1 | /* === S Y N F I G ========================================================= */ |
---|
2 | /*! \file renderer_canvas.cpp |
---|
3 | ** \brief Template File |
---|
4 | ** |
---|
5 | ** $Id$ |
---|
6 | ** |
---|
7 | ** \legal |
---|
8 | ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley |
---|
9 | ** Copyright (c) 2007, 2008 Chris Moore |
---|
10 | ** Copyright (c) 2011 Nikita Kitaev |
---|
11 | ** |
---|
12 | ** This package is free software; you can redistribute it and/or |
---|
13 | ** modify it under the terms of the GNU General Public License as |
---|
14 | ** published by the Free Software Foundation; either version 2 of |
---|
15 | ** the License, or (at your option) any later version. |
---|
16 | ** |
---|
17 | ** This package is distributed in the hope that it will be useful, |
---|
18 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
19 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
20 | ** General Public License for more details. |
---|
21 | ** \endlegal |
---|
22 | */ |
---|
23 | /* ========================================================================= */ |
---|
24 | |
---|
25 | /* === H E A D E R S ======================================================= */ |
---|
26 | |
---|
27 | #ifdef USING_PCH |
---|
28 | # include "pch.h" |
---|
29 | #else |
---|
30 | #ifdef HAVE_CONFIG_H |
---|
31 | # include <config.h> |
---|
32 | #endif |
---|
33 | |
---|
34 | #include "renderer_canvas.h" |
---|
35 | #include <ETL/misc> |
---|
36 | #include <gdkmm/general.h> |
---|
37 | |
---|
38 | #include "general.h" |
---|
39 | #include "app.h" |
---|
40 | |
---|
41 | #endif |
---|
42 | |
---|
43 | /* === U S I N G =========================================================== */ |
---|
44 | |
---|
45 | using namespace std; |
---|
46 | using namespace etl; |
---|
47 | using namespace synfig; |
---|
48 | using namespace studio; |
---|
49 | |
---|
50 | /* === M A C R O S ========================================================= */ |
---|
51 | |
---|
52 | /* === G L O B A L S ======================================================= */ |
---|
53 | |
---|
54 | /* === P R O C E D U R E S ================================================= */ |
---|
55 | |
---|
56 | /* === M E T H O D S ======================================================= */ |
---|
57 | |
---|
58 | Renderer_Canvas::~Renderer_Canvas() |
---|
59 | { |
---|
60 | } |
---|
61 | std::vector< std::pair<Glib::RefPtr<Gdk::Pixbuf>,int> >& |
---|
62 | Renderer_Canvas::get_tile_book() |
---|
63 | { |
---|
64 | return get_work_area()->get_tile_book(); |
---|
65 | } |
---|
66 | |
---|
67 | studio::WorkArea::SurfaceBook& |
---|
68 | Renderer_Canvas::get_cairo_book() |
---|
69 | { |
---|
70 | return get_work_area()->get_cairo_book(); |
---|
71 | } |
---|
72 | |
---|
73 | bool |
---|
74 | Renderer_Canvas::get_full_frame()const |
---|
75 | { |
---|
76 | return get_work_area()->get_full_frame(); |
---|
77 | } |
---|
78 | |
---|
79 | int Renderer_Canvas::get_refreshes()const |
---|
80 | { |
---|
81 | return get_work_area()->get_refreshes(); |
---|
82 | } |
---|
83 | |
---|
84 | bool |
---|
85 | Renderer_Canvas::get_canceled()const |
---|
86 | { |
---|
87 | return get_work_area()->get_canceled(); |
---|
88 | } |
---|
89 | |
---|
90 | bool |
---|
91 | Renderer_Canvas::get_queued()const |
---|
92 | { |
---|
93 | return get_work_area()->get_queued(); |
---|
94 | } |
---|
95 | |
---|
96 | bool |
---|
97 | Renderer_Canvas::get_rendering()const |
---|
98 | { |
---|
99 | return get_work_area()->get_rendering(); |
---|
100 | } |
---|
101 | |
---|
102 | void |
---|
103 | Renderer_Canvas::render_vfunc( |
---|
104 | const Glib::RefPtr<Gdk::Window>& drawable, |
---|
105 | const Gdk::Rectangle& /*expose_area*/ |
---|
106 | ) |
---|
107 | { |
---|
108 | assert(get_work_area()); |
---|
109 | if(!get_work_area()) |
---|
110 | return; |
---|
111 | |
---|
112 | // const synfig::RendDesc &rend_desc(get_work_area()->get_canvas()->rend_desc()); |
---|
113 | |
---|
114 | const synfig::Vector focus_point(get_work_area()->get_focus_point()); |
---|
115 | |
---|
116 | std::vector< std::pair<Glib::RefPtr<Gdk::Pixbuf>,int> >& tile_book(get_tile_book()); |
---|
117 | WorkArea::SurfaceBook& cairo_book(get_cairo_book()); |
---|
118 | |
---|
119 | int drawable_w = drawable->get_width(); |
---|
120 | int drawable_h = drawable->get_height(); |
---|
121 | |
---|
122 | // Calculate the window coordinates of the top-left |
---|
123 | // corner of the canvas. |
---|
124 | const synfig::Vector::value_type |
---|
125 | x(focus_point[0]/get_pw()+drawable_w/2-get_w()/2), |
---|
126 | y(focus_point[1]/get_ph()+drawable_h/2-get_h()/2); |
---|
127 | |
---|
128 | /*const synfig::Vector::value_type window_startx(window_tl[0]); |
---|
129 | const synfig::Vector::value_type window_endx(window_br[0]); |
---|
130 | const synfig::Vector::value_type window_starty(window_tl[1]); |
---|
131 | const synfig::Vector::value_type window_endy(window_br[1]); |
---|
132 | */ |
---|
133 | const int |
---|
134 | tile_w(get_work_area()->get_tile_w()), |
---|
135 | tile_h(get_work_area()->get_tile_h()); |
---|
136 | |
---|
137 | const int |
---|
138 | w(get_w()), |
---|
139 | h(get_h()); |
---|
140 | |
---|
141 | Cairo::RefPtr<Cairo::Context> cr = drawable->create_cairo_context(); |
---|
142 | if(studio::App::workarea_uses_cairo) |
---|
143 | { |
---|
144 | if(!cairo_book.empty()) |
---|
145 | { |
---|
146 | if(get_full_frame()) |
---|
147 | { |
---|
148 | if(cairo_book[0].surface) |
---|
149 | { |
---|
150 | int div; |
---|
151 | cr->save(); |
---|
152 | if(get_work_area()->get_low_resolution_flag()) |
---|
153 | { |
---|
154 | div = get_work_area()->get_low_res_pixel_size(); |
---|
155 | cr->scale(div, div); |
---|
156 | } |
---|
157 | else |
---|
158 | div=1; |
---|
159 | cairo_set_source_surface(cr->cobj(), cairo_book[0].surface, round_to_int(x)/div, round_to_int(y)/div); |
---|
160 | cairo_pattern_set_filter(cairo_get_source(cr->cobj()), CAIRO_FILTER_NEAREST); |
---|
161 | cr->paint(); |
---|
162 | cr->restore(); |
---|
163 | } |
---|
164 | |
---|
165 | if(cairo_book[0].refreshes!=get_refreshes() && get_canceled()==false && get_rendering()==false && get_queued()==false) |
---|
166 | get_work_area()->async_update_preview(); |
---|
167 | } |
---|
168 | else // tiled frame |
---|
169 | { |
---|
170 | int div= get_work_area()->get_low_res_pixel_size();; |
---|
171 | |
---|
172 | const int width_in_tiles(w/tile_w+(((get_work_area()->get_low_resolution_flag())?((w/div)%(tile_w/div)):(w%tile_w))?1:0)); |
---|
173 | const int height_in_tiles(h/tile_h+(h%tile_h?1:0)); |
---|
174 | |
---|
175 | int u(0),v(0),tx,ty; |
---|
176 | int u1(0),v1(0),u2(width_in_tiles), v2(height_in_tiles); |
---|
177 | |
---|
178 | bool needs_refresh(false); |
---|
179 | |
---|
180 | u1=int(-x/tile_w); |
---|
181 | v1=int(-y/tile_h); |
---|
182 | u2=int((-x+drawable_w)/tile_w+1); |
---|
183 | v2=int((-y+drawable_h)/tile_h+1); |
---|
184 | if(u2>width_in_tiles)u2=width_in_tiles; |
---|
185 | if(v2>height_in_tiles)v2=height_in_tiles; |
---|
186 | if(u1<0)u1=0; |
---|
187 | if(v1<0)v1=0; |
---|
188 | |
---|
189 | for(v=v1;v<v2;v++) |
---|
190 | { |
---|
191 | for(u=u1;u<u2;u++) |
---|
192 | { |
---|
193 | int index=v*width_in_tiles+u; |
---|
194 | if(int(cairo_book.size())>index && cairo_book[index].surface) |
---|
195 | { |
---|
196 | cr->save(); |
---|
197 | if(get_work_area()->get_low_resolution_flag()) |
---|
198 | { |
---|
199 | div = get_work_area()->get_low_res_pixel_size(); |
---|
200 | cr->scale(div, div); |
---|
201 | } |
---|
202 | else |
---|
203 | div=1; |
---|
204 | |
---|
205 | tx=u*tile_w; |
---|
206 | ty=v*tile_w; // not tile_h? |
---|
207 | |
---|
208 | cairo_set_source_surface(cr->cobj(), cairo_book[index].surface, (round_to_int(x)+tx)/div, (round_to_int(y)+ty)/div); |
---|
209 | cairo_pattern_set_filter(cairo_get_source(cr->cobj()), CAIRO_FILTER_NEAREST); |
---|
210 | cr->paint(); |
---|
211 | cr->restore(); |
---|
212 | } |
---|
213 | if(cairo_book[index].refreshes!=get_refreshes()) |
---|
214 | needs_refresh=true; |
---|
215 | } |
---|
216 | } |
---|
217 | if(needs_refresh==true && get_canceled()==false && get_rendering()==false && get_queued()==false) |
---|
218 | { |
---|
219 | get_work_area()->async_update_preview(); |
---|
220 | } |
---|
221 | |
---|
222 | } |
---|
223 | } |
---|
224 | } |
---|
225 | |
---|
226 | else if(!tile_book.empty()) |
---|
227 | { |
---|
228 | if(get_full_frame()) |
---|
229 | { |
---|
230 | if(tile_book[0].first) |
---|
231 | { |
---|
232 | cr->save(); |
---|
233 | Gdk::Cairo::set_source_pixbuf( |
---|
234 | cr, //cairo context |
---|
235 | tile_book[0].first, //pixbuf |
---|
236 | round_to_int(x), round_to_int(y) //coordinates to place upper left corner of pixbuf |
---|
237 | ); |
---|
238 | cr->paint(); |
---|
239 | cr->restore(); |
---|
240 | /* |
---|
241 | drawable->draw_pixbuf( |
---|
242 | gc, //GC |
---|
243 | tile_book[0].first, //pixbuf |
---|
244 | 0, 0, // Source X and Y |
---|
245 | round_to_int(x),round_to_int(y), // Dest X and Y |
---|
246 | -1,-1, // Width and Height |
---|
247 | Gdk::RGB_DITHER_MAX, // RgbDither |
---|
248 | 2, 2 // Dither offset X and Y |
---|
249 | ); |
---|
250 | */ |
---|
251 | } |
---|
252 | if(tile_book[0].second!=get_refreshes() && get_canceled()==false && get_rendering()==false && get_queued()==false) |
---|
253 | get_work_area()->async_update_preview(); |
---|
254 | } |
---|
255 | else |
---|
256 | { |
---|
257 | int div = get_work_area()->get_low_res_pixel_size(); |
---|
258 | const int width_in_tiles(w/tile_w+(((get_work_area()->get_low_resolution_flag())?((w/div)%(tile_w/div)):(w%tile_w))?1:0)); |
---|
259 | const int height_in_tiles(h/tile_h+(h%tile_h?1:0)); |
---|
260 | |
---|
261 | int u(0),v(0),tx,ty; |
---|
262 | int u1(0),v1(0),u2(width_in_tiles), v2(height_in_tiles); |
---|
263 | |
---|
264 | bool needs_refresh(false); |
---|
265 | |
---|
266 | u1=int(-x/tile_w); |
---|
267 | v1=int(-y/tile_h); |
---|
268 | u2=int((-x+drawable_w)/tile_w+1); |
---|
269 | v2=int((-y+drawable_h)/tile_h+1); |
---|
270 | if(u2>width_in_tiles)u2=width_in_tiles; |
---|
271 | if(v2>height_in_tiles)v2=height_in_tiles; |
---|
272 | if(u1<0)u1=0; |
---|
273 | if(v1<0)v1=0; |
---|
274 | |
---|
275 | for(v=v1;v<v2;v++) |
---|
276 | { |
---|
277 | for(u=u1;u<u2;u++) |
---|
278 | { |
---|
279 | int index=v*width_in_tiles+u; |
---|
280 | if(int(tile_book.size())>index && tile_book[index].first) |
---|
281 | { |
---|
282 | tx=u*tile_w; |
---|
283 | ty=v*tile_w; |
---|
284 | |
---|
285 | cr->save(); |
---|
286 | Gdk::Cairo::set_source_pixbuf( |
---|
287 | cr, //cairo context |
---|
288 | tile_book[index].first, //pixbuf |
---|
289 | round_to_int(x)+tx, round_to_int(y)+ty //coordinates to place upper left corner of pixbuf |
---|
290 | ); |
---|
291 | cr->paint(); |
---|
292 | cr->restore(); |
---|
293 | /* |
---|
294 | |
---|
295 | drawable->draw_pixbuf( |
---|
296 | gc, //GC |
---|
297 | tile_book[index].first, //pixbuf |
---|
298 | 0, 0, // Source X and Y |
---|
299 | round_to_int(x)+tx,round_to_int(y)+ty, // Dest X and Y |
---|
300 | -1,-1, // Width and Height |
---|
301 | Gdk::RGB_DITHER_MAX, // RgbDither |
---|
302 | 2, 2 // Dither offset X and Y |
---|
303 | ); |
---|
304 | */ |
---|
305 | } |
---|
306 | if(tile_book[index].second!=get_refreshes()) |
---|
307 | needs_refresh=true; |
---|
308 | } |
---|
309 | } |
---|
310 | if(needs_refresh==true && get_canceled()==false && get_rendering()==false && get_queued()==false) |
---|
311 | { |
---|
312 | //queue_render_preview(); |
---|
313 | get_work_area()->async_update_preview(); |
---|
314 | //update_preview(); |
---|
315 | //return true; |
---|
316 | } |
---|
317 | |
---|
318 | } |
---|
319 | } |
---|
320 | |
---|
321 | // Draw the border around the rendered region |
---|
322 | { |
---|
323 | cr->save(); |
---|
324 | |
---|
325 | cr->set_line_cap(Cairo::LINE_CAP_BUTT); |
---|
326 | cr->set_line_join(Cairo::LINE_JOIN_MITER); |
---|
327 | cr->set_antialias(Cairo::ANTIALIAS_NONE); |
---|
328 | |
---|
329 | cr->set_line_width(1.0); |
---|
330 | cr->set_source_rgb(0,0,0); |
---|
331 | |
---|
332 | cr->rectangle( |
---|
333 | round_to_int(x), round_to_int(y), |
---|
334 | w, h |
---|
335 | ); |
---|
336 | |
---|
337 | cr->stroke(); |
---|
338 | |
---|
339 | cr->restore(); |
---|
340 | } |
---|
341 | } |
---|