1 /*$
2  Copyright (C) 2013-2020 Azel.
3 
4  This file is part of AzPainter.
5 
6  AzPainter 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  AzPainter 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  * 操作 - XOR 処理
24  *****************************************/
25 
26 #include <stdlib.h>
27 
28 #include "mDef.h"
29 #include "mRectBox.h"
30 #include "mPixbuf.h"
31 
32 #include "defDraw.h"
33 #include "TileImage.h"
34 #include "TileImageDrawInfo.h"
35 #include "FillPolygon.h"
36 
37 #include "draw_main.h"
38 #include "draw_calc.h"
39 #include "draw_op_def.h"
40 #include "draw_op_func.h"
41 #include "draw_op_sub.h"
42 #include "draw_rule.h"
43 #include "draw_boxedit.h"
44 
45 
46 
47 //=============================
48 // sub
49 //=============================
50 
51 
52 /** 矩形範囲 共通処理
53  *
54  * pttmp[0] : 左上, pttmp[1] : 右下, pttmp[2] : 開始点 */
55 
_common_rect_func(DrawData * p,int x,int y,uint32_t state)56 static void _common_rect_func(DrawData *p,int x,int y,uint32_t state)
57 {
58 	int x1,y1,x2,y2,w,h;
59 
60 	//左上、左下
61 
62 	if(x < p->w.pttmp[2].x)
63 		x1 = x, x2 = p->w.pttmp[2].x;
64 	else
65 		x1 = p->w.pttmp[2].x, x2 = x;
66 
67 	if(y < p->w.pttmp[2].y)
68 		y1 = y, y2 = p->w.pttmp[2].y;
69 	else
70 		y1 = p->w.pttmp[2].y, y2 = y;
71 
72 	//正方形調整
73 
74 	if(state & M_MODS_SHIFT)
75 	{
76 		w = x2 - x1;
77 		h = y2 - y1;
78 
79 		if(w < h)
80 		{
81 			if(x < p->w.pttmp[2].x)
82 				x1 = x2 - h;
83 			else
84 				x2 = x1 + h;
85 		}
86 		else
87 		{
88 			if(y < p->w.pttmp[2].y)
89 				y1 = y2 - w;
90 			else
91 				y2 = y1 + w;
92 		}
93 	}
94 
95 	p->w.pttmp[0].x = x1, p->w.pttmp[0].y = y1;
96 	p->w.pttmp[1].x = x2, p->w.pttmp[1].y = y2;
97 }
98 
99 
100 //=============================
101 // XOR直線
102 //=============================
103 /*
104 	pttmp[0] : 始点
105 	pttmp[1] : 終点 (現在の位置)
106 */
107 
108 
109 /** 移動 (連続直線/集中線/多角形と共用) */
110 
_xorline_motion(DrawData * p,uint32_t state)111 static void _xorline_motion(DrawData *p,uint32_t state)
112 {
113 	mPoint pt;
114 
115 	drawOpSub_getAreaPoint_int(p, &pt);
116 
117 	if(pt.x == p->w.pttmp[1].x && pt.y == p->w.pttmp[1].y)
118 		return;
119 
120 	//
121 
122 	drawOpXor_drawline(p);
123 
124 	if(state & M_MODS_SHIFT)
125 		drawCalc_fitLine45(&pt, p->w.pttmp);
126 
127 	p->w.pttmp[1] = pt;
128 
129 	drawOpXor_drawline(p);
130 }
131 
132 /** 離し */
133 
_xorline_release(DrawData * p)134 static mBool _xorline_release(DrawData *p)
135 {
136 	drawOpXor_drawline(p);
137 
138 	switch(p->w.opsubtype)
139 	{
140 		//直線描画
141 		case DRAW_OPSUB_DRAW_LINE:
142 			drawOpDraw_brush_line(p);
143 			break;
144 		//ベジェ曲線、制御点操作に移行
145 		case DRAW_OPSUB_TO_BEZIER:
146 			return drawOp_xorline_to_bezier(p);
147 		//定規設定
148 		case DRAW_OPSUB_RULE_SETTING:
149 			drawRule_setting_line(p);
150 			break;
151 		//グラデーション描画
152 		case DRAW_OPSUB_DRAW_GRADATION:
153 			drawOpDraw_gradation(p);
154 			break;
155 	}
156 
157 	return TRUE;
158 }
159 
160 /** 押し */
161 
drawOpXor_line_press(DrawData * p,int opsubtype)162 mBool drawOpXor_line_press(DrawData *p,int opsubtype)
163 {
164 	drawOpSub_setOpInfo(p, DRAW_OPTYPE_XOR_LINE,
165 		_xorline_motion, _xorline_release, opsubtype);
166 
167 	p->w.opflags |= DRAW_OPFLAGS_MOTION_POS_INT;
168 
169 	drawOpSub_getAreaPoint_int(p, p->w.pttmp);
170 
171 	p->w.pttmp[1] = p->w.pttmp[0];
172 
173 	drawOpXor_drawline(p);
174 
175 	return TRUE;
176 }
177 
178 
179 //=============================
180 // XOR 四角形 (領域に対する)
181 //=============================
182 /*
183 	pttmp[0] : 左上
184 	pttmp[1] : 右下
185 	pttmp[2] : 開始点
186 */
187 
188 
189 /** 移動 */
190 
_xorbox_area_motion(DrawData * p,uint32_t state)191 static void _xorbox_area_motion(DrawData *p,uint32_t state)
192 {
193 	mPoint pt;
194 
195 	drawOpXor_drawBox_area(p);
196 
197 	drawOpSub_getAreaPoint_int(p, &pt);
198 
199 	_common_rect_func(p, pt.x, pt.y, state);
200 
201 	drawOpXor_drawBox_area(p);
202 }
203 
204 /** 離し */
205 
_xorbox_area_release(DrawData * p)206 static mBool _xorbox_area_release(DrawData *p)
207 {
208 	drawOpXor_drawBox_area(p);
209 
210 	switch(p->w.opsubtype)
211 	{
212 		//四角形枠描画
213 		case DRAW_OPSUB_DRAW_FRAME:
214 			drawOpDraw_brush_box(p);
215 			break;
216 		//四角形塗りつぶし
217 		case DRAW_OPSUB_DRAW_FILL:
218 			drawOpDraw_fillBox(p);
219 			break;
220 		//選択範囲セット
221 		case DRAW_OPSUB_SET_SELECT:
222 			drawOp_setSelect(p, 0);
223 			break;
224 	}
225 
226 	return TRUE;
227 }
228 
229 /** 押し */
230 
drawOpXor_boxarea_press(DrawData * p,int opsubtype)231 mBool drawOpXor_boxarea_press(DrawData *p,int opsubtype)
232 {
233 	drawOpSub_setOpInfo(p, DRAW_OPTYPE_XOR_BOXAREA,
234 		_xorbox_area_motion, _xorbox_area_release, opsubtype);
235 
236 	p->w.opflags |= DRAW_OPFLAGS_MOTION_POS_INT;
237 
238 	drawOpSub_getAreaPoint_int(p, p->w.pttmp);
239 
240 	p->w.pttmp[1] = p->w.pttmp[2] = p->w.pttmp[0];
241 
242 	drawOpXor_drawBox_area(p);
243 
244 	return TRUE;
245 }
246 
247 
248 //=================================
249 // XOR 四角形 (イメージに対する)
250 //=================================
251 /*
252 	pttmp[0] : 左上位置 (イメージ座標)
253 	pttmp[1] : 右下位置 (イメージ座標)
254 	pttmp[2] : 開始点 (イメージ座標)
255 	pttmp[3] : 前回の位置 (イメージ座標)
256 
257 	boxtmp[0] : 結果の mBox
258 	rctmp[0]  : 結果の mRect
259 
260 	[!] 範囲のクリッピングは行われないので注意
261 */
262 
263 
264 /** 移動 */
265 
_xorbox_image_motion(DrawData * p,uint32_t state)266 static void _xorbox_image_motion(DrawData *p,uint32_t state)
267 {
268 	mPoint pt;
269 
270 	drawOpSub_getImagePoint_int(p, &pt);
271 
272 	if(pt.x != p->w.pttmp[3].x || pt.y != p->w.pttmp[3].y)
273 	{
274 		drawOpXor_drawBox_image(p);
275 
276 		_common_rect_func(p, pt.x, pt.y, state);
277 
278 		drawOpXor_drawBox_image(p);
279 
280 		p->w.pttmp[3] = pt;
281 	}
282 }
283 
284 /** 離し */
285 
_xorbox_image_release(DrawData * p)286 static mBool _xorbox_image_release(DrawData *p)
287 {
288 	drawOpXor_drawBox_image(p);
289 
290 	//結果範囲 (mBox, mRect)
291 
292 	mBoxSetByPoint(p->w.boxtmp, p->w.pttmp, p->w.pttmp + 1);
293 
294 	p->w.rctmp[0].x1 = p->w.pttmp[0].x, p->w.rctmp[0].y1 = p->w.pttmp[0].y;
295 	p->w.rctmp[0].x2 = p->w.pttmp[1].x, p->w.rctmp[0].y2 = p->w.pttmp[1].y;
296 
297 	//
298 
299 	switch(p->w.opsubtype)
300 	{
301 		//スタンプ画像セット
302 		case DRAW_OPSUB_SET_STAMP:
303 			drawOp_setStampImage(p);
304 			break;
305 		//矩形編集範囲セット
306 		case DRAW_OPSUB_SET_BOXEDIT:
307 			drawBoxEdit_setBox(p, p->w.rctmp);
308 			break;
309 	}
310 
311 	return TRUE;
312 }
313 
314 /** 押し */
315 
drawOpXor_boximage_press(DrawData * p,int opsubtype)316 mBool drawOpXor_boximage_press(DrawData *p,int opsubtype)
317 {
318 	drawOpSub_setOpInfo(p, DRAW_OPTYPE_XOR_BOXIMAGE,
319 		_xorbox_image_motion, _xorbox_image_release, opsubtype);
320 
321 	p->w.opflags |= DRAW_OPFLAGS_MOTION_POS_INT;
322 
323 	drawOpSub_getImagePoint_int(p, p->w.pttmp);
324 
325 	drawOpSub_copyTmpPoint(p, 3);
326 
327 	drawOpXor_drawBox_image(p);
328 
329 	return TRUE;
330 }
331 
332 
333 //=============================
334 // XOR 楕円 (領域に対する)
335 //=============================
336 /*
337 	pttmp[0] : 位置 (領域座標)
338 	pttmp[1] : 半径
339 	ntmp[0]  : 正円か
340 */
341 
342 
343 /** 移動 */
344 
_xorellipse_motion(DrawData * p,uint32_t state)345 static void _xorellipse_motion(DrawData *p,uint32_t state)
346 {
347 	mPoint pt;
348 	int xr,yr;
349 
350 	drawOpXor_drawEllipse(p);
351 
352 	drawOpSub_getAreaPoint_int(p, &pt);
353 
354 	xr = abs(pt.x - p->w.pttmp[0].x);
355 	yr = abs(pt.y - p->w.pttmp[0].y);
356 
357 	if(state & M_MODS_SHIFT)
358 	{
359 		if(xr > yr) yr = xr;
360 		else xr = yr;
361 
362 		p->w.ntmp[0] = 1;
363 	}
364 	else
365 		p->w.ntmp[0] = 0;
366 
367 	p->w.pttmp[1].x = xr;
368 	p->w.pttmp[1].y = yr;
369 
370 	drawOpXor_drawEllipse(p);
371 }
372 
373 /** 離し */
374 
_xorellipse_release(DrawData * p)375 static mBool _xorellipse_release(DrawData *p)
376 {
377 	drawOpXor_drawEllipse(p);
378 
379 	switch(p->w.opsubtype)
380 	{
381 		//円枠描画
382 		case DRAW_OPSUB_DRAW_FRAME:
383 			drawOpDraw_brush_ellipse(p);
384 			break;
385 		//円塗りつぶし描画
386 		case DRAW_OPSUB_DRAW_FILL:
387 			drawOpDraw_fillEllipse(p);
388 			break;
389 		//定規設定
390 		case DRAW_OPSUB_RULE_SETTING:
391 			drawRule_setting_ellipse(p);
392 			break;
393 	}
394 
395 	return TRUE;
396 }
397 
398 /** 押し */
399 
drawOpXor_ellipse_press(DrawData * p,int opsubtype)400 mBool drawOpXor_ellipse_press(DrawData *p,int opsubtype)
401 {
402 	drawOpSub_setOpInfo(p, DRAW_OPTYPE_XOR_ELLIPSE,
403 		_xorellipse_motion, _xorellipse_release, opsubtype);
404 
405 	p->w.opflags |= DRAW_OPFLAGS_MOTION_POS_INT;
406 
407 	drawOpSub_getAreaPoint_int(p, p->w.pttmp);
408 
409 	p->w.pttmp[1].x = p->w.pttmp[1].y = 0;
410 	p->w.ntmp[0] = 0;
411 
412 	drawOpXor_drawEllipse(p);
413 
414 	return TRUE;
415 }
416 
417 
418 //========================================
419 // XOR 複数直線 (連続直線/集中線)
420 //========================================
421 /*
422 	pttmp[0] : 始点
423 	pttmp[1] : 終点 (現在位置)
424 	pttmp[2] : 一番最初の点 (保存用)
425 */
426 
427 
428 /** 2回目以降の押し時 */
429 
_xorsumline_pressInGrab(DrawData * p,uint32_t state)430 static void _xorsumline_pressInGrab(DrawData *p,uint32_t state)
431 {
432 	drawOpXor_drawline(p);
433 
434 	drawOpDraw_brush_lineSuccConc(p);
435 
436 	//連続直線の場合、始点変更
437 
438 	if(p->w.opsubtype == DRAW_OPSUB_DRAW_SUCCLINE)
439 		p->w.pttmp[0] = p->w.pttmp[1];
440 
441 	drawOpXor_drawline(p);
442 }
443 
444 /** 各アクション (操作終了) */
445 
_xorsumline_action(DrawData * p,int action)446 static mBool _xorsumline_action(DrawData *p,int action)
447 {
448 	//BackSpace は連続直線のみ
449 
450 	if(action == DRAW_FUNCACTION_KEY_BACKSPACE
451 		&& p->w.opsubtype != DRAW_OPSUB_DRAW_SUCCLINE)
452 		return FALSE;
453 
454 	//
455 
456 	drawOpXor_drawline(p);
457 
458 	//BackSpace (連続直線) => 始点と結ぶ
459 
460 	if(action == DRAW_FUNCACTION_KEY_BACKSPACE)
461 	{
462 		p->w.pttmp[1] = p->w.pttmp[2];
463 
464 		drawOpDraw_brush_lineSuccConc(p);
465 	}
466 
467 	drawOpSub_finishDraw_workrect(p);
468 
469 	return TRUE;
470 }
471 
472 /** 複数直線の初期化 (多角形と共用) */
473 
_xorsumline_init(DrawData * p,int optype,int opsubtype)474 static void _xorsumline_init(DrawData *p,int optype,int opsubtype)
475 {
476 	drawOpSub_setOpInfo(p, optype,
477 		_xorline_motion, drawOp_common_norelease, opsubtype);
478 
479 	p->w.opflags |= DRAW_OPFLAGS_MOTION_POS_INT;
480 
481 	drawOpSub_getAreaPoint_int(p, p->w.pttmp);
482 
483 	drawOpSub_copyTmpPoint(p, 2);
484 
485 	drawOpXor_drawline(p);
486 }
487 
488 /** 押し */
489 
drawOpXor_sumline_press(DrawData * p,int opsubtype)490 mBool drawOpXor_sumline_press(DrawData *p,int opsubtype)
491 {
492 	_xorsumline_init(p, DRAW_OPTYPE_XOR_SUMLINE, opsubtype);
493 
494 	p->w.funcPressInGrab = _xorsumline_pressInGrab;
495 	p->w.funcAction = _xorsumline_action;
496 
497 	//描画開始
498 
499 	drawOpSub_setDrawInfo(p, p->w.optoolno, 0);
500 	drawOpSub_beginDraw(p);
501 
502 	return TRUE;
503 }
504 
505 
506 //=================================
507 // 多角形
508 //=================================
509 /*
510 	確定した線は XOR 用イメージに描画。
511 	現在の線はキャンバスに直接 XOR 描画。
512 
513 	pttmp などは連続直線/集中線と同じ。
514 	boxtmp[0] : XOR 描画用範囲
515 */
516 
517 
518 /** 2回目以降の押し時 */
519 
_xorpolygon_pressInGrab(DrawData * p,uint32_t state)520 static void _xorpolygon_pressInGrab(DrawData *p,uint32_t state)
521 {
522 	mDoublePoint pt;
523 
524 	//ポイント追加
525 
526 	drawCalc_areaToimage_double(p, &pt.x, &pt.y, p->w.pttmp[1].x, p->w.pttmp[1].y);
527 
528 	FillPolygon_addPoint(p->w.fillpolygon, pt.x, pt.y);
529 
530 	//XOR
531 
532 	drawOpXor_drawline(p);
533 	drawOpXor_drawPolygon(p);
534 
535 	TileImage_drawLineB(p->tileimgTmp, p->w.pttmp[0].x, p->w.pttmp[0].y,
536 		p->w.pttmp[1].x, p->w.pttmp[1].y, &p->w.rgbaDraw, FALSE);
537 
538 	drawOpXor_drawPolygon(p);
539 
540 	p->w.pttmp[0] = p->w.pttmp[1];
541 
542 	drawOpXor_drawline(p);
543 }
544 
545 /** 各アクション (操作終了) */
546 
_xorpolygon_action(DrawData * p,int action)547 static mBool _xorpolygon_action(DrawData *p,int action)
548 {
549 	//BackSpace 無効
550 
551 	if(action == DRAW_FUNCACTION_KEY_BACKSPACE) return FALSE;
552 
553 	//XOR 消去
554 
555 	drawOpXor_drawline(p);
556 	drawOpXor_drawPolygon(p);
557 
558 	drawOpSub_freeTmpImage(p);
559 
560 	//描画
561 
562 	if(action != DRAW_FUNCACTION_KEY_ESC
563 		&& action != DRAW_FUNCACTION_UNGRAB)
564 	{
565 		if(FillPolygon_closePoint(p->w.fillpolygon))
566 		{
567 			switch(p->w.opsubtype)
568 			{
569 				//多角形塗りつぶし
570 				case DRAW_OPSUB_DRAW_FILL:
571 					drawOpDraw_fillPolygon(p);
572 					break;
573 				//スタンプイメージセット
574 				case DRAW_OPSUB_SET_STAMP:
575 					drawOp_setStampImage(p);
576 					break;
577 				//選択範囲セット
578 				case DRAW_OPSUB_SET_SELECT:
579 					drawOp_setSelect(p, 1);
580 					break;
581 			}
582 		}
583 	}
584 
585 	drawOpSub_freeFillPolygon(p);
586 
587 	return TRUE;
588 }
589 
590 /** 多角形初期化 (投げ縄と共用) */
591 
_fillpolygon_init(DrawData * p)592 static mBool _fillpolygon_init(DrawData *p)
593 {
594 	mDoublePoint pt;
595 
596 	if(!drawOpSub_createTmpImage_area(p))
597 		return FALSE;
598 
599 	//FillPolygon 作成
600 
601 	if(!(p->w.fillpolygon = FillPolygon_new()))
602 	{
603 		drawOpSub_freeTmpImage(p);
604 		return FALSE;
605 	}
606 
607 	//現在位置追加
608 
609 	drawOpSub_getImagePoint_double(p, &pt);
610 
611 	FillPolygon_addPoint(p->w.fillpolygon, pt.x, pt.y);
612 
613 	//
614 
615 	g_tileimage_dinfo.funcDrawPixel = TileImage_setPixel_new_notp;
616 
617 	p->w.rgbaDraw.a = 0x8000;
618 
619 	return TRUE;
620 }
621 
622 /** 最初の押し時 */
623 
drawOpXor_polygon_press(DrawData * p,int opsubtype)624 mBool drawOpXor_polygon_press(DrawData *p,int opsubtype)
625 {
626 	if(!_fillpolygon_init(p)) return FALSE;
627 
628 	//XOR 更新範囲
629 
630 	p->w.boxtmp[0].x = p->w.boxtmp[0].y = 0;
631 	p->w.boxtmp[0].w = p->szCanvas.w;
632 	p->w.boxtmp[0].h = p->szCanvas.h;
633 
634 	//
635 
636 	_xorsumline_init(p, DRAW_OPTYPE_XOR_POLYGON, opsubtype);
637 
638 	p->w.funcPressInGrab = _xorpolygon_pressInGrab;
639 	p->w.funcAction = _xorpolygon_action;
640 
641 	return TRUE;
642 }
643 
644 
645 //=============================
646 // XOR 投げ縄
647 //=============================
648 /*
649 	pttmp[0] : 線描画用、現在の位置
650 	pttmp[1] : 前回の位置
651 */
652 
653 
654 /** 移動 */
655 
_xorlasso_motion(DrawData * p,uint32_t state)656 static void _xorlasso_motion(DrawData *p,uint32_t state)
657 {
658 	mDoublePoint pt;
659 
660 	p->w.pttmp[1] = p->w.pttmp[0];
661 
662 	drawOpSub_getAreaPoint_int(p, p->w.pttmp);
663 
664 	drawOpXor_drawLasso(p, FALSE);
665 
666 	//ポイント追加
667 
668 	drawOpSub_getImagePoint_double(p, &pt);
669 	FillPolygon_addPoint(p->w.fillpolygon, pt.x, pt.y);
670 }
671 
672 /** 離し */
673 
_xorlasso_release(DrawData * p)674 static mBool _xorlasso_release(DrawData *p)
675 {
676 	drawOpXor_drawLasso(p, TRUE);
677 	drawOpSub_freeTmpImage(p);
678 
679 	if(FillPolygon_closePoint(p->w.fillpolygon))
680 	{
681 		switch(p->w.opsubtype)
682 		{
683 			//フリーハンド塗りつぶし
684 			case DRAW_OPSUB_DRAW_FILL:
685 				drawOpDraw_fillPolygon(p);
686 				break;
687 			//スタンプイメージセット
688 			case DRAW_OPSUB_SET_STAMP:
689 				drawOp_setStampImage(p);
690 				break;
691 			//選択範囲セット
692 			case DRAW_OPSUB_SET_SELECT:
693 				drawOp_setSelect(p, 1);
694 				break;
695 		}
696 	}
697 
698 	drawOpSub_freeFillPolygon(p);
699 
700 	return TRUE;
701 }
702 
703 /** 各アクション (キーなどの操作は無効) */
704 
_xorlasso_action(DrawData * p,int action)705 static mBool _xorlasso_action(DrawData *p,int action)
706 {
707 	if(action == DRAW_FUNCACTION_UNGRAB)
708 		return _xorlasso_release(p);
709 	else
710 		return FALSE;
711 }
712 
713 /** 押し時 */
714 
drawOpXor_lasso_press(DrawData * p,int opsubtype)715 mBool drawOpXor_lasso_press(DrawData *p,int opsubtype)
716 {
717 	if(!_fillpolygon_init(p)) return FALSE;
718 
719 	drawOpSub_setOpInfo(p, DRAW_OPTYPE_XOR_LASSO,
720 		_xorlasso_motion, _xorlasso_release, opsubtype);
721 
722 	p->w.funcAction = _xorlasso_action;
723 
724 	drawOpSub_getAreaPoint_int(p, p->w.pttmp);
725 
726 	drawOpSub_copyTmpPoint(p, 2);
727 
728 	drawOpXor_drawLasso(p, FALSE);
729 
730 	return TRUE;
731 }
732 
733 
734 //=========================================
735 // 定規の位置設定 (集中線、同心円[正円])
736 //=========================================
737 /*
738 	pttmp[0] : 押し位置
739 */
740 
741 
742 /** 離し */
743 
_rulepoint_release(DrawData * p)744 static mBool _rulepoint_release(DrawData *p)
745 {
746 	drawOpXor_drawCrossPoint(p);
747 
748 	return TRUE;
749 }
750 
751 /** 押し */
752 
drawOpXor_rulepoint_press(DrawData * p)753 mBool drawOpXor_rulepoint_press(DrawData *p)
754 {
755 	drawOpSub_setOpInfo(p, DRAW_OPTYPE_GENERAL,
756 		NULL, _rulepoint_release, 0);
757 
758 	drawOpSub_getAreaPoint_int(p, p->w.pttmp);
759 
760 	drawOpXor_drawCrossPoint(p);
761 
762 	return TRUE;
763 }
764 
765 
766 /********************************
767  * XOR 描画
768  ********************************/
769 
770 
771 /** XOR 直線描画
772  *
773  * pttmp[0] が始点、pttmp[1] が終点 */
774 
drawOpXor_drawline(DrawData * p)775 void drawOpXor_drawline(DrawData *p)
776 {
777 	mPixbuf *pixbuf;
778 	mBox box;
779 
780 	if((pixbuf = drawOpSub_beginAreaDraw()))
781 	{
782 		mPixbufLine(pixbuf, p->w.pttmp[0].x, p->w.pttmp[0].y,
783 			p->w.pttmp[1].x, p->w.pttmp[1].y, MPIXBUF_COL_XOR);
784 
785 		mBoxSetByPoint(&box, p->w.pttmp, p->w.pttmp + 1);
786 
787 		drawOpSub_endAreaDraw(pixbuf, &box);
788 	}
789 }
790 
791 /** XOR 四角形描画 (領域) */
792 
drawOpXor_drawBox_area(DrawData * p)793 void drawOpXor_drawBox_area(DrawData *p)
794 {
795 	mPixbuf *pixbuf;
796 	mBox box;
797 
798 	if((pixbuf = drawOpSub_beginAreaDraw()))
799 	{
800 		box.x = p->w.pttmp[0].x;
801 		box.y = p->w.pttmp[0].y;
802 		box.w = p->w.pttmp[1].x - p->w.pttmp[0].x + 1;
803 		box.h = p->w.pttmp[1].y - p->w.pttmp[0].y + 1;
804 
805 		mPixbufBoxSlow(pixbuf, box.x, box.y, box.w, box.h, MPIXBUF_COL_XOR);
806 
807 		drawOpSub_endAreaDraw(pixbuf, &box);
808 	}
809 }
810 
811 /** XOR 四角形描画 (イメージに対する) */
812 
drawOpXor_drawBox_image(DrawData * p)813 void drawOpXor_drawBox_image(DrawData *p)
814 {
815 	int x1,y1,x2,y2,i;
816 	mPoint pt[5];
817 	mPixbuf *pixbuf;
818 	mBox box;
819 
820 	if((pixbuf = drawOpSub_beginAreaDraw()))
821 	{
822 		x1 = p->w.pttmp[0].x, y1 = p->w.pttmp[0].y;
823 		x2 = p->w.pttmp[1].x, y2 = p->w.pttmp[1].y;
824 
825 		if(p->canvas_zoom != 1000)
826 			x2++, y2++;
827 
828 		//イメージ -> 領域座標
829 
830 		drawCalc_imageToarea_pt(p, pt, x1, y1);
831 		drawCalc_imageToarea_pt(p, pt + 1, x2, y1);
832 		drawCalc_imageToarea_pt(p, pt + 2, x2, y2);
833 		drawCalc_imageToarea_pt(p, pt + 3, x1, y2);
834 		pt[4] = pt[0];
835 
836 		//更新範囲
837 
838 		mBoxSetByPoints(&box, pt, 4);
839 
840 		//描画
841 
842 		if(x1 == x2 && y1 == y2)
843 			mPixbufSetPixel(pixbuf, pt[0].x, pt[0].y, MPIXBUF_COL_XOR);
844 		else if(x1 == x2 || y1 == y2)
845 			mPixbufLine(pixbuf, pt[0].x, pt[0].y, pt[2].x, pt[2].y, MPIXBUF_COL_XOR);
846 		else
847 		{
848 			for(i = 0; i < 4; i++)
849 				mPixbufLine_noend(pixbuf, pt[i].x, pt[i].y, pt[i + 1].x, pt[i + 1].y, MPIXBUF_COL_XOR);
850 		}
851 
852 		drawOpSub_endAreaDraw(pixbuf, &box);
853 	}
854 }
855 
856 /** XOR 円描画
857  *
858  * pttmp[0] が中心、pttmp[1] が半径(x,y) */
859 
drawOpXor_drawEllipse(DrawData * p)860 void drawOpXor_drawEllipse(DrawData *p)
861 {
862 	mPixbuf *pixbuf;
863 	mBox box;
864 	int x1,y1,x2,y2;
865 
866 	if((pixbuf = drawOpSub_beginAreaDraw()))
867 	{
868 		x1 = p->w.pttmp[0].x - p->w.pttmp[1].x;
869 		y1 = p->w.pttmp[0].y - p->w.pttmp[1].y;
870 		x2 = p->w.pttmp[0].x + p->w.pttmp[1].x;
871 		y2 = p->w.pttmp[0].y + p->w.pttmp[1].y;
872 
873 		mPixbufEllipse(pixbuf, x1, y1, x2, y2, MPIXBUF_COL_XOR);
874 
875 		box.x = x1, box.y = y1;
876 		box.w = x2 - x1 + 1, box.h = y2 - y1 + 1;
877 
878 		drawOpSub_endAreaDraw(pixbuf, &box);
879 	}
880 }
881 
882 /** XOR ベジェ曲線描画 */
883 
drawOpXor_drawBezier(DrawData * p,mBool erase)884 void drawOpXor_drawBezier(DrawData *p,mBool erase)
885 {
886 	mPixbuf *pixbuf;
887 
888 	//描画
889 
890 	if(!erase)
891 	{
892 		TileImage_freeAllTiles(p->tileimgTmp);
893 
894 		TileImageDrawInfo_clearDrawRect();
895 		TileImage_drawBezier_forXor(p->tileimgTmp, p->w.pttmp, p->w.opsubtype);
896 
897 		drawCalc_clipArea_toBox(p, p->w.boxtmp, &g_tileimage_dinfo.rcdraw);
898 	}
899 
900 	//XOR
901 
902 	if((pixbuf = drawOpSub_beginAreaDraw()))
903 	{
904 		TileImage_blendXorToPixbuf(p->tileimgTmp, pixbuf, p->w.boxtmp);
905 
906 		drawOpSub_endAreaDraw(pixbuf, p->w.boxtmp);
907 	}
908 }
909 
910 /** XOR 多角形描画 */
911 
drawOpXor_drawPolygon(DrawData * p)912 void drawOpXor_drawPolygon(DrawData *p)
913 {
914 	mPixbuf *pixbuf;
915 
916 	if((pixbuf = drawOpSub_beginAreaDraw()))
917 	{
918 		TileImage_blendXorToPixbuf(p->tileimgTmp, pixbuf, p->w.boxtmp);
919 
920 		drawOpSub_endAreaDraw(pixbuf, p->w.boxtmp);
921 	}
922 }
923 
924 /** XOR 投げ縄描画 */
925 
drawOpXor_drawLasso(DrawData * p,mBool erase)926 void drawOpXor_drawLasso(DrawData *p,mBool erase)
927 {
928 	mPixbuf *pixbuf;
929 	mBox box;
930 	mRect rc;
931 
932 	if((pixbuf = drawOpSub_beginAreaDraw()))
933 	{
934 		if(erase)
935 		{
936 			//消去
937 
938 			box.x = box.y = 0;
939 			box.w = p->szCanvas.w, box.h = p->szCanvas.h;
940 
941 			TileImage_blendXorToPixbuf(p->tileimgTmp, pixbuf, &box);
942 		}
943 		else
944 		{
945 			//新しい線描画
946 
947 			mRectSetByPoint_minmax(&rc, p->w.pttmp, p->w.pttmp + 1);
948 
949 			if(drawCalc_clipArea_toBox(p, &box, &rc))
950 			{
951 				TileImage_blendXorToPixbuf(p->tileimgTmp, pixbuf, &box);
952 
953 				TileImage_drawLineB(p->tileimgTmp, p->w.pttmp[1].x, p->w.pttmp[1].y,
954 					p->w.pttmp[0].x, p->w.pttmp[0].y, &p->w.rgbaDraw, FALSE);
955 
956 				TileImage_blendXorToPixbuf(p->tileimgTmp, pixbuf, &box);
957 			}
958 		}
959 
960 		drawOpSub_endAreaDraw(pixbuf, &box);
961 	}
962 }
963 
964 /** XOR 十字線描画 */
965 
drawOpXor_drawCrossPoint(DrawData * p)966 void drawOpXor_drawCrossPoint(DrawData *p)
967 {
968 	mPixbuf *pixbuf;
969 	int x,y;
970 	mBox box;
971 
972 	if((pixbuf = drawOpSub_beginAreaDraw()))
973 	{
974 		x = p->w.pttmp[0].x;
975 		y = p->w.pttmp[0].y;
976 
977 		mPixbufLineH(pixbuf, x - 9, y, 19, MPIXBUF_COL_XOR);
978 		mPixbufLineV(pixbuf, x, y - 9, 19, MPIXBUF_COL_XOR);
979 
980 		box.x = x - 9, box.y = y - 9;
981 		box.w = box.h = 19;
982 
983 		drawOpSub_endAreaDraw(pixbuf, &box);
984 	}
985 }
986 
987 /** XOR ブラシサイズ円描画 */
988 
989 /* pttmp[0] : 中心位置
990  * ntmp[0]  : 半径 px サイズ */
991 
drawOpXor_drawBrushSizeCircle(DrawData * p,mBool erase)992 void drawOpXor_drawBrushSizeCircle(DrawData *p,mBool erase)
993 {
994 	mPixbuf *pixbuf;
995 	mBox box;
996 	int r;
997 
998 	if(erase)
999 		box = p->w.boxtmp[0];
1000 	else
1001 	{
1002 		r = p->w.ntmp[0];
1003 
1004 		box.x = p->w.pttmp[0].x - r;
1005 		box.y = p->w.pttmp[0].y - r;
1006 		box.w = box.h = (r << 1) + 1;
1007 
1008 		p->w.boxtmp[0] = box;
1009 	}
1010 
1011 	//描画
1012 
1013 	if((pixbuf = drawOpSub_beginAreaDraw()))
1014 	{
1015 		mPixbufEllipse(pixbuf,
1016 			box.x, box.y, box.x + box.w - 1, box.y + box.h - 1, MPIXBUF_COL_XOR);
1017 
1018 		drawOpSub_endAreaDraw(pixbuf, &box);
1019 	}
1020 }
1021