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