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