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  * 計算関連
24  *****************************************/
25 
26 #include <stdlib.h>
27 #include <math.h>
28 
29 #include "mDef.h"
30 #include "mRectBox.h"
31 
32 #include "defDraw.h"
33 #include "defConfig.h"
34 #include "defMacros.h"
35 
36 #include "draw_calc.h"
37 
38 #include "TileImage.h"
39 
40 
41 
42 /** 現在の倍率&角度から、キャンバス用パラメータセット */
43 
drawCalc_setCanvasViewParam(DrawData * p)44 void drawCalc_setCanvasViewParam(DrawData *p)
45 {
46 	double d;
47 
48 	d = p->canvas_zoom * 0.001;
49 
50 	p->viewparam.scale = d;
51 	p->viewparam.scalediv = 1.0 / d;
52 
53 	d = p->canvas_angle * M_MATH_PI / 18000.0;
54 
55 	p->viewparam.rd = d;
56 	p->viewparam.cos = cos(d);
57 	p->viewparam.sin = sin(d);
58 	p->viewparam.cosrev = p->viewparam.cos;
59 	p->viewparam.sinrev = -(p->viewparam.sin);
60 }
61 
62 /** 指定位置がキャンバスの範囲内か */
63 
drawCalc_isPointInCanvasArea(DrawData * p,mPoint * pt)64 mBool drawCalc_isPointInCanvasArea(DrawData *p,mPoint *pt)
65 {
66 	return (pt->x >= 0 && pt->x < p->szCanvas.w && pt->y >= 0 && pt->y < p->szCanvas.h);
67 }
68 
69 
70 //==============================
71 // 座標変換
72 //==============================
73 
74 
75 /** 領域座標 (double) -> イメージ位置 (double) */
76 
drawCalc_areaToimage_double(DrawData * p,double * dx,double * dy,double x,double y)77 void drawCalc_areaToimage_double(DrawData *p,double *dx,double *dy,double x,double y)
78 {
79 	double xx,yy;
80 
81 	x += p->ptScroll.x - (p->szCanvas.w >> 1);
82 	y += p->ptScroll.y - (p->szCanvas.h >> 1);
83 
84 	xx = x * p->viewparam.cosrev - y * p->viewparam.sinrev;
85 	yy = x * p->viewparam.sinrev + y * p->viewparam.cosrev;
86 
87 	if(p->canvas_mirror) xx = -xx;
88 
89 	*dx = xx * p->viewparam.scalediv + p->imgoriginX;
90 	*dy = yy * p->viewparam.scalediv + p->imgoriginY;
91 }
92 
93 /** 領域座標 (mPoint) -> イメージ位置 (mDoublePoint) */
94 
drawCalc_areaToimage_double_pt(DrawData * p,mDoublePoint * dst,mPoint * src)95 void drawCalc_areaToimage_double_pt(DrawData *p,mDoublePoint *dst,mPoint *src)
96 {
97 	drawCalc_areaToimage_double(p, &dst->x, &dst->y, src->x, src->y);
98 }
99 
100 /** 領域座標 (double) -> イメージ位置 (mPoint) */
101 
drawCalc_areaToimage_pt(DrawData * p,mPoint * pt,double x,double y)102 void drawCalc_areaToimage_pt(DrawData *p,mPoint *pt,double x,double y)
103 {
104 	drawCalc_areaToimage_double(p, &x, &y, x, y);
105 
106 	pt->x = floor(x);
107 	pt->y = floor(y);
108 }
109 
110 /** キャンバス座標における相対値をイメージ座標での相対値に変換 */
111 
drawCalc_areaToimage_relative(DrawData * p,mPoint * dst,mPoint * src)112 void drawCalc_areaToimage_relative(DrawData *p,mPoint *dst,mPoint *src)
113 {
114 	dst->x = (int)((src->x * p->viewparam.cosrev - src->y * p->viewparam.sinrev) * p->viewparam.scalediv);
115 	dst->y = (int)((src->x * p->viewparam.sinrev + src->y * p->viewparam.cosrev) * p->viewparam.scalediv);
116 
117 	if(p->canvas_mirror)
118 		dst->x = -(dst->x);
119 }
120 
121 /** イメージ位置 (int) -> 領域座標 (mPoint) */
122 
drawCalc_imageToarea_pt(DrawData * p,mPoint * dst,int x,int y)123 void drawCalc_imageToarea_pt(DrawData *p,mPoint *dst,int x,int y)
124 {
125 	double dx,dy;
126 
127 	dx = (x - p->imgoriginX) * p->viewparam.scale;
128 	dy = (y - p->imgoriginY) * p->viewparam.scale;
129 
130 	if(p->canvas_mirror) dx = -dx;
131 
132 	dst->x = round((dx * p->viewparam.cos - dy * p->viewparam.sin) + (p->szCanvas.w >> 1) - p->ptScroll.x);
133 	dst->y = round((dx * p->viewparam.sin + dy * p->viewparam.cos) + (p->szCanvas.h >> 1) - p->ptScroll.y);
134 }
135 
136 /** イメージ位置 (double) -> 領域座標 (mPoint) */
137 
drawCalc_imageToarea_pt_double(DrawData * p,mPoint * dst,double x,double y)138 void drawCalc_imageToarea_pt_double(DrawData *p,mPoint *dst,double x,double y)
139 {
140 	double dx,dy;
141 
142 	dx = (x - p->imgoriginX) * p->viewparam.scale;
143 	dy = (y - p->imgoriginY) * p->viewparam.scale;
144 
145 	if(p->canvas_mirror) dx = -dx;
146 
147 	dst->x = round((dx * p->viewparam.cos - dy * p->viewparam.sin) + (p->szCanvas.w >> 1) - p->ptScroll.x);
148 	dst->y = round((dx * p->viewparam.sin + dy * p->viewparam.cos) + (p->szCanvas.h >> 1) - p->ptScroll.y);
149 }
150 
151 /** キャンバス中央におけるイメージ位置取得 */
152 
drawCalc_getImagePos_atCanvasCenter(DrawData * p,double * px,double * py)153 void drawCalc_getImagePos_atCanvasCenter(DrawData *p,double *px,double *py)
154 {
155 	drawCalc_areaToimage_double(p, px, py, p->szCanvas.w * 0.5, p->szCanvas.h * 0.5);
156 }
157 
158 /** イメージ座標 (mBox) -> 領域座標 (mBox)
159  *
160  * @return FALSE で範囲外 */
161 
drawCalc_imageToarea_box(DrawData * p,mBox * dst,mBox * src)162 mBool drawCalc_imageToarea_box(DrawData *p,mBox *dst,mBox *src)
163 {
164 	mPoint pt[4];
165 	int x1,y1,x2,y2,i;
166 
167 	//右・下端は+1
168 
169 	x1 = src->x, y1 = src->y;
170 	x2 = x1 + src->w;
171 	y2 = y1 + src->h;
172 
173 	//最小・最大値
174 
175 	if(p->canvas_angle == 0)
176 	{
177 		drawCalc_imageToarea_pt(p, pt, x1, y1);
178 		drawCalc_imageToarea_pt(p, pt + 1, x2, y2);
179 
180 		if(pt[0].x < pt[1].x)
181 			x1 = pt[0].x, x2 = pt[1].x;
182 		else
183 			x1 = pt[1].x, x2 = pt[0].x;
184 
185 		if(pt[0].y < pt[1].y)
186 			y1 = pt[0].y, y2 = pt[1].y;
187 		else
188 			y1 = pt[1].y, y2 = pt[0].y;
189 	}
190 	else
191 	{
192 		drawCalc_imageToarea_pt(p, pt    , x1, y1);
193 		drawCalc_imageToarea_pt(p, pt + 1, x2, y1);
194 		drawCalc_imageToarea_pt(p, pt + 2, x1, y2);
195 		drawCalc_imageToarea_pt(p, pt + 3, x2, y2);
196 
197 		x1 = x2 = pt[0].x;
198 		y1 = y2 = pt[0].y;
199 
200 		for(i = 1; i < 4; i++)
201 		{
202 			if(x1 > pt[i].x) x1 = pt[i].x;
203 			if(y1 > pt[i].y) y1 = pt[i].y;
204 			if(x2 < pt[i].x) x2 = pt[i].x;
205 			if(y2 < pt[i].y) y2 = pt[i].y;
206 		}
207 	}
208 
209 	//念のため範囲拡張
210 
211 	x1--, y1--;
212 	x2++, y2++;
213 
214 	//範囲外判定
215 
216 	if(x2 < 0 || y2 < 0 || x1 >= p->szCanvas.w || y1 >= p->szCanvas.h)
217 		return FALSE;
218 
219 	//調整
220 
221 	if(x1 < 0) x1 = 0;
222 	if(y1 < 0) y1 = 0;
223 	if(x2 >= p->szCanvas.w) x2 = p->szCanvas.w - 1;
224 	if(y2 >= p->szCanvas.h) y2 = p->szCanvas.h - 1;
225 
226 	//
227 
228 	dst->x = x1, dst->y = y1;
229 	dst->w = x2 - x1 + 1;
230 	dst->h = y2 - y1 + 1;
231 
232 	return TRUE;
233 }
234 
235 /** 領域座標 (mBox) -> イメージ座標 (mBox)
236  *
237  * @return FALSE でイメージの範囲外 */
238 
drawCalc_areaToimage_box(DrawData * p,mBox * dst,mBox * src)239 mBool drawCalc_areaToimage_box(DrawData *p,mBox *dst,mBox *src)
240 {
241 	mPoint pt[4];
242 	mRect rc;
243 	int i;
244 
245 	//四隅をイメージ位置に変換
246 
247 	drawCalc_areaToimage_pt(p, pt    , src->x - 1, src->y - 1);
248 	drawCalc_areaToimage_pt(p, pt + 1, src->x + src->w, src->y - 1);
249 	drawCalc_areaToimage_pt(p, pt + 2, src->x - 1, src->y + src->h);
250 	drawCalc_areaToimage_pt(p, pt + 3, src->x + src->w, src->y + src->h);
251 
252 	//範囲
253 
254 	rc.x1 = rc.x2 = pt[0].x;
255 	rc.y1 = rc.y2 = pt[0].y;
256 
257 	for(i = 1; i < 4; i++)
258 	{
259         if(pt[i].x < rc.x1) rc.x1 = pt[i].x;
260         if(pt[i].y < rc.y1) rc.y1 = pt[i].y;
261         if(pt[i].x > rc.x2) rc.x2 = pt[i].x;
262         if(pt[i].y > rc.y2) rc.y2 = pt[i].y;
263 	}
264 
265 	//イメージ範囲調整
266 
267 	return drawCalc_getImageBox_rect(p, dst, &rc);
268 }
269 
270 
271 //==============================
272 // 範囲
273 //==============================
274 
275 
276 /** mRect を領域の範囲内にクリッピングして mBox へ
277  *
278  * @param dst 範囲がない場合、w = h = 0 */
279 
drawCalc_clipArea_toBox(DrawData * p,mBox * dst,mRect * src)280 mBool drawCalc_clipArea_toBox(DrawData *p,mBox *dst,mRect *src)
281 {
282 	int x1,y1,x2,y2;
283 
284 	if(src->x1 > src->x2 || src->y1 > src->y2
285 		|| src->x2 < 0 || src->y2 < 0
286 		|| src->x1 >= p->szCanvas.w || src->y1 >= p->szCanvas.h)
287 	{
288 		dst->w = dst->h = 0;
289 		return FALSE;
290 	}
291 	else
292 	{
293 		x1 = (src->x1 < 0)? 0: src->x1;
294 		y1 = (src->y1 < 0)? 0: src->y1;
295 		x2 = (src->x2 >= p->szCanvas.w)? p->szCanvas.w - 1: src->x2;
296 		y2 = (src->y2 >= p->szCanvas.h)? p->szCanvas.h - 1: src->y2;
297 
298 		dst->x = x1, dst->y = y1;
299 		dst->w = x2 - x1 + 1;
300 		dst->h = y2 - y1 + 1;
301 
302 		return TRUE;
303 	}
304 }
305 
306 /** mRect をイメージ範囲内にクリッピング */
307 
drawCalc_clipImageRect(DrawData * p,mRect * rc)308 mBool drawCalc_clipImageRect(DrawData *p,mRect *rc)
309 {
310 	int x1,y1,x2,y2;
311 
312 	if(mRectIsEmpty(rc)) return FALSE;
313 
314 	x1 = rc->x1, y1 = rc->y1;
315 	x2 = rc->x2, y2 = rc->y2;
316 
317 	//範囲外
318 
319 	if(x2 < 0 || y2 < 0 || x1 >= p->imgw || y1 >= p->imgh)
320 		return FALSE;
321 
322 	//調整
323 
324 	if(x1 < 0) x1 = 0;
325 	if(y1 < 0) y1 = 0;
326 	if(x2 >= p->imgw) x2 = p->imgw - 1;
327 	if(y2 >= p->imgh) y2 = p->imgh - 1;
328 
329 	//セット
330 
331 	rc->x1 = x1, rc->y1 = y1;
332 	rc->x2 = x2, rc->y2 = y2;
333 
334 	return TRUE;
335 }
336 
337 /** mRect をイメージの範囲内に収めて mBox へ
338  *
339  * @return FALSE で範囲外、または範囲が空 */
340 
drawCalc_getImageBox_rect(DrawData * p,mBox * dst,mRect * rc)341 mBool drawCalc_getImageBox_rect(DrawData *p,mBox *dst,mRect *rc)
342 {
343 	mRect rc2;
344 
345 	rc2 = *rc;
346 
347 	if(!drawCalc_clipImageRect(p, &rc2))
348 	{
349 		dst->w = dst->h = 0;
350 		return FALSE;
351 	}
352 	else
353 	{
354 		dst->x = rc2.x1;
355 		dst->y = rc2.y1;
356 		dst->w = rc2.x2 - rc2.x1 + 1;
357 		dst->h = rc2.y2 - rc2.y1 + 1;
358 
359 		return TRUE;
360 	}
361 }
362 
363 /** mBox (イメージ座標) の範囲を結合
364  *
365  * x < 0 の場合は範囲なしとする。
366  *
367  * @return FALSE で両方共範囲なし */
368 
drawCalc_unionImageBox(mBox * dst,mBox * src)369 mBool drawCalc_unionImageBox(mBox *dst,mBox *src)
370 {
371 	if(dst->x < 0 && src->x < 0)
372 		//両方共範囲なし
373 		return FALSE;
374 	else if(src->x < 0)
375 		//src が範囲なし => dst は変化なし
376 		return TRUE;
377 	else if(dst->x < 0)
378 	{
379 		//dst が範囲なし => src をコピー
380 
381 		*dst = *src;
382 		return TRUE;
383 	}
384 	else
385 	{
386 		//範囲合成
387 
388 		mBoxUnion(dst, src);
389 		return TRUE;
390 	}
391 }
392 
393 /** src と、src を mx,my 分相対移動した範囲を合成 */
394 
drawCalc_unionRect_relmove(mRect * dst,mRect * src,int mx,int my)395 void drawCalc_unionRect_relmove(mRect *dst,mRect *src,int mx,int my)
396 {
397 	*dst = *src;
398 	mRectRelMove(dst, mx, my);
399 
400 	mRectUnion(dst, src);
401 }
402 
403 
404 //=============================
405 // 描画関連
406 //=============================
407 
408 
409 /** 直線を45度単位に調整
410  *
411  * @param pt  対象点。結果はここに入る。
412  * @param ptstart 始点 */
413 
drawCalc_fitLine45(mPoint * pt,mPoint * ptstart)414 void drawCalc_fitLine45(mPoint *pt,mPoint *ptstart)
415 {
416 	int dx,dy,adx,ady,n;
417 
418 	dx = pt->x - ptstart->x;
419 	dy = pt->y - ptstart->y;
420 
421 	adx = abs(dx);
422 	ady = abs(dy);
423 
424 	n = (adx > ady)? adx: ady;
425 
426 	if(abs(adx - ady) < n / 2)
427 	{
428 		//45度線
429 
430 		if(adx < ady)
431 			pt->y = ptstart->y + ((dy < 0)? -adx: adx);
432 		else
433 			pt->x = ptstart->x + ((dx < 0)? -ady: ady);
434 	}
435 	else if(adx > ady)
436 		//水平
437 		pt->y = ptstart->y;
438 	else
439 		//垂直
440 		pt->x = ptstart->x;
441 }
442 
443 /** pttmp[0,1] から線の角度をラジアンで取得 (イメージ位置に対する角度。反時計回り) */
444 
drawCalc_getLineRadian_forImage(DrawData * p)445 double drawCalc_getLineRadian_forImage(DrawData *p)
446 {
447 	double x1,y1,x2,y2;
448 
449 	drawCalc_areaToimage_double(p, &x1, &y1, p->w.pttmp[0].x, p->w.pttmp[0].y);
450 	drawCalc_areaToimage_double(p, &x2, &y2, p->w.pttmp[1].x, p->w.pttmp[1].y);
451 
452 	return atan2(y2 - y1, x2 - x1);
453 }
454 
455 /** イメージ移動時の計算
456  *
457  * @param img   相対移動数を計算するためのイメージ
458  * @param ptret 相対移動数が入る
459  * @return 1px でも移動するか */
460 
drawCalc_moveImage_onMotion(DrawData * p,TileImage * img,uint32_t state,mPoint * ptret)461 mBool drawCalc_moveImage_onMotion(DrawData *p,TileImage *img,uint32_t state,mPoint *ptret)
462 {
463 	mPoint pt,pt2;
464 	double x,y;
465 
466 	//カーソル移動距離
467 
468 	x = p->w.dptAreaCur.x - p->w.dptAreaLast.x;
469 	y = p->w.dptAreaCur.y - p->w.dptAreaLast.y;
470 
471 	if(state & M_MODS_CTRL)  x = 0;
472 	if(state & M_MODS_SHIFT) y = 0;
473 
474 	//総移動数
475 
476 	p->w.ptd_tmp[0].x += x;
477 	p->w.ptd_tmp[0].y += y;
478 
479 	//総移動数を キャンバス -> イメージ 座標変換
480 
481 	pt2.x = (int)p->w.ptd_tmp[0].x;
482 	pt2.y = (int)p->w.ptd_tmp[0].y;
483 
484 	drawCalc_areaToimage_relative(p, &pt, &pt2);
485 
486 	//移動開始時のオフセット位置を加算して絶対値に
487 
488 	pt.x += p->w.pttmp[0].x;
489 	pt.y += p->w.pttmp[0].y;
490 
491 	//現在位置からの相対移動数
492 
493 	TileImage_getOffset(img, &pt2);
494 
495 	pt.x -= pt2.x;
496 	pt.y -= pt2.y;
497 
498 	if(pt.x == 0 && pt.y == 0)
499 		return FALSE;
500 	else
501 	{
502 		//総相対移動数
503 		p->w.pttmp[1].x += pt.x;
504 		p->w.pttmp[1].y += pt.y;
505 
506 		*ptret = pt;
507 
508 		return TRUE;
509 	}
510 }
511 
512 
513 //==============================
514 // ほか
515 //==============================
516 
517 
518 /** 1段階上げ/下げした表示倍率取得 */
519 
drawCalc_getZoom_step(DrawData * p,mBool zoomup)520 int drawCalc_getZoom_step(DrawData *p,mBool zoomup)
521 {
522 	int n,step;
523 
524 	n = p->canvas_zoom / 10;
525 
526 	if((!zoomup && n <= 100) || (zoomup && n < 100))
527 	{
528 		//100% 以下
529 
530 		step = APP_CONF->canvasZoomStep_low;
531 		if(step == 0) step = 1;
532 
533 		if(step < 0)
534 		{
535 			//元の倍率*指定倍率を増減
536 
537 			step = -step;
538 			n = round(p->canvas_zoom * (step / 100.0));
539 
540 			if(zoomup)
541 			{
542 				n += p->canvas_zoom;
543 				if(n > 1000) n = 1000;
544 			}
545 			else
546 				n = p->canvas_zoom - n;
547 		}
548 		else
549 		{
550 			//段階
551 			if(zoomup)
552 			{
553 				n = 100 - (100 - n - 1) / step * step;
554 				if(n > 100) n = 100;
555 			}
556 			else
557 				n = 100 - (100 - n + step) / step * step;
558 
559 			n *= 10;
560 		}
561 	}
562 	else
563 	{
564 		//100% 以上
565 
566 		step = APP_CONF->canvasZoomStep_hi;
567 
568 		if(zoomup)
569 			n = (n + step) / step * step;
570 		else
571 		{
572 			n = (n - 1) / step * step;
573 			if(n < 100) n = 100;
574 		}
575 
576 		n *= 10;
577 	}
578 
579 	//
580 
581 	if(n < CANVAS_ZOOM_MIN)
582 		n = CANVAS_ZOOM_MIN;
583 	else if(n > CANVAS_ZOOM_MAX)
584 		n = CANVAS_ZOOM_MAX;
585 
586 	return n;
587 }
588 
589 /** ウィンドウに収まる表示倍率を取得
590  *
591  * 最大で 100% */
592 
drawCalc_getZoom_fitWindow(DrawData * p)593 int drawCalc_getZoom_fitWindow(DrawData *p)
594 {
595 	mBox box;
596 	int w,h;
597 
598 	//領域の余白 10px 分を引く
599 
600 	if(p->szCanvas.w < 20 || p->szCanvas.h < 20)
601 		w = h = 21;
602 	else
603 	{
604 		w = p->szCanvas.w - 20;
605 		h = p->szCanvas.h - 20;
606 	}
607 
608 	//
609 
610 	box.x = box.y = 0;
611 	box.w = p->imgw, box.h = p->imgh;
612 
613 	mBoxScaleKeepAspect(&box, w, h, TRUE);
614 
615 	//倍率
616 
617 	return (int)((double)box.w / p->imgw * 1000 + 0.5);
618 }
619 
620 /** キャンバスのスクロールバーの最大値取得
621  *
622  * 四隅をイメージ座標 -> 領域座標変換し、一番大きい半径の値+余白 */
623 
drawCalc_getCanvasScrollMax(DrawData * p,mSize * size)624 void drawCalc_getCanvasScrollMax(DrawData *p,mSize *size)
625 {
626 	mPoint pt[4];
627 	int i,r,rmax = 0;
628 	double x,y;
629 
630 	//イメージの四隅を領域座標に変換。
631 	//キャンバス中央からの距離の最大値を取得。
632 
633 	mMemzero(pt, sizeof(mPoint) * 4);
634 
635 	pt[1].x = pt[3].x = p->imgw;
636 	pt[2].y = pt[3].y = p->imgh;
637 
638 	for(i = 0; i < 4; i++)
639 	{
640 		drawCalc_imageToarea_pt(p, pt + i, pt[i].x, pt[i].y);
641 
642 		x = pt[i].x - (p->szCanvas.w >> 1);
643 		y = pt[i].y - (p->szCanvas.h >> 1);
644 
645 		r = (int)(sqrt(x * x + y * y) + 0.5);
646 		if(rmax < r) rmax = r;
647 	}
648 
649 	//
650 
651 	size->w = rmax * 2 + p->szCanvas.w;
652 	size->h = rmax * 2 + p->szCanvas.h;
653 }
654 
655 
656 //===============================
657 // defCanvasInfo.h
658 //===============================
659 
660 
661 /** イメージ座標からキャンバス座標に変換 */
662 
CanvasDrawInfo_imageToarea(CanvasDrawInfo * p,double x,double y,double * px,double * py)663 void CanvasDrawInfo_imageToarea(CanvasDrawInfo *p,double x,double y,double *px,double *py)
664 {
665 	x = (x - p->originx) * p->param->scale;
666 	y = (y - p->originy) * p->param->scale;
667 	if(p->mirror) x = -x;
668 
669 	*px = (x * p->param->cos - y * p->param->sin) - p->scrollx;
670 	*py = (x * p->param->sin + y * p->param->cos) - p->scrolly;
671 }
672 
673 /** イメージ座標からキャンバス座標に変換 (=> mPoint) */
674 
CanvasDrawInfo_imageToarea_pt(CanvasDrawInfo * p,double x,double y,mPoint * pt)675 void CanvasDrawInfo_imageToarea_pt(CanvasDrawInfo *p,double x,double y,mPoint *pt)
676 {
677 	x = (x - p->originx) * p->param->scale;
678 	y = (y - p->originy) * p->param->scale;
679 	if(p->mirror) x = -x;
680 
681 	pt->x = floor((x * p->param->cos - y * p->param->sin) - p->scrollx);
682 	pt->y = floor((x * p->param->sin + y * p->param->cos) - p->scrolly);
683 }
684 
685 /** イメージ座標を +1 した時のキャンバス座標の増加幅を取得
686  *
687  * @param dst 0:x-x 1:x-y 2:y-x 3:y-y */
688 
CanvasDrawInfo_getImageIncParam(CanvasDrawInfo * p,double * dst)689 void CanvasDrawInfo_getImageIncParam(CanvasDrawInfo *p,double *dst)
690 {
691 	dst[0] = p->param->scale * p->param->cos;
692 	dst[1] = p->param->scale * p->param->sin;
693 	dst[2] = -dst[1];
694 	dst[3] = dst[0];
695 
696 	if(p->mirror)
697 	{
698 		dst[0] = -dst[0];
699 		dst[1] = -dst[1];
700 	}
701 }
702 
703