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 * 操作 - いろいろ1
24 *****************************************/
25 /*
26 * 図形塗りつぶし、塗りつぶし、グラデーション、移動ツール、テキスト
27 * キャンバス移動、キャンバス回転、上下ドラッグキャンバス倍率変更
28 * スポイト、中間色作成、色置き換え
29 */
30
31
32 #include <math.h>
33
34 #include "mDef.h"
35 #include "mRectBox.h"
36 #include "mNanoTime.h"
37 #include "mFont.h"
38 #include "mStr.h"
39
40 #include "defDraw.h"
41 #include "defWidgets.h"
42
43 #include "draw_main.h"
44 #include "draw_calc.h"
45 #include "draw_op_def.h"
46 #include "draw_op_sub.h"
47 #include "draw_op_func.h"
48
49 #include "macroToolOpt.h"
50
51 #include "TileImage.h"
52 #include "TileImageDrawInfo.h"
53 #include "LayerItem.h"
54 #include "LayerList.h"
55
56 #include "FillPolygon.h"
57 #include "DrawFill.h"
58 #include "Undo.h"
59 #include "DrawFont.h"
60
61 #include "AppCursor.h"
62 #include "MainWinCanvas.h"
63 #include "Docks_external.h"
64
65
66 //----------------
67
68 mBool DrawTextDlg_run(mWindow *owner);
69
70 //----------------
71
72
73 //==============================
74 // 共通
75 //==============================
76
77
78 /** 離し : キャンバス状態変更用 */
79
_common_release_canvas(DrawData * p)80 static mBool _common_release_canvas(DrawData *p)
81 {
82 MainWinCanvasArea_clearTimer_updateArea();
83
84 drawCanvas_normalQuality();
85 drawUpdate_canvasArea();
86
87 return TRUE;
88 }
89
90 /** 離し : グラブ解除しない */
91
drawOp_common_norelease(DrawData * p)92 mBool drawOp_common_norelease(DrawData *p)
93 {
94 return FALSE;
95 }
96
97
98
99 //=================================
100 // 描画
101 //=================================
102
103
104
105 /** 四角形塗りつぶし描画 (イメージに対する)
106 *
107 * 描画系ツールでの描画タイプ時 or 図形塗りでグリッド吸着時。 */
108
drawOpDraw_fillBox_forImage(DrawData * p)109 void drawOpDraw_fillBox_forImage(DrawData *p)
110 {
111 drawOpSub_setDrawInfo(p, p->w.optoolno, -1);
112 drawOpSub_beginDraw_single(p);
113
114 TileImage_drawFillBox(p->w.dstimg, p->w.boxtmp[0].x, p->w.boxtmp[0].y,
115 p->w.boxtmp[0].w, p->w.boxtmp[0].h, &p->w.pixdraw);
116
117 drawOpSub_endDraw_single(p);
118 }
119
120 /** 四角形塗りつぶし描画 (領域に対する)
121 *
122 * 図形塗りの通常時。 */
123
drawOpDraw_fillBox_forArea(DrawData * p)124 void drawOpDraw_fillBox_forArea(DrawData *p)
125 {
126 if(p->canvas_angle == 0)
127 {
128 //キャンバス回転無しの場合
129
130 mBox box;
131
132 drawOpSub_getDrawBox_noangle(p, &box);
133
134 drawOpSub_setDrawInfo(p, p->w.optoolno, 0);
135 drawOpSub_beginDraw_single(p);
136
137 TileImage_drawFillBox(p->w.dstimg, box.x, box.y, box.w, box.h, &p->w.pixdraw);
138
139 drawOpSub_endDraw_single(p);
140 }
141 else
142 {
143 //キャンバス回転ありの場合、多角形で
144
145 mDoublePoint pt[4];
146 int i;
147
148 drawOpSub_getDrawBoxPoints(p, pt, FALSE);
149
150 if((p->w.fillpolygon = FillPolygon_new()))
151 {
152 for(i = 0; i < 4; i++)
153 FillPolygon_addPoint(p->w.fillpolygon, pt[i].x, pt[i].y);
154
155 if(FillPolygon_closePoint(p->w.fillpolygon))
156 drawOpDraw_fillPolygon(p);
157
158 drawOpSub_freeFillPolygon(p);
159 }
160 }
161 }
162
163 /** 楕円塗りつぶし */
164
drawOpDraw_fillEllipse(DrawData * p,mBool draw_dot)165 void drawOpDraw_fillEllipse(DrawData *p,mBool draw_dot)
166 {
167 mDoublePoint pt,pt_r;
168
169 if(!draw_dot)
170 drawOpSub_getDrawEllipseParam(p, &pt, &pt_r, FALSE);
171
172 //描画
173 /* ntmp[0] : アンチエイリアスか */
174
175 drawOpSub_setDrawInfo(p, p->w.optoolno, 0);
176 drawOpSub_beginDraw_single(p);
177
178 if(draw_dot)
179 {
180 g_tileimage_dinfo.funcDrawPixel = TileImage_setPixel_draw_stroke;
181
182 TileImage_drawFillEllipse_dot(p->w.dstimg,
183 p->w.rctmp[0].x1, p->w.rctmp[0].y1,
184 p->w.rctmp[0].x2, p->w.rctmp[0].y2,
185 &p->w.pixdraw);
186 }
187 else
188 {
189 TileImage_drawFillEllipse(p->w.dstimg,
190 pt.x, pt.y, pt_r.x, pt_r.y,
191 &p->w.pixdraw, p->w.ntmp[0],
192 &p->viewparam, p->canvas_mirror);
193 }
194
195 drawOpSub_endDraw_single(p);
196 }
197
198 /** 多角形/投げ縄 塗りつぶし */
199
drawOpDraw_fillPolygon(DrawData * p)200 void drawOpDraw_fillPolygon(DrawData *p)
201 {
202 int aa;
203
204 drawOpSub_setDrawInfo(p, p->w.optoolno, -1);
205
206 //アンチエイリアスか
207 /* 図形塗り/ブラシ系時は ntmp[0] に指定されている */
208
209 if(drawOpSub_isDotPenDraw())
210 aa = FALSE;
211 else
212 aa = p->w.ntmp[0];
213
214 //描画
215
216 drawOpSub_beginDraw_single(p);
217
218 TileImage_drawFillPolygon(p->w.dstimg, p->w.fillpolygon,
219 &p->w.pixdraw, aa);
220
221 drawOpSub_endDraw_single(p);
222 }
223
224 /** グラデーション描画 */
225
drawOpDraw_gradation(DrawData * p)226 void drawOpDraw_gradation(DrawData *p)
227 {
228 TileImageDrawGradInfo info;
229 void (*drawfunc[4])(TileImage *,int,int,int,int,TileImageDrawGradInfo *) = {
230 TileImage_drawGradation_line, TileImage_drawGradation_circle,
231 TileImage_drawGradation_box, TileImage_drawGradation_radial
232 };
233
234 //情報
235
236 drawOpSub_setDrawGradationInfo(&info);
237
238 //描画
239
240 drawOpSub_setDrawInfo(p, TOOL_GRADATION, 0);
241 drawOpSub_beginDraw_single(p);
242
243 (drawfunc[p->tool.subno[TOOL_GRADATION]])(p->w.dstimg,
244 p->w.pttmp[0].x, p->w.pttmp[0].y,
245 p->w.pttmp[1].x, p->w.pttmp[1].y, &info);
246
247 drawOpSub_endDraw_single(p);
248 }
249
250
251
252 //=================================
253 // 塗りつぶし
254 //=================================
255
256
257 /** 離し */
258
_fill_release(DrawData * p)259 static mBool _fill_release(DrawData *p)
260 {
261 DrawFill *draw;
262 LayerItem *item;
263 mPoint pt;
264 int type,diff,opacity;
265 uint32_t val;
266 mBool disable_ref;
267
268 //設定値
269
270 if(p->w.optoolno == TOOL_FILL)
271 {
272 //通常塗りつぶし
273
274 val = p->tool.opt_fill;
275
276 type = FILL_GET_TYPE(val);
277 diff = FILL_GET_COLOR_DIFF(val);
278 opacity = FILL_GET_OPACITY(val);
279
280 if(p->w.press_state & M_MODS_SHIFT) //+Shift : 判定元無効
281 disable_ref = TRUE;
282 else
283 disable_ref = FILL_IS_DISABLE_REF(val);
284 }
285 else
286 {
287 //不透明消去
288
289 type = DRAWFILL_TYPE_OPAQUE;
290 diff = 0;
291 opacity = 255;
292 disable_ref = TRUE;
293 }
294
295 //判定元イメージリンクセット & 先頭を取得
296
297 item = LayerList_setLink_filltool(p->layerlist, p->curlayer, disable_ref);
298
299 //初期化
300
301 drawOpSub_getImagePoint_int_raw(p, &pt);
302
303 draw = DrawFill_new(p->curlayer->img, item->img, &pt, type, diff, opacity);
304 if(!draw) return TRUE;
305
306 //描画
307
308 drawOpSub_setDrawInfo(p, p->w.optoolno, 0);
309 drawOpSub_beginDraw_single(p);
310
311 DrawFill_run(draw, &p->w.pixdraw);
312
313 drawOpSub_endDraw_single(p);
314
315 //
316
317 DrawFill_free(draw);
318
319 return TRUE;
320 }
321
322 /** 押し */
323
drawOp_fill_press(DrawData * p)324 mBool drawOp_fill_press(DrawData *p)
325 {
326 if(drawOpSub_canDrawLayer(p))
327 //描画不可
328 return FALSE;
329 else
330 {
331 drawOpSub_setOpInfo(p, DRAW_OPTYPE_TMP, NULL, _fill_release, 0);
332 return TRUE;
333 }
334 }
335
336
337 //==================================
338 // 移動ツール
339 //==================================
340 /*
341 pttmp[0] : 移動開始時の先頭レイヤのオフセット位置
342 pttmp[1] : オフセット位置の総相対移動数
343 ptd_tmp[0] : 総相対移動 px 数 (キャンバス座標)
344 rctmp[0] : 現在の、対象レイヤすべての表示イメージ範囲
345 rcdraw : 更新範囲
346
347 * フォルダレイヤ選択時は、フォルダ下すべて移動。
348 * 移動対象のレイヤは DrawData::w.layer を先頭に LayerItem::link でリンクされている。
349 (フォルダ、ロックレイヤは含まれない)
350 */
351
352
353 /** 移動時の計算
354 *
355 * @param ptret 相対移動数が入る
356 * @return 1px でも移動するか */
357
_movetool_calc(DrawData * p,uint32_t state,mPoint * ptret)358 static mBool _movetool_calc(DrawData *p,uint32_t state,mPoint *ptret)
359 {
360 mPoint pt,pt2;
361 double x,y;
362
363 //カーソル移動距離
364
365 x = p->w.dptAreaCur.x - p->w.dptAreaLast.x;
366 y = p->w.dptAreaCur.y - p->w.dptAreaLast.y;
367
368 if(state & M_MODS_CTRL) x = 0;
369 if(state & M_MODS_SHIFT) y = 0;
370
371 //総移動数
372
373 p->w.ptd_tmp[0].x += x;
374 p->w.ptd_tmp[0].y += y;
375
376 //総移動数を キャンバス -> イメージ 座標変換
377
378 pt2.x = (int)p->w.ptd_tmp[0].x;
379 pt2.y = (int)p->w.ptd_tmp[0].y;
380
381 drawCalc_areaToimage_relative(p, &pt, &pt2);
382
383 //移動開始時のオフセット位置を加算して絶対値に
384
385 pt.x += p->w.pttmp[0].x;
386 pt.y += p->w.pttmp[0].y;
387
388 //現在位置からの相対移動数
389
390 TileImage_getOffset(p->w.layer->img, &pt2);
391
392 pt.x -= pt2.x;
393 pt.y -= pt2.y;
394
395 if(pt.x == 0 && pt.y == 0)
396 return FALSE;
397 else
398 {
399 //総相対移動数
400 p->w.pttmp[1].x += pt.x;
401 p->w.pttmp[1].y += pt.y;
402
403 *ptret = pt;
404
405 return TRUE;
406 }
407 }
408
409 /** 移動 */
410
_movetool_motion(DrawData * p,uint32_t state)411 static void _movetool_motion(DrawData *p,uint32_t state)
412 {
413 mPoint pt;
414 mRect rc;
415 LayerItem *pi;
416
417 if(_movetool_calc(p, state, &pt))
418 {
419 //オフセット位置移動
420
421 for(pi = p->w.layer; pi; pi = pi->link)
422 TileImage_moveOffset_rel(pi->img, pt.x, pt.y);
423
424 //更新範囲
425 /* rcTmp[0] と、rcTmp[0] を pt 分相対移動した範囲を合わせたもの */
426
427 drawCalc_unionRect_relmove(&rc, p->w.rctmp, pt.x, pt.y);
428
429 //現在のイメージ範囲移動
430
431 mRectRelMove(p->w.rctmp, pt.x, pt.y);
432
433 //更新
434 /* タイマーで更新が行われると、rcdraw が空になる */
435
436 mRectUnion(&p->w.rcdraw, &rc);
437
438 MainWinCanvasArea_setTimer_updateMove();
439 }
440 }
441
442 /** 離し */
443
_movetool_release(DrawData * p)444 static mBool _movetool_release(DrawData *p)
445 {
446 mRect rc;
447
448 if(p->w.pttmp[1].x || p->w.pttmp[1].y)
449 {
450 //undo
451
452 Undo_addLayerMoveOffset(p->w.pttmp[1].x, p->w.pttmp[1].y,
453 p->w.layer, LayerItem_getLinkLayerNum(p->w.layer));
454
455 //タイマークリア
456
457 MainWinCanvasArea_clearTimer_updateMove();
458
459 //未更新の範囲を処理
460
461 drawUpdate_rect_imgcanvas_fromRect(p, &p->w.rcdraw);
462
463 //キャンバスビュー更新
464 /* 移動前の範囲 (p->w.rctmp[0] を総相対移動数分戻す)
465 * + 移動後の範囲 (p->w.rctmp[0]) */
466
467 drawCalc_unionRect_relmove(&rc, p->w.rctmp, -(p->w.pttmp[1].x), -(p->w.pttmp[1].y));
468
469 drawUpdate_canvasview(p, &rc);
470 }
471
472 return TRUE;
473 }
474
475 /** 押し */
476
drawOp_movetool_press(DrawData * p)477 mBool drawOp_movetool_press(DrawData *p)
478 {
479 LayerItem *pi;
480 int target;
481 mPoint pt;
482
483 target = p->tool.opt_move;
484
485 //対象レイヤ (pi)
486
487 if(target == 0)
488 //カレントレイヤ
489 pi = p->curlayer;
490 else if(target == 2)
491 //すべてのレイヤ
492 pi = NULL;
493 else
494 {
495 //掴んだレイヤ
496
497 drawOpSub_getImagePoint_int_raw(p, &pt);
498
499 pi = LayerList_getItem_topPixelLayer(p->layerlist, pt.x, pt.y);
500 if(!pi) return FALSE;
501 }
502
503 //レイヤのリンクセット & 先頭のレイヤ取得
504
505 p->w.layer = LayerList_setLink_movetool(p->layerlist, target, pi);
506 if(!p->w.layer) return FALSE;
507
508 //
509
510 drawOpSub_setOpInfo(p, DRAW_OPTYPE_MOVETOOL,
511 _movetool_motion, _movetool_release, 0);
512
513 //全体の表示イメージ範囲
514
515 LayerItem_getVisibleImageRect_link(p->w.layer, &p->w.rctmp[0]);
516
517 //元のオフセット位置取得
518
519 TileImage_getOffset(p->w.layer->img, &p->w.pttmp[0]);
520
521 //
522
523 p->w.ptd_tmp[0].x = p->w.ptd_tmp[0].y = 0;
524 p->w.pttmp[1].x = p->w.pttmp[1].y = 0;
525
526 mRectEmpty(&p->w.rcdraw);
527
528 return TRUE;
529 }
530
531
532 //==============================
533 // キャンバス移動
534 //==============================
535 /*
536 pttmp[0] : 開始時のスクロール位置
537 */
538
539
540 /** 移動 */
541
_canvasmove_motion(DrawData * p,uint32_t state)542 static void _canvasmove_motion(DrawData *p,uint32_t state)
543 {
544 mPoint pt;
545
546 pt.x = p->w.pttmp[0].x + (int)(p->w.dptAreaPress.x - p->w.dptAreaCur.x);
547 pt.y = p->w.pttmp[0].y + (int)(p->w.dptAreaPress.y - p->w.dptAreaCur.y);
548
549 if(pt.x != p->w.pttmp[0].x || pt.y != p->w.pttmp[0].y)
550 {
551 p->ptScroll = pt;
552
553 MainWinCanvas_setScrollPos();
554
555 MainWinCanvasArea_setTimer_updateArea(5);
556 }
557 }
558
559 /** 押し */
560
drawOp_canvasMove_press(DrawData * p)561 mBool drawOp_canvasMove_press(DrawData *p)
562 {
563 drawOpSub_setOpInfo(p, DRAW_OPTYPE_CANVAS_MOVE,
564 _canvasmove_motion, _common_release_canvas, 0);
565
566 p->w.opflags |= DRAW_OPFLAGS_MOTION_POS_INT;
567 p->w.pttmp[0] = p->ptScroll;
568 p->w.drag_cursor_type = APP_CURSOR_HAND_DRAG;
569
570 drawCanvas_lowQuality();
571
572 return TRUE;
573 }
574
575
576 //==============================
577 // キャンバス回転
578 //==============================
579 /*
580 ntmp[0] : 現在の回転角度
581 ntmp[1] : 前のキャンバス上の角度
582 */
583
584
585 /** カーソルとキャンバス中央の角度取得 */
586
_get_canvasrotate_angle(DrawData * p)587 static int _get_canvasrotate_angle(DrawData *p)
588 {
589 double x,y;
590
591 x = p->w.dptAreaCur.x - p->szCanvas.w * 0.5;
592 y = p->w.dptAreaCur.y - p->szCanvas.h * 0.5;
593
594 return (int)(atan2(y, x) * 18000 / M_MATH_PI);
595 }
596
597 /** 移動 */
598
_canvasrotate_motion(DrawData * p,uint32_t state)599 static void _canvasrotate_motion(DrawData *p,uint32_t state)
600 {
601 int angle,n;
602
603 angle = _get_canvasrotate_angle(p);
604
605 //前回の角度からの移動分を加算
606
607 n = p->w.ntmp[0] + angle - p->w.ntmp[1];
608
609 if(n < -18000) n += 36000;
610 else if(n > 18000) n -= 36000;
611
612 p->w.ntmp[0] = n;
613 p->w.ntmp[1] = angle;
614
615 //45度補正
616
617 if(state & M_MODS_SHIFT)
618 n = n / 4500 * 4500;
619
620 //更新
621
622 if(n != p->canvas_angle)
623 {
624 drawCanvas_setZoomAndAngle(p, 0, n, 2 | DRAW_SETZOOMANDANGLE_F_NO_UPDATE, FALSE);
625
626 MainWinCanvasArea_setTimer_updateArea(5);
627 }
628 }
629
630 /** 押し */
631
drawOp_canvasRotate_press(DrawData * p)632 mBool drawOp_canvasRotate_press(DrawData *p)
633 {
634 drawOpSub_setOpInfo(p, DRAW_OPTYPE_CANVAS_ROTATE,
635 _canvasrotate_motion, _common_release_canvas, 0);
636
637 p->w.opflags |= DRAW_OPFLAGS_MOTION_POS_INT;
638 p->w.ntmp[0] = p->canvas_angle;
639 p->w.ntmp[1] = _get_canvasrotate_angle(p);
640 p->w.drag_cursor_type = APP_CURSOR_ROTATE;
641
642 drawCanvas_lowQuality();
643 drawCanvas_setScrollReset_update(p, NULL);
644
645 return TRUE;
646 }
647
648
649 //===============================
650 // 上下ドラッグでの表示倍率変更
651 //===============================
652 /*
653 ntmp[0] : 開始時の表示倍率
654 */
655
656
657 /** 移動 */
658
_canvaszoom_motion(DrawData * p,uint32_t state)659 static void _canvaszoom_motion(DrawData *p,uint32_t state)
660 {
661 int n;
662
663 n = p->w.ntmp[0] + (int)(p->w.dptAreaPress.y - p->w.dptAreaCur.y) * 10;
664
665 if(n != p->canvas_zoom)
666 {
667 drawCanvas_setZoomAndAngle(p, n, 0, 1 | DRAW_SETZOOMANDANGLE_F_NO_UPDATE, FALSE);
668
669 MainWinCanvasArea_setTimer_updateArea(5);
670 }
671 }
672
673 /** 押し */
674
drawOp_canvasZoom_press(DrawData * p)675 mBool drawOp_canvasZoom_press(DrawData *p)
676 {
677 drawOpSub_setOpInfo(p, DRAW_OPTYPE_CANVAS_ZOOM,
678 _canvaszoom_motion, _common_release_canvas, 0);
679
680 p->w.opflags |= DRAW_OPFLAGS_MOTION_POS_INT;
681 p->w.ntmp[0] = p->canvas_zoom;
682
683 drawCanvas_lowQuality();
684 drawCanvas_setScrollReset_update(p, NULL);
685
686 return TRUE;
687 }
688
689
690 //===============================
691 // スポイト
692 //===============================
693
694
695 /** 押し */
696
drawOp_spoit_press(DrawData * p,mBool enable_alt)697 mBool drawOp_spoit_press(DrawData *p,mBool enable_alt)
698 {
699 mPoint pt;
700 PixelRGBA pix;
701 uint32_t col;
702
703 drawOpSub_setOpInfo(p, DRAW_OPTYPE_TMP, NULL, NULL, 0);
704
705 drawOpSub_getImagePoint_int_raw(p, &pt);
706
707 if(pt.x >= 0 && pt.x < p->imgw && pt.y >= 0 && pt.y < p->imgh)
708 {
709 //----- 色取得
710
711 if(p->w.press_state & M_MODS_CTRL)
712 {
713 //+Ctrl : カレントレイヤ (フォルダの場合は除く)
714
715 if(drawOpSub_isFolder_curlayer()) return TRUE;
716
717 TileImage_getPixel(p->curlayer->img, pt.x, pt.y, &pix);
718
719 col = M_RGB(pix.r, pix.g, pix.b);
720 }
721 else
722 //全レイヤ合成後
723 col = drawImage_getBlendColor_atPoint(p, pt.x, pt.y, NULL);
724
725 //----- セット
726
727 if(enable_alt && (p->w.press_state & M_MODS_ALT))
728 {
729 //+Alt : 色マスクに追加
730
731 drawColorMask_addColor(p, col);
732 DockColor_changeColorMask();
733 }
734 else if(p->w.press_state & M_MODS_SHIFT)
735 {
736 //+Shift : 色マスクにセット
737
738 drawColorMask_setColor(p, col);
739 DockColor_changeColorMask();
740 }
741 else
742 {
743 //描画色にセット
744
745 drawColor_setDrawColor(col);
746 DockColor_changeDrawColor();
747 }
748 }
749
750 return TRUE;
751 }
752
753
754 //===============================
755 // 中間色作成
756 //===============================
757 /*
758 * ntmp[0..2] : 最初の色 (RGB)
759 */
760
761
762 /** 押し */
763
drawOp_intermediateColor_press(DrawData * p)764 mBool drawOp_intermediateColor_press(DrawData *p)
765 {
766 mPoint pt;
767 mNanoTime nt;
768 PixelRGB pix;
769 int i;
770
771 //スポイト
772
773 drawOpSub_getImagePoint_int_raw(p, &pt);
774 drawImage_getBlendColor_atPoint(p, pt.x, pt.y, &pix);
775
776 //
777
778 mNanoTimeGet(&nt);
779
780 if(p->w.sec_midcol == 0 || nt.sec > p->w.sec_midcol + 5)
781 {
782 //最初の色 (前回押し時から5秒以上経った場合は初期化)
783
784 p->w.ntmp[0] = pix.r;
785 p->w.ntmp[1] = pix.g;
786 p->w.ntmp[2] = pix.b;
787
788 p->w.sec_midcol = nt.sec;
789 }
790 else
791 {
792 //中間色作成
793
794 for(i = 0; i < 3; i++)
795 pix.c[i] = (p->w.ntmp[i] - pix.c[i]) / 2 + pix.c[i];
796
797 drawColor_setDrawColor(M_RGB(pix.c[0], pix.c[1], pix.c[2]));
798
799 DockColor_changeDrawColor();
800
801 p->w.sec_midcol = 0;
802 }
803
804 //
805
806 drawOpSub_setOpInfo(p, DRAW_OPTYPE_TMP, NULL, NULL, 0);
807
808 return TRUE;
809 }
810
811
812 //===============================
813 // 色置換え
814 //===============================
815
816
817 /** カレントレイヤ上で、クリックした色を描画色 or 透明に置き換える */
818
drawOp_replaceColor_press(DrawData * p,mBool rep_tp)819 mBool drawOp_replaceColor_press(DrawData *p,mBool rep_tp)
820 {
821 mPoint pt;
822 PixelRGBA pixsrc,pixdst;
823
824 if(drawOpSub_canDrawLayer(p)) return FALSE;
825
826 //スポイト
827
828 drawOpSub_getImagePoint_int_raw(p, &pt);
829
830 TileImage_getPixel(p->curlayer->img, pt.x, pt.y, &pixsrc);
831
832 //置き換える色
833
834 if(rep_tp)
835 pixdst.c = 0;
836 else
837 drawColor_getDrawColor_pixRGBA(&pixdst);
838
839 //置き換える必要がないか
840
841 if((pixdst.a == 0 && pixsrc.a == 0)
842 || (pixsrc.a && pixdst.a && pixsrc.r == pixdst.r && pixsrc.g == pixdst.g && pixsrc.b == pixdst.b))
843 return FALSE;
844
845 //置換え
846
847 drawOpSub_setDrawInfo_forOverwrite(p);
848 drawOpSub_beginDraw_single(p);
849
850 if(pixsrc.a == 0)
851 TileImage_replaceColor_fromTP(p->w.dstimg, &pixdst);
852 else
853 TileImage_replaceColor(p->w.dstimg, &pixsrc, &pixdst);
854
855 drawOpSub_endDraw_single(p);
856
857 //
858
859 drawOpSub_setOpInfo(p, DRAW_OPTYPE_TMP, NULL, NULL, 0);
860
861 return TRUE;
862 }
863
864
865 //===============================
866 // テキスト描画
867 //===============================
868 /*
869 * tileimgTmp : プレビュー描画用
870 * pttmp[0] : 描画位置 (イメージ座標)
871 * rcdraw : プレビューの前回の描画範囲
872 */
873
874
875 /** フォント作成 */
876
drawText_createFont()877 void drawText_createFont()
878 {
879 DrawTextData *pt = &APP_DRAW->drawtext;
880 mFontInfo info;
881
882 DrawFont_free(pt->font);
883
884 //---------
885
886 mMemzero(&info, sizeof(mFontInfo));
887
888 info.mask = MFONTINFO_MASK_SIZE | MFONTINFO_MASK_RENDER;
889
890 //フォント名
891
892 if(!mStrIsEmpty(&pt->strName))
893 {
894 info.mask |= MFONTINFO_MASK_FAMILY;
895 mStrCopy(&info.strFamily, &pt->strName);
896 }
897
898 //スタイル
899
900 if(!mStrIsEmpty(&pt->strStyle))
901 {
902 info.mask |= MFONTINFO_MASK_STYLE;
903 mStrCopy(&info.strStyle, &pt->strStyle);
904 }
905 else
906 {
907 //太字
908
909 info.mask |= MFONTINFO_MASK_WEIGHT;
910 info.weight = (pt->weight == 0)? MFONTINFO_WEIGHT_NORMAL: MFONTINFO_WEIGHT_BOLD;
911
912 //斜体
913
914 info.mask |= MFONTINFO_MASK_SLANT;
915 info.slant = pt->slant;
916 }
917
918 //サイズ
919
920 info.size = pt->size * 0.1;
921 if(pt->flags & DRAW_DRAWTEXT_F_SIZE_PIXEL) info.size = -info.size;
922
923 //レンダリング
924
925 info.render = (pt->flags & DRAW_DRAWTEXT_F_ANTIALIAS)? MFONTINFO_RENDER_GRAY: MFONTINFO_RENDER_MONO;
926
927 //--------------
928
929 pt->font = DrawFont_create(&info, APP_DRAW->imgdpi);
930
931 mFontInfoFree(&info);
932
933 //DPI 記録
934
935 pt->create_dpi = APP_DRAW->imgdpi;
936 }
937
938 /** ヒンティング変更 */
939
drawText_setHinting(DrawData * p)940 void drawText_setHinting(DrawData *p)
941 {
942 DrawFont_setHinting(p->drawtext.font, p->drawtext.hinting);
943 }
944
945 /** テキスト描画情報セット */
946
_drawtext_set_info(DrawFontInfo * dst,DrawTextData * src,TileImage * img)947 static void _drawtext_set_info(DrawFontInfo *dst,DrawTextData *src,TileImage *img)
948 {
949 dst->char_space = src->char_space;
950 dst->line_space = src->line_space;
951
952 dst->flags = 0;
953 if(src->flags & DRAW_DRAWTEXT_F_VERT) dst->flags |= DRAWFONT_F_VERT;
954
955 dst->param = img;
956 }
957
958 /** プレビュー用の点描画 */
959
_drawtext_setpixel_prev(int x,int y,int a,void * param)960 static void _drawtext_setpixel_prev(int x,int y,int a,void *param)
961 {
962 APP_DRAW->w.pixdraw.a = a;
963
964 TileImage_setPixel_subdraw((TileImage *)param, x, y, &APP_DRAW->w.pixdraw);
965 }
966
967 /** プレビュー描画 */
968
drawText_drawPreview(DrawData * p)969 void drawText_drawPreview(DrawData *p)
970 {
971 DrawTextData *pdat = &p->drawtext;
972 DrawFontInfo info;
973 mRect rc;
974
975 rc = p->w.rcdraw;
976
977 //前回のイメージと範囲をクリア
978
979 if(!mRectIsEmpty(&rc))
980 {
981 TileImage_freeAllTiles(p->tileimgTmp);
982
983 mRectEmpty(&p->w.rcdraw);
984 }
985
986 //プレビューなし、または空文字列の場合、前回の範囲を更新して終了
987
988 if(!(pdat->flags & DRAW_DRAWTEXT_F_PREVIEW)
989 || mStrIsEmpty(&pdat->strText))
990 {
991 drawUpdate_rect_imgcanvas_canvasview_fromRect(p, &rc);
992 return;
993 }
994
995 //描画
996
997 _drawtext_set_info(&info, pdat, p->tileimgTmp);
998
999 info.setpixel = _drawtext_setpixel_prev;
1000
1001 g_tileimage_dinfo.funcColor = TileImage_colfunc_normal;
1002
1003 TileImageDrawInfo_clearDrawRect();
1004
1005 DrawFont_drawText(pdat->font, p->w.pttmp[0].x, p->w.pttmp[0].y,
1006 pdat->strText.buf, &info);
1007
1008 //更新 (前回の範囲と結合)
1009
1010 mRectUnion(&rc, &g_tileimage_dinfo.rcdraw);
1011
1012 drawUpdate_rect_imgcanvas_fromRect(p, &rc);
1013
1014 //範囲を記録
1015
1016 p->w.rcdraw = g_tileimage_dinfo.rcdraw;
1017 }
1018
1019 /** 実際の描画時の点描画 */
1020
_drawtext_setpixel_draw(int x,int y,int a,void * param)1021 static void _drawtext_setpixel_draw(int x,int y,int a,void *param)
1022 {
1023 APP_DRAW->w.pixdraw.a = a;
1024
1025 TileImage_setPixel_draw_direct((TileImage *)param, x, y, &APP_DRAW->w.pixdraw);
1026 }
1027
1028 /** 描画 */
1029
_drawtext_draw(DrawData * p)1030 static void _drawtext_draw(DrawData *p)
1031 {
1032 DrawFontInfo info;
1033
1034 //描画準備
1035
1036 drawOpSub_setDrawInfo(p, TOOL_TEXT, 0);
1037
1038 //描画情報
1039
1040 _drawtext_set_info(&info, &p->drawtext, p->w.dstimg);
1041
1042 info.setpixel = _drawtext_setpixel_draw;
1043
1044 //描画
1045
1046 drawOpSub_beginDraw_single(p);
1047
1048 DrawFont_drawText(p->drawtext.font, p->w.pttmp[0].x, p->w.pttmp[0].y,
1049 p->drawtext.strText.buf, &info);
1050
1051 drawOpSub_endDraw_single(p);
1052 }
1053
1054 /** 押し */
1055
drawOp_drawtext_press(DrawData * p)1056 mBool drawOp_drawtext_press(DrawData *p)
1057 {
1058 mBool ret;
1059
1060 //描画位置
1061
1062 drawOpSub_getImagePoint_int_raw(p, &p->w.pttmp[0]);
1063
1064 //プレビュー用イメージ作成
1065
1066 p->tileimgTmp = TileImage_new(TILEIMAGE_COLTYPE_RGBA, p->imgw, p->imgh);
1067 if(!p->tileimgTmp) return FALSE;
1068
1069 //初期化
1070
1071 mRectEmpty(&p->w.rcdraw);
1072
1073 drawColor_getDrawColor_pixRGBA(&p->w.pixdraw);
1074
1075 //ダイアログ
1076
1077 p->drawtext.in_dialog = TRUE;
1078
1079 ret = DrawTextDlg_run(M_WINDOW(APP_WIDGETS->mainwin));
1080
1081 p->drawtext.in_dialog = FALSE;
1082
1083 //----------
1084
1085 //プレビュー用イメージ削除
1086
1087 drawOpSub_freeTmpImage(p);
1088
1089 //プレビュー範囲を元に戻す
1090 /* [!] ダイアログ表示中にメインウィンドウのサイズを変更した場合などは、
1091 * [dock]キャンバスビューで、プレビューが適用された blendimg を元に再描画されているので、
1092 * 念のためキャンバスビューの範囲も戻す。 */
1093
1094 drawUpdate_rect_imgcanvas_canvasview_fromRect(p, &p->w.rcdraw);
1095
1096 //描画
1097
1098 if(ret && !mStrIsEmpty(&p->drawtext.strText))
1099 _drawtext_draw(p);
1100
1101 return FALSE;
1102 }
1103
1104 /** ダイアログ中にキャンバス上がクリックされた時 */
1105
drawText_setDrawPoint_inDialog(DrawData * p,int x,int y)1106 void drawText_setDrawPoint_inDialog(DrawData *p,int x,int y)
1107 {
1108 //位置
1109
1110 drawCalc_areaToimage_pt(p, &p->w.pttmp[0], x, y);
1111
1112 //プレビュー
1113
1114 drawText_drawPreview(p);
1115 }
1116
1117