1 /*$
2 Copyright (C) 2016-2020 Azel.
3
4 This file is part of AzPainterB.
5
6 AzPainterB is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 AzPainterB is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 $*/
19
20 /*****************************************
21 * DrawData
22 *
23 * 更新関連
24 *****************************************/
25
26 #include "mDef.h"
27 #include "mWindowDef.h"
28 #include "mWidget.h"
29 #include "mPixbuf.h"
30 #include "mRectBox.h"
31
32 #include "defConfig.h"
33 #include "defDraw.h"
34 #include "defWidgets.h"
35 #include "defGridData.h"
36
37 #include "draw_op_def.h"
38 #include "draw_main.h"
39 #include "draw_calc.h"
40
41 #include "LayerList.h"
42 #include "LayerItem.h"
43 #include "TileImage.h"
44 #include "ImageBuf24.h"
45 #include "PixbufDraw.h"
46
47 #include "Docks_external.h"
48
49
50
51 /** キャンバスエリアを更新 */
52
drawUpdate_canvasArea()53 void drawUpdate_canvasArea()
54 {
55 mWidgetUpdate(M_WIDGET(APP_WIDGETS->canvas_area));
56 }
57
58 /** すべて更新
59 *
60 * [ 合成イメージ、キャンバスエリア、(Dock)キャンバスビュー ] */
61
drawUpdate_all()62 void drawUpdate_all()
63 {
64 drawUpdate_blendImage_full(APP_DRAW);
65 drawUpdate_canvasArea();
66
67 DockCanvasView_update();
68 }
69
70 /** 全体 + レイヤ一覧を更新 */
71
drawUpdate_all_layer()72 void drawUpdate_all_layer()
73 {
74 drawUpdate_all();
75
76 DockLayer_update_all();
77 }
78
79 /** 合成イメージを全体更新
80 *
81 * 背景とレイヤイメージ */
82
drawUpdate_blendImage_full(DrawData * p)83 void drawUpdate_blendImage_full(DrawData *p)
84 {
85 mBox box;
86
87 box.x = box.y = 0;
88 box.w = p->imgw, box.h = p->imgh;
89
90 //背景
91
92 if(APP_CONF->fView & CONFIG_VIEW_F_BKGND_PLAID)
93 {
94 ImageBuf24_fillPlaid_box(p->blendimg, &box,
95 APP_CONF->colBkgndPlaid[0], APP_CONF->colBkgndPlaid[1]);
96 }
97 else
98 ImageBuf24_fillWhite(p->blendimg);
99
100 //合成
101
102 drawUpdate_blendImage_layer(p, &box);
103 }
104
105 /** 合成イメージ:レイヤイメージを範囲更新
106 *
107 * [!] 背景は描画しない */
108
drawUpdate_blendImage_layer(DrawData * p,mBox * box)109 void drawUpdate_blendImage_layer(DrawData *p,mBox *box)
110 {
111 LayerItem *pi;
112 int opacity,mode;
113
114 mode = p->sel.mode;
115
116 pi = LayerList_getItem_bottomVisibleImage(p->layerlist);
117
118 if(mode == DRAW_SELMODE_MOVECOPY_PASTE
119 || mode == DRAW_SELMODE_SELECT_PASTE)
120 {
121 //----- 貼付けモード時
122
123 for(; pi; pi = LayerItem_getPrevVisibleImage(pi))
124 {
125 opacity = LayerItem_getOpacity_real(pi);
126
127 TileImage_blendToImage24_rgba(pi->img, p->blendimg,
128 box, opacity, pi->blendmode);
129
130 //貼付けイメージをカレントの上に挿入
131
132 if(pi == p->curlayer)
133 {
134 TileImage_blendToImage24_rgba(
135 (mode == DRAW_SELMODE_SELECT_PASTE)? p->sel.img_selcopy: p->sel.img_movecopy,
136 p->blendimg, box, opacity, pi->blendmode);
137 }
138 }
139
140 //カレントがフォルダの場合は表示されないので、最後に
141
142 if(!p->curlayer->img)
143 {
144 TileImage_blendToImage24_rgba(
145 (mode == DRAW_SELMODE_SELECT_PASTE)? p->sel.img_selcopy: p->sel.img_movecopy,
146 p->blendimg, box, 128, 0);
147 }
148 }
149 else if(p->drawtext.in_dialog
150 && (p->drawtext.flags & DRAW_DRAWTEXT_F_PREVIEW))
151 {
152 //----- テキスト描画、ダイアログ中のプレビュー
153
154 for(; pi; pi = LayerItem_getPrevVisibleImage(pi))
155 {
156 opacity = LayerItem_getOpacity_real(pi);
157
158 TileImage_blendToImage24_rgba(pi->img, p->blendimg,
159 box, opacity, pi->blendmode);
160
161 //プレビューイメージを挿入
162
163 if(pi == p->curlayer)
164 {
165 TileImage_blendToImage24_rgba(p->tileimgTmp,
166 p->blendimg, box, opacity, pi->blendmode);
167 }
168 }
169 }
170 else
171 {
172 //----- 通常時
173
174 for(; pi; pi = LayerItem_getPrevVisibleImage(pi))
175 {
176 TileImage_blendToImage24_rgba(pi->img, p->blendimg,
177 box, LayerItem_getOpacity_real(pi), pi->blendmode);
178 }
179 }
180 }
181
182 /** キャンバスを描画
183 *
184 * 合成イメージをソースとして mPixbuf に描画。
185 *
186 * @param pixbuf 描画対象のキャンバスエリアの mPixbuf
187 * @param box NULL で全体 */
188
drawUpdate_drawCanvas(DrawData * p,mPixbuf * pixbuf,mBox * box)189 void drawUpdate_drawCanvas(DrawData *p,mPixbuf *pixbuf,mBox *box)
190 {
191 CanvasDrawInfo di;
192 mBox boximg;
193 mRect rc;
194 int n;
195
196 //描画情報
197
198 if(box)
199 di.boxdst = *box;
200 else
201 {
202 di.boxdst.x = di.boxdst.y = 0;
203 di.boxdst.w = p->szCanvas.w;
204 di.boxdst.h = p->szCanvas.h;
205 }
206
207 di.originx = p->imgoriginX;
208 di.originy = p->imgoriginY;
209 di.scrollx = p->ptScroll.x - (p->szCanvas.w >> 1);
210 di.scrolly = p->ptScroll.y - (p->szCanvas.h >> 1);
211 di.mirror = p->canvas_mirror;
212 di.imgw = p->imgw;
213 di.imgh = p->imgh;
214 di.bkgndcol = APP_CONF->colCanvasBkgnd;
215 di.param = &p->viewparam;
216
217 //------ 描画
218
219 if(p->canvas_angle)
220 {
221 //回転あり
222
223 n = p->canvas_angle;
224
225 if(p->bCanvasLowQuality
226 || (p->canvas_zoom == 1000 && (n == 9000 || n == 18000 || n == 27000)))
227 //キャンバス移動中、または90 度単位 (倍率100%) の場合は低品質
228 ImageBuf24_drawMainCanvas_rotate_normal(p->blendimg, pixbuf, &di);
229 else
230 ImageBuf24_drawMainCanvas_rotate_oversamp(p->blendimg, pixbuf, &di);
231 }
232 else
233 {
234 //回転なし (200%以下 [!] 100%は除く 時は高品質で)
235
236 if(!p->bCanvasLowQuality && p->canvas_zoom != 1000 && p->canvas_zoom < 2000)
237 ImageBuf24_drawMainCanvas_oversamp(p->blendimg, pixbuf, &di);
238 else
239 ImageBuf24_drawMainCanvas_nearest(p->blendimg, pixbuf, &di);
240 }
241
242 //------ グリッド
243
244 if((APP_CONF->fView & CONFIG_VIEW_F_GRID)
245 && drawCalc_areaToimage_box(p, &boximg, &di.boxdst))
246 {
247 GridListData *pi;
248
249 //リストで上にあるものほど前面にしたいので、後ろから描画
250
251 for(pi = (GridListData *)APP_CONF->grid_list.bottom; pi; pi = (GridListData *)pi->i.prev)
252 {
253 n = pi->flags;
254
255 if(n & GRIDDATA_F_ON)
256 {
257 //表示倍率条件
258
259 if((n & GRIDDATA_F_HAVE_ZOOM)
260 && (p->canvas_zoom < pi->zoom_min || p->canvas_zoom > pi->zoom_max))
261 continue;
262
263 //範囲
264
265 if(n & GRIDDATA_F_HAVE_AREA)
266 {
267 rc.x1 = pi->area[0], rc.y1 = pi->area[1];
268 rc.x2 = pi->area[2], rc.y2 = pi->area[3];
269
270 //始点がイメージの範囲外なら表示しない
271
272 if(rc.x1 >= p->imgw || rc.y1 >= p->imgh)
273 continue;
274
275 //イメージの範囲内に収める
276
277 if(rc.x2 > p->imgw) rc.x2 = p->imgw;
278 if(rc.y2 > p->imgh) rc.y2 = p->imgh;
279 }
280
281 //描画
282
283 pixbufDrawGrid(pixbuf, &di.boxdst, &boximg,
284 pi->w, pi->h, pi->col,
285 (n & GRIDDATA_F_HAVE_AREA)? &rc: NULL, &di);
286 }
287 }
288 }
289
290 //------ 選択範囲
291
292 if(p->sel.boxsel.w)
293 pixbufDrawSelectBox(pixbuf, &p->sel.boxsel, &di);
294 }
295
296 /** 合成イメージの範囲更新
297 *
298 * @param boximg イメージ範囲内であること */
299
drawUpdate_rect_blendimg(DrawData * p,mBox * boximg)300 void drawUpdate_rect_blendimg(DrawData *p,mBox *boximg)
301 {
302 //背景
303
304 if(APP_CONF->fView & CONFIG_VIEW_F_BKGND_PLAID)
305 {
306 ImageBuf24_fillPlaid_box(p->blendimg, boximg,
307 APP_CONF->colBkgndPlaid[0], APP_CONF->colBkgndPlaid[1]);
308 }
309 else
310 ImageBuf24_fillBox(p->blendimg, boximg, 0xffffff);
311
312 //レイヤ
313
314 drawUpdate_blendImage_layer(p, boximg);
315 }
316
317 /** キャンバスエリアの範囲更新 */
318
drawUpdate_rect_canvas(DrawData * p,mBox * boximg)319 void drawUpdate_rect_canvas(DrawData *p,mBox *boximg)
320 {
321 mBox boxc;
322 mWidget *wgarea;
323 mPixbuf *pixbuf;
324
325 wgarea = M_WIDGET(APP_WIDGETS->canvas_area);
326
327 if(drawCalc_imageToarea_box(p, &boxc, boximg))
328 {
329 //キャンバス描画
330
331 pixbuf = mWidgetBeginDirectDraw(wgarea);
332
333 if(pixbuf)
334 {
335 drawUpdate_drawCanvas(p, pixbuf, &boxc);
336
337 //[debug]
338 //mPixbufBox(pixbuf, boxc.x, boxc.y, boxc.w, boxc.h, 0xff0000);
339
340 mWidgetEndDirectDraw(wgarea, pixbuf);
341
342 //ウィンドウ更新
343
344 mWidgetUpdateBox_box(wgarea, &boxc);
345 }
346 }
347 }
348
349
350 //===========================
351 // 範囲更新
352 //===========================
353
354
355 /** 範囲更新 (合成イメージ + キャンバスエリア)
356 *
357 * @param boximg イメージ範囲内であること */
358
drawUpdate_rect_imgcanvas(DrawData * p,mBox * boximg)359 void drawUpdate_rect_imgcanvas(DrawData *p,mBox *boximg)
360 {
361 //合成イメージ
362
363 drawUpdate_rect_blendimg(p, boximg);
364
365 //キャンバス
366
367 drawUpdate_rect_canvas(p, boximg);
368 }
369
370 /** 範囲更新、選択範囲用
371 *
372 * 選択範囲がイメージの範囲外でも表示されるように。
373 *
374 * @param rc NULL で現在の選択範囲 */
375
drawUpdate_rect_imgcanvas_forSelect(DrawData * p,mRect * rc)376 void drawUpdate_rect_imgcanvas_forSelect(DrawData *p,mRect *rc)
377 {
378 mBox box;
379 mRect rc2;
380
381 if(rc)
382 rc2 = *rc;
383 else
384 mRectSetByBox(&rc2, &p->sel.boxsel);
385
386 //合成イメージ
387
388 if(drawCalc_getImageBox_rect(p, &box, &rc2))
389 drawUpdate_rect_blendimg(p, &box);
390
391 //キャンバス
392
393 mBoxSetByRect(&box, &rc2);
394
395 box.x -= 2;
396 box.y -= 2;
397 box.w += 4;
398 box.h += 4;
399
400 drawUpdate_rect_canvas(p, &box);
401 }
402
403 /** 選択範囲のキャンバス領域を更新
404 *
405 * @param box NULL で現在の選択範囲 */
406
drawUpdate_rect_canvas_select(DrawData * p,mBox * box)407 void drawUpdate_rect_canvas_select(DrawData *p,mBox *box)
408 {
409 mBox boxu;
410
411 if(box)
412 boxu = *box;
413 else
414 boxu = p->sel.boxsel;
415
416 //1px 拡張して表示しているので、更新範囲を拡張
417
418 boxu.x -= 2;
419 boxu.y -= 2;
420 boxu.w += 4;
421 boxu.h += 4;
422
423 drawUpdate_rect_canvas(p, &boxu);
424 }
425
426 /** 範囲更新 (mRect)
427 *
428 * @param rc イメージ範囲 */
429
drawUpdate_rect_imgcanvas_fromRect(DrawData * p,mRect * rc)430 void drawUpdate_rect_imgcanvas_fromRect(DrawData *p,mRect *rc)
431 {
432 mBox box;
433
434 if(drawCalc_getImageBox_rect(p, &box, rc))
435 drawUpdate_rect_imgcanvas(p, &box);
436 }
437
438 /** 範囲更新 + [dock]キャンバスビュー */
439
drawUpdate_rect_imgcanvas_canvasview_fromRect(DrawData * p,mRect * rc)440 void drawUpdate_rect_imgcanvas_canvasview_fromRect(DrawData *p,mRect *rc)
441 {
442 mBox box;
443
444 if(drawCalc_getImageBox_rect(p, &box, rc))
445 {
446 drawUpdate_rect_imgcanvas(p, &box);
447
448 DockCanvasView_updateRect(&box);
449 }
450 }
451
452 /** 範囲更新 + [dock]キャンバスビュー (レイヤの表示イメージ部分)
453 *
454 * フォルダの場合、フォルダ下の全ての表示レイヤの範囲。
455 *
456 * @param item NULL でカレントレイヤ */
457
drawUpdate_rect_imgcanvas_canvasview_inLayerHave(DrawData * p,LayerItem * item)458 void drawUpdate_rect_imgcanvas_canvasview_inLayerHave(DrawData *p,LayerItem *item)
459 {
460 mRect rc;
461
462 if(!item) item = p->curlayer;
463
464 if(LayerItem_getVisibleImageRect(item, &rc))
465 drawUpdate_rect_imgcanvas_canvasview_fromRect(p, &rc);
466 }
467
468 /** [dock]キャンバスビューのみ更新 (mRect) */
469
drawUpdate_canvasview(DrawData * p,mRect * rc)470 void drawUpdate_canvasview(DrawData *p,mRect *rc)
471 {
472 mBox box;
473
474 if(drawCalc_getImageBox_rect(p, &box, rc))
475 DockCanvasView_updateRect(&box);
476 }
477
478 /** [dock]キャンバスビューがルーペ時、更新
479 *
480 * ドットペンの押し時など、カーソルが移動されていない状態でイメージが更新されたときに使う。 */
481
drawUpdate_canvasview_inLoupe()482 void drawUpdate_canvasview_inLoupe()
483 {
484 if(APP_CONF->canvasview_flags & CONFIG_CANVASVIEW_F_LOUPE_MODE)
485 DockCanvasView_update();
486 }
487
488 /** 描画終了時の範囲更新
489 *
490 * @param boximg イメージ範囲。x < 0 で範囲なし */
491
drawUpdate_endDraw_box(DrawData * p,mBox * boximg)492 void drawUpdate_endDraw_box(DrawData *p,mBox *boximg)
493 {
494 //[Dock]キャンバスビュー
495
496 if(boximg->x >= 0)
497 DockCanvasView_updateRect(boximg);
498 }
499