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  * mPixbuf への描画関数
22  *****************************************/
23 
24 #include <math.h>
25 
26 #include "mDef.h"
27 #include "mPixbuf.h"
28 #include "mSysCol.h"
29 #include "mRectBox.h"
30 
31 #include "defCanvasInfo.h"
32 
33 
34 
35 
36 //===========================
37 // sub
38 //===========================
39 
40 
41 /** クリッピング付き直線描画 (blend A=0-128) */
42 
43 /* クリッピング範囲が異なっても、常に同じ位置に点が打たれるようにする。
44  * でないと、キャンバス全体を更新した時と描画時に範囲更新した時とで
45  * グリッドの線がずれる場合がある。 */
46 
_drawline_blend_clip(mPixbuf * p,int x1,int y1,int x2,int y2,uint32_t col,mRect * rc)47 static void _drawline_blend_clip(mPixbuf *p,int x1,int y1,int x2,int y2,uint32_t col,
48 	mRect *rc)
49 {
50 	int dx,dy,tmp;
51 	int64_t f,inc;
52 	mRect rcb;
53 
54 	//線からなる矩形が範囲外か
55 
56 	if(x1 < x2)
57 		rcb.x1 = x1, rcb.x2 = x2;
58 	else
59 		rcb.x1 = x2, rcb.x2 = x1;
60 
61 	if(y1 < y2)
62 		rcb.y1 = y1, rcb.y2 = y2;
63 	else
64 		rcb.y1 = y2, rcb.y2 = y1;
65 
66 	if(rcb.x2 < rc->x1 || rcb.x1 > rc->x2 || rcb.y2 < rc->y1 || rcb.y1 > rc->y2)
67 		return;
68 
69 	//
70 
71 	if(x1 == x2 && y1 == y2)
72 	{
73 		//1px
74 
75 		mPixbufSetPixel_blend128(p, x1, y1, col);
76 	}
77 	else if(y1 == y2)
78 	{
79 		//横線
80 
81 		x1 = rcb.x1, x2 = rcb.x2;
82 
83 		if(x1 < rc->x1) x1 = rc->x1;
84 		if(x2 > rc->x2) x2 = rc->x2;
85 
86 		mPixbufLineH_blend(p, x1, y1, x2 - x1 + 1, col, (col >> 24) << 1); //A=0-256
87 	}
88 	else if(x1 == x2)
89 	{
90 		//縦線
91 
92 		y1 = rcb.y1, y2 = rcb.y2;
93 
94 		if(y1 < rc->y1) y1 = rc->y1;
95 		if(y2 > rc->y2) y2 = rc->y2;
96 
97 		mPixbufLineV_blend(p, x1, y1, y2 - y1 + 1, col, (col >> 24) << 1);
98 	}
99 	else
100 	{
101 		//直線
102 
103 		dx = rcb.x2 - rcb.x1;
104 		dy = rcb.y2 - rcb.y1;
105 
106 		if(dx > dy)
107 		{
108 			//----- 横長
109 
110 			//x1 -> x2 の方向にする
111 
112 			if(x1 > x2)
113 			{
114 				x1 = rcb.x1, x2 = rcb.x2;
115 				tmp = y1, y1 = y2, y2 = tmp;
116 			}
117 
118 			inc = ((int64_t)(y2 - y1) << 16) / dx;
119 			f = (int64_t)y1 << 16;
120 
121 			//X クリッピング
122 
123 			if(x1 < rc->x1)
124 			{
125 				f += inc * (rc->x1 - x1);
126 				x1 = rc->x1;
127 			}
128 
129 			if(x2 > rc->x2) x2 = rc->x2;
130 
131 			//
132 
133 			tmp = (f + (1<<15)) >> 16;
134 
135 			if(y1 < y2)
136 			{
137 				//----- Y が下方向
138 
139 				//開始位置が範囲外
140 
141 				if(tmp > rc->y2) return;
142 
143 				//範囲内まで進める
144 
145 				while(tmp < rc->y1)
146 				{
147 					x1++;
148 					f += inc;
149 
150 					tmp = (f + (1<<15)) >> 16;
151 				}
152 
153 				//描画
154 
155 				for(; x1 <= x2; x1++, f += inc)
156 				{
157 					tmp = (f + (1<<15)) >> 16;
158 					if(tmp > rc->y2) break;
159 
160 					mPixbufSetPixel_blend128(p, x1, tmp, col);
161 				}
162 			}
163 			else
164 			{
165 				//----- Y が上方向
166 
167 				//開始位置が範囲外
168 
169 				if(tmp < rc->y1) return;
170 
171 				//範囲内まで進める
172 
173 				while(tmp > rc->y2)
174 				{
175 					x1++;
176 					f += inc;
177 
178 					tmp = (f + (1<<15)) >> 16;
179 				}
180 
181 				//描画
182 
183 				for(; x1 <= x2; x1++, f += inc)
184 				{
185 					tmp = (f + (1<<15)) >> 16;
186 					if(tmp < rc->y1) break;
187 
188 					mPixbufSetPixel_blend128(p, x1, tmp, col);
189 				}
190 			}
191 		}
192 		else
193 		{
194 			//------ 縦長
195 
196 			//y1 -> y2 の方向にする
197 
198 			if(y1 > y2)
199 			{
200 				y1 = rcb.y1, y2 = rcb.y2;
201 				tmp = x1, x1 = x2, x2 = tmp;
202 			}
203 
204 			inc = ((int64_t)(x2 - x1) << 16) / dy;
205 			f = (int64_t)x1 << 16;
206 
207 			//Y クリッピング
208 
209 			if(y1 < rc->y1)
210 			{
211 				f += inc * (rc->y1 - y1);
212 				y1 = rc->y1;
213 			}
214 
215 			if(y2 > rc->y2) y2 = rc->y2;
216 
217 			//
218 
219 			tmp = (f + (1<<15)) >> 16;
220 
221 			if(x1 < x2)
222 			{
223 				//----- X が右方向
224 
225 				//開始位置が範囲外
226 
227 				if(tmp > rc->x2) return;
228 
229 				//範囲内まで進める
230 
231 				while(tmp < rc->x1)
232 				{
233 					y1++;
234 					f += inc;
235 
236 					tmp = (f + (1<<15)) >> 16;
237 				}
238 
239 				//描画
240 
241 				for(; y1 <= y2; y1++, f += inc)
242 				{
243 					tmp = (f + (1<<15)) >> 16;
244 					if(tmp > rc->x2) break;
245 
246 					mPixbufSetPixel_blend128(p, tmp, y1, col);
247 				}
248 			}
249 			else
250 			{
251 				//----- X が左方向
252 
253 				//開始位置が範囲外
254 
255 				if(tmp < rc->x1) return;
256 
257 				//範囲内まで進める
258 
259 				while(tmp > rc->x2)
260 				{
261 					y1++;
262 					f += inc;
263 
264 					tmp = (f + (1<<15)) >> 16;
265 				}
266 
267 				//描画
268 
269 				for(; y1 <= y2; y1++, f += inc)
270 				{
271 					tmp = (f + (1<<15)) >> 16;
272 					if(tmp < rc->x1) break;
273 
274 					mPixbufSetPixel_blend128(p, tmp, y1, col);
275 				}
276 			}
277 		}
278 	}
279 }
280 
281 /** クリッピング付き破線直線描画
282  *
283  * @return (x2,y2) の位置のパターン番号 */
284 
_drawline_dash_clip(mPixbuf * p,int x1,int y1,int x2,int y2,int pat,mRect * rcclip)285 static int _drawline_dash_clip(mPixbuf *p,int x1,int y1,int x2,int y2,int pat,mRect *rcclip)
286 {
287 	int dx,dy,tmp,pat_end,dir;
288 	int64_t f,inc;
289 	mPoint min,max;
290 	mPixCol col[4];
291 	uint8_t *pd;
292 
293 	col[0] = col[1] = 0;
294 	col[2] = col[3] = MSYSCOL(WHITE);
295 
296 	//描画座標の最小、最大値
297 
298 	if(x1 < x2)
299 		min.x = x1, max.x = x2;
300 	else
301 		min.x = x2, max.x = x1;
302 
303 	if(y1 < y2)
304 		min.y = y1, max.y = y2;
305 	else
306 		min.y = y2, max.y = y1;
307 
308 	//
309 
310 	if(x1 == x2 && y1 == y2)
311 	{
312 		//====== 1px
313 
314 		if(rcclip->x1 <= x1 && x1 <= rcclip->x2 && rcclip->y1 <= y1 && y1 <= rcclip->y2)
315 			mPixbufSetPixel(p, x1, y1, col[pat]);
316 
317 		return pat;
318 	}
319 	else if(y1 == y2)
320 	{
321 		//====== 横線
322 
323 		pat_end = (pat + max.x - min.x) & 3;
324 
325 		if(min.x <= rcclip->x2 && max.x >= rcclip->x1
326 			&& y1 >= rcclip->y1 && y1 <= rcclip->y2)
327 		{
328 			dir = (x1 < x2)? 1: -1;
329 
330 			x1 = min.x, x2 = max.x;
331 			if(dir < 0) pat = pat_end;
332 
333 			if(x1 < rcclip->x1)
334 			{
335 				pat = (pat + (rcclip->x1 - x1) * dir) & 3;
336 				x1 = rcclip->x1;
337 			}
338 
339 			if(x2 > rcclip->x2) x2 = rcclip->x2;
340 
341 			pd = mPixbufGetBufPtFast(p, x1, y1);
342 
343 			for(dx = x2 - x1 + 1; dx; dx--, pd += p->bpp, pat = (pat + dir) & 3)
344 				(p->setbuf)(pd, col[pat]);
345 		}
346 
347 		return pat_end;
348 	}
349 	else if(x1 == x2)
350 	{
351 		//====== 縦線
352 
353 		pat_end = (pat + max.y - min.y) & 3;
354 
355 		if(x1 >= rcclip->x1 && x1 <= rcclip->x2
356 			&& min.y <= rcclip->y2 && max.y >= rcclip->y1)
357 		{
358 			dir = (y1 < y2)? 1: -1;
359 
360 			y1 = min.y, y2 = max.y;
361 			if(dir < 0) pat = pat_end;
362 
363 			if(y1 < rcclip->y1)
364 			{
365 				pat = (pat + (rcclip->y1 - y1) * dir) & 3;
366 				y1 = rcclip->y1;
367 			}
368 
369 			if(y2 > rcclip->y2) y2 = rcclip->y2;
370 
371 			pd = mPixbufGetBufPtFast(p, x1, y1);
372 
373 			for(dy = y2 - y1 + 1; dy; dy--, pd += p->pitch_dir, pat = (pat + dir) & 3)
374 				(p->setbuf)(pd, col[pat]);
375 		}
376 
377 		return pat_end;
378 	}
379 	else
380 	{
381 		//====== 斜め
382 
383 		dx = max.x - min.x;
384 		dy = max.y - min.y;
385 
386 		if(dx > dy)
387 			pat_end = (pat + max.x - min.x) & 3;
388 		else
389 			pat_end = (pat + max.y - min.y) & 3;
390 
391 		//範囲外
392 
393 		if(min.x > rcclip->x2 || max.x < rcclip->x1
394 			|| min.y > rcclip->y2 || max.y < rcclip->y1)
395 			return pat_end;
396 
397 		//
398 
399 		if(dx > dy)
400 		{
401 			//----- 横長
402 
403 			dir = (x1 < x2)? 1: -1;
404 
405 			//x1 -> x2 の方向にする
406 
407 			if(dir < 0)
408 			{
409 				x1 = min.x, x2 = max.x;
410 				tmp = y1, y1 = y2, y2 = tmp;
411 				pat = pat_end;
412 			}
413 
414 			inc = ((int64_t)(y2 - y1) << 16) / dx;
415 			f = (int64_t)y1 << 16;
416 
417 			//X クリッピング
418 
419 			if(x1 < rcclip->x1)
420 			{
421 				pat = (pat + (rcclip->x1 - x1) * dir) & 3;
422 				f += inc * (rcclip->x1 - x1);
423 				x1 = rcclip->x1;
424 			}
425 
426 			if(x2 > rcclip->x2) x2 = rcclip->x2;
427 
428 			//
429 
430 			tmp = (f + (1<<15)) >> 16;
431 
432 			if(y1 < y2)
433 			{
434 				//----- Y が下方向
435 
436 				//開始位置が範囲外
437 
438 				if(tmp > rcclip->y2) return pat_end;
439 
440 				//範囲内まで進める
441 
442 				while(tmp < rcclip->y1)
443 				{
444 					x1++;
445 					f += inc;
446 					pat = (pat + dir) & 3;
447 
448 					tmp = (f + (1<<15)) >> 16;
449 				}
450 
451 				//描画
452 
453 				for(; x1 <= x2; x1++, f += inc, pat = (pat + dir) & 3)
454 				{
455 					tmp = (f + (1<<15)) >> 16;
456 					if(tmp > rcclip->y2) break;
457 
458 					mPixbufSetPixel(p, x1, tmp, col[pat]);
459 				}
460 			}
461 			else
462 			{
463 				//----- Y が上方向
464 
465 				//開始位置が範囲外
466 
467 				if(tmp < rcclip->y1) return pat_end;
468 
469 				//範囲内まで進める
470 
471 				while(tmp > rcclip->y2)
472 				{
473 					x1++;
474 					f += inc;
475 					pat = (pat + dir) & 3;
476 
477 					tmp = (f + (1<<15)) >> 16;
478 				}
479 
480 				//描画
481 
482 				for(; x1 <= x2; x1++, f += inc, pat = (pat + dir) & 3)
483 				{
484 					tmp = (f + (1<<15)) >> 16;
485 					if(tmp < rcclip->y1) break;
486 
487 					mPixbufSetPixel(p, x1, tmp, col[pat]);
488 				}
489 			}
490 		}
491 		else
492 		{
493 			//------ 縦長
494 
495 			dir = (y1 < y2)? 1: -1;
496 
497 			//y1 -> y2 の方向にする
498 
499 			if(y1 > y2)
500 			{
501 				y1 = min.y, y2 = max.y;
502 				tmp = x1, x1 = x2, x2 = tmp;
503 				pat = pat_end;
504 			}
505 
506 			inc = ((int64_t)(x2 - x1) << 16) / dy;
507 			f = (int64_t)x1 << 16;
508 
509 			//Y クリッピング
510 
511 			if(y1 < rcclip->y1)
512 			{
513 				pat = (pat + (rcclip->y1 - y1) * dir) & 3;
514 				f += inc * (rcclip->y1 - y1);
515 				y1 = rcclip->y1;
516 			}
517 
518 			if(y2 > rcclip->y2) y2 = rcclip->y2;
519 
520 			//
521 
522 			tmp = (f + (1<<15)) >> 16;
523 
524 			if(x1 < x2)
525 			{
526 				//----- X が右方向
527 
528 				//開始位置が範囲外
529 
530 				if(tmp > rcclip->x2) return pat_end;
531 
532 				//範囲内まで進める
533 
534 				while(tmp < rcclip->x1)
535 				{
536 					y1++;
537 					f += inc;
538 					pat = (pat + dir) & 3;
539 
540 					tmp = (f + (1<<15)) >> 16;
541 				}
542 
543 				//描画
544 
545 				for(; y1 <= y2; y1++, f += inc, pat = (pat + dir) & 3)
546 				{
547 					tmp = (f + (1<<15)) >> 16;
548 					if(tmp > rcclip->x2) break;
549 
550 					mPixbufSetPixel(p, tmp, y1, col[pat]);
551 				}
552 			}
553 			else
554 			{
555 				//----- X が左方向
556 
557 				//開始位置が範囲外
558 
559 				if(tmp < rcclip->x1) return pat_end;
560 
561 				//範囲内まで進める
562 
563 				while(tmp > rcclip->x2)
564 				{
565 					y1++;
566 					f += inc;
567 					pat = (pat + dir) & 3;
568 
569 					tmp = (f + (1<<15)) >> 16;
570 				}
571 
572 				//描画
573 
574 				for(; y1 <= y2; y1++, f += inc, pat = (pat + dir) & 3)
575 				{
576 					tmp = (f + (1<<15)) >> 16;
577 					if(tmp < rcclip->x1) break;
578 
579 					mPixbufSetPixel(p, tmp, y1, col[pat]);
580 				}
581 			}
582 		}
583 
584 		return pat_end;
585 	}
586 }
587 
588 
589 //===========================
590 //
591 //===========================
592 
593 
594 /** 白黒破線の十字線描画
595  *
596  * キャンバスビューのルーペ時。
597  *
598  * @param x    左側の垂直線の位置
599  * @param y    上側の水平線の位置
600  * @param size 2つの線の間隔
601  * @param box  描画範囲 */
602 
pixbufDraw_cross_dash(mPixbuf * pixbuf,int x,int y,int size,mBox * boxarea)603 void pixbufDraw_cross_dash(mPixbuf *pixbuf,int x,int y,int size,mBox *boxarea)
604 {
605 	mPixCol col[2];
606 	mBox box;
607 	uint8_t *pd;
608 	int i,n;
609 
610 	if(!mPixbufGetClipBox_box(pixbuf, &box, boxarea))
611 		return;
612 
613 	col[0] = 0;
614 	col[1] = MSYSCOL(WHITE);
615 
616 	//水平線、上 (実際には y - 1 の位置)
617 
618 	n = y - 1;
619 
620 	if(box.y <= n && n < box.y + box.h)
621 	{
622 		pd = mPixbufGetBufPtFast(pixbuf, box.x, n);
623 		n = box.x;
624 
625 		for(i = box.w; i; i--, pd += pixbuf->bpp, n++)
626 		{
627 			if(n < x || n >= x + size)
628 				(pixbuf->setbuf)(pd, col[(n >> 1) & 1]);
629 		}
630 	}
631 
632 	//水平線、下
633 
634 	n = y + size;
635 
636 	if(box.y <= n && n < box.y + box.h)
637 	{
638 		pd = mPixbufGetBufPtFast(pixbuf, box.x, n);
639 		n = box.x;
640 
641 		for(i = box.w; i; i--, pd += pixbuf->bpp, n++)
642 		{
643 			if(n < x || n >= x + size)
644 				(pixbuf->setbuf)(pd, col[(n >> 1) & 1]);
645 		}
646 	}
647 
648 	//垂直線、左
649 
650 	n = x - 1;
651 
652 	if(box.x <= n && n < box.x + box.w)
653 	{
654 		pd = mPixbufGetBufPtFast(pixbuf, n, box.y);
655 		n = box.y;
656 
657 		for(i = box.h; i; i--, pd += pixbuf->pitch_dir, n++)
658 		{
659 			if(n < y || n >= y + size)
660 				(pixbuf->setbuf)(pd, col[(n >> 1) & 1]);
661 		}
662 	}
663 
664 	//垂直線、右
665 
666 	n = x + size;
667 
668 	if(box.x <= n && n < box.x + box.w)
669 	{
670 		pd = mPixbufGetBufPtFast(pixbuf, n, box.y);
671 		n = box.y;
672 
673 		for(i = box.h; i; i--, pd += pixbuf->pitch_dir, n++)
674 		{
675 			if(n < y || n >= y + size)
676 				(pixbuf->setbuf)(pd, col[(n >> 1) & 1]);
677 		}
678 	}
679 }
680 
681 /** 白黒破線の矩形枠描画 (フィルタプレビュー用) */
682 
pixbufDraw_dashBox_mono(mPixbuf * pixbuf,int x,int y,int w,int h)683 void pixbufDraw_dashBox_mono(mPixbuf *pixbuf,int x,int y,int w,int h)
684 {
685 	mPixCol col[2];
686 	int i,n,pos = 0;
687 
688 	col[0] = 0;
689 	col[1] = MSYSCOL(WHITE);
690 
691 	//上
692 
693 	for(i = 0; i < w; i++, pos++)
694 		mPixbufSetPixel(pixbuf, x + i, y, col[(pos >> 1) & 1]);
695 
696 	//右
697 
698 	n = x + w - 1;
699 
700 	for(i = 1; i < h; i++, pos++)
701 		mPixbufSetPixel(pixbuf, n, y + i, col[(pos >> 1) & 1]);
702 
703 	//下
704 
705 	n = y + h - 1;
706 
707 	for(i = w - 2; i >= 0; i--, pos++)
708 		mPixbufSetPixel(pixbuf, x + i, n, col[(pos >> 1) & 1]);
709 
710 	//左
711 
712 	for(i = h - 2; i > 0; i--, pos++)
713 		mPixbufSetPixel(pixbuf, x, y + i, col[(pos >> 1) & 1]);
714 }
715 
716 /** 選択範囲の枠を描画 */
717 
pixbufDrawSelectBox(mPixbuf * pixbuf,mBox * boximg,CanvasDrawInfo * info)718 void pixbufDrawSelectBox(mPixbuf *pixbuf,mBox *boximg,CanvasDrawInfo *info)
719 {
720 	mRect rcclip;
721 	mPoint pt[4];
722 	double x1,y1,x2,y2;
723 	int pat;
724 
725 	//描画先のクリッピング範囲 (rect)
726 
727 	mRectSetByBox(&rcclip, &info->boxdst);
728 
729 	//
730 
731 	x1 = boximg->x, y1 = boximg->y;
732 	x2 = boximg->x + boximg->w, y2 = boximg->y + boximg->h;
733 
734 	if(info->param->rd == 0)
735 	{
736 		//----- 回転なし
737 
738 		CanvasDrawInfo_imageToarea_pt(info, x1, y1, pt);
739 		CanvasDrawInfo_imageToarea_pt(info, x2, y2, pt + 1);
740 
741 		//左上を -1px
742 
743 		pt[0].y--;
744 
745 		if(info->mirror)
746 			pt[0].x++;
747 		else
748 			pt[0].x--;
749 
750 		//描画
751 
752 		pat = _drawline_dash_clip(pixbuf, pt[0].x, pt[0].y, pt[1].x, pt[0].y, 0, &rcclip);
753 		pat = _drawline_dash_clip(pixbuf, pt[1].x, pt[0].y, pt[1].x, pt[1].y, pat, &rcclip);
754 		pat = _drawline_dash_clip(pixbuf, pt[1].x, pt[1].y, pt[0].x, pt[1].y, pat, &rcclip);
755 		_drawline_dash_clip(pixbuf, pt[0].x, pt[1].y, pt[0].x, pt[0].y, pat, &rcclip);
756 	}
757 	else
758 	{
759 		//----- 回転あり
760 
761 		//左上を -1px するため、イメージ座標で 1px に相当する値を引く
762 
763 		x1 -= info->param->scalediv;
764 		y1 -= info->param->scalediv;
765 
766 		CanvasDrawInfo_imageToarea_pt(info, x1, y1, pt);
767 		CanvasDrawInfo_imageToarea_pt(info, x2, y1, pt + 1);
768 		CanvasDrawInfo_imageToarea_pt(info, x2, y2, pt + 2);
769 		CanvasDrawInfo_imageToarea_pt(info, x1, y2, pt + 3);
770 
771 		//描画
772 
773 		pat = _drawline_dash_clip(pixbuf, pt[0].x, pt[0].y, pt[1].x, pt[1].y, 0, &rcclip);
774 		pat = _drawline_dash_clip(pixbuf, pt[1].x, pt[1].y, pt[2].x, pt[2].y, pat, &rcclip);
775 		pat = _drawline_dash_clip(pixbuf, pt[2].x, pt[2].y, pt[3].x, pt[3].y, pat, &rcclip);
776 		_drawline_dash_clip(pixbuf, pt[3].x, pt[3].y, pt[0].x, pt[0].y, pat, &rcclip);
777 	}
778 }
779 
780 /** キャンバスにグリッド線描画
781  *
782  * @param boxdst 描画先の範囲
783  * @param boximg boxdst の範囲に相当するイメージ座標での範囲
784  * @param rcgrid グリッドを描画するイメージ範囲 (NULL で全体) */
785 
pixbufDrawGrid(mPixbuf * pixbuf,mBox * boxdst,mBox * boximg,int gridw,int gridh,uint32_t col,mRect * rcgrid,CanvasDrawInfo * info)786 void pixbufDrawGrid(mPixbuf *pixbuf,mBox *boxdst,mBox *boximg,
787 	int gridw,int gridh,uint32_t col,mRect *rcgrid,CanvasDrawInfo *info)
788 {
789 	mRect rcclip;
790 	int top,bottom,i;
791 	double inc[4],x1,y1,x2,y2,incx,incy;
792 	mBool inarea;
793 
794 	//描画先のクリッピング範囲 (rect)
795 
796 	mRectSetByBox(&rcclip, boxdst);
797 
798 	//イメージ座標 +1 時のキャンバス座標変化値
799 
800 	CanvasDrawInfo_getImageIncParam(info, inc);
801 
802 	//--------- 縦線
803 
804 	top = boximg->x;
805 	bottom = boximg->x + boximg->w - 1;
806 	inarea = TRUE;
807 
808 	if(rcgrid)
809 	{
810 		//グリッド範囲あり
811 
812 		if(top > rcgrid->x2 || bottom < rcgrid->x1)
813 			inarea = FALSE;
814 		else
815 		{
816 			if(top < rcgrid->x1) top = rcgrid->x1;
817 			if(bottom > rcgrid->x2) bottom = rcgrid->x2;
818 
819 			top = (top - rcgrid->x1) / gridw * gridw + rcgrid->x1;
820 			bottom = (bottom - rcgrid->x1) / gridw * gridw + rcgrid->x1;
821 
822 			CanvasDrawInfo_imageToarea(info, top, rcgrid->y1, &x1, &y1);
823 			CanvasDrawInfo_imageToarea(info, top, rcgrid->y2, &x2, &y2);
824 		}
825 	}
826 	else
827 	{
828 		//全体
829 
830 		top = top / gridw * gridw;
831 		bottom = bottom / gridw * gridw;
832 
833 		CanvasDrawInfo_imageToarea(info, top, 0, &x1, &y1);
834 		CanvasDrawInfo_imageToarea(info, top, info->imgh, &x2, &y2);
835 	}
836 
837 	//描画
838 
839 	if(inarea)
840 	{
841 		incx = inc[0] * gridw;
842 		incy = inc[1] * gridw;
843 
844 		for(i = top; i <= bottom; i += gridw)
845 		{
846 			_drawline_blend_clip(pixbuf, x1, y1, x2, y2, col, &rcclip);
847 
848 			x1 += incx, y1 += incy;
849 			x2 += incx, y2 += incy;
850 		}
851 	}
852 
853 	//--------- 横線
854 
855 	top = boximg->y;
856 	bottom = boximg->y + boximg->h - 1;
857 	inarea = TRUE;
858 
859 	if(rcgrid)
860 	{
861 		//グリッド範囲あり
862 
863 		if(top > rcgrid->y2 || bottom < rcgrid->y1)
864 			inarea = FALSE;
865 		else
866 		{
867 			if(top < rcgrid->y1) top = rcgrid->y1;
868 			if(bottom > rcgrid->y2) bottom = rcgrid->y2;
869 
870 			top = (top - rcgrid->y1) / gridh * gridh + rcgrid->y1;
871 			bottom = (bottom - rcgrid->y1) / gridh * gridh + rcgrid->y1;
872 
873 			CanvasDrawInfo_imageToarea(info, rcgrid->x1, top, &x1, &y1);
874 			CanvasDrawInfo_imageToarea(info, rcgrid->x2, top, &x2, &y2);
875 		}
876 	}
877 	else
878 	{
879 		//全体
880 
881 		top = top / gridh * gridh;
882 		bottom = bottom / gridh * gridh;
883 
884 		CanvasDrawInfo_imageToarea(info, 0, top, &x1, &y1);
885 		CanvasDrawInfo_imageToarea(info, info->imgw, top, &x2, &y2);
886 	}
887 
888 	//描画
889 
890 	if(inarea)
891 	{
892 		incx = inc[2] * gridh;
893 		incy = inc[3] * gridh;
894 
895 		for(i = top; i <= bottom; i += gridh)
896 		{
897 			_drawline_blend_clip(pixbuf, x1, y1, x2, y2, col, &rcclip);
898 
899 			x1 += incx, y1 += incy;
900 			x2 += incx, y2 += incy;
901 		}
902 	}
903 }
904