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  * mPixbuf
22  *****************************************/
23 
24 #include <string.h>
25 
26 #include "mDef.h"
27 #include "mPixbuf.h"
28 #include "mPixbuf_pv.h"
29 
30 #include "mAppDef.h"
31 #include "mSysCol.h"
32 #include "mRectBox.h"
33 #include "mLoadImage.h"
34 
35 
36 //--------------------------
37 
38 mPixbuf *__mPixbufAlloc(void);
39 void __mPixbufFree(mPixbuf *p);
40 int __mPixbufCreate(mPixbuf *p,int w,int h);
41 
42 //--------------------------
43 
44 
45 /*****************************//**
46 
47 @defgroup pixbuf mPixbuf
48 @brief 画面に転送可能なピクセルバッファ
49 
50 ディスプレイ環境により 16/24/32 bit イメージのいずれか。\n
51 ビットオーダーは OS に依存。
52 
53 @ingroup group_image
54 @{
55 
56 @file mPixbuf.h
57 @struct _mPixbuf
58 @enum MPIXBUF_DRAWBTT_FLAGS
59 @enum MPIXBUF_DRAWCKBOX_FLAGS
60 
61 @def MPIXBUF_COL_XOR
62 XOR で塗る場合の色値
63 
64 **********************************/
65 
66 
67 //====================================
68 // ピクセルバッファ位置に色をセット
69 //====================================
70 
71 
_setbuf_32bit(uint8_t * pd,mPixCol col)72 static void _setbuf_32bit(uint8_t *pd,mPixCol col)
73 {
74 	if(col == MPIXBUF_COL_XOR)
75 		*((uint32_t *)pd) ^= 0xffffffff;
76 	else
77 		*((uint32_t *)pd) = col;
78 }
79 
_setbuf_24bit(uint8_t * pd,mPixCol col)80 static void _setbuf_24bit(uint8_t *pd,mPixCol col)
81 {
82 	if(col == MPIXBUF_COL_XOR)
83 	{
84 		pd[0] ^= 0xff;
85 		pd[1] ^= 0xff;
86 		pd[2] ^= 0xff;
87 	}
88 	else
89 	{
90 	#ifdef MLIB_BIGENDIAN
91 		pd[0] = (uint8_t)(col >> 16);
92 		pd[1] = (uint8_t)(col >> 8);
93 		pd[2] = (uint8_t)col;
94 	#else
95 		pd[0] = (uint8_t)col;
96 		pd[1] = (uint8_t)(col >> 8);
97 		pd[2] = (uint8_t)(col >> 16);
98 	#endif
99 	}
100 }
101 
_setbuf_16bit(uint8_t * pd,mPixCol col)102 static void _setbuf_16bit(uint8_t *pd,mPixCol col)
103 {
104 	if(col == MPIXBUF_COL_XOR)
105 		*((uint16_t *)pd) ^= 0xffff;
106 	else
107 		*((uint16_t *)pd) = col;
108 }
109 
110 
111 //=============================
112 
113 
114 /** 解放 */
115 
mPixbufFree(mPixbuf * p)116 void mPixbufFree(mPixbuf *p)
117 {
118 	if(p)
119 	{
120 		__mPixbufFree(p);
121 		mFree(p);
122 	}
123 }
124 
125 /** 作成 */
126 
mPixbufCreate(int w,int h)127 mPixbuf *mPixbufCreate(int w,int h)
128 {
129 	mPixbuf *p;
130 
131 	if(w < 1) w = 1;
132 	if(h < 1) h = 1;
133 
134 	//
135 
136 	p = __mPixbufAlloc();
137 	if(!p) return NULL;
138 
139 	if(__mPixbufCreate(p, w, h))
140 	{
141 		mFree(p);
142 		return NULL;
143 	}
144 
145 	//
146 
147 	if(p->bpp == 4)
148 		p->setbuf = _setbuf_32bit;
149 	else if(p->bpp == 3)
150 		p->setbuf = _setbuf_24bit;
151 	else
152 		p->setbuf = _setbuf_16bit;
153 
154 	return p;
155 }
156 
157 /** サイズ変更 */
158 
mPixbufResizeStep(mPixbuf * p,int w,int h,int stepw,int steph)159 int mPixbufResizeStep(mPixbuf *p,int w,int h,int stepw,int steph)
160 {
161 	int neww,newh;
162 
163 	if(w < 1) w = 1;
164 	if(h < 1) h = 1;
165 
166 	neww = (w + stepw - 1) / stepw * stepw;
167 	newh = (h + steph - 1) / steph * steph;
168 
169 	if(p->w != neww || p->h != newh)
170 	{
171 		if(__mPixbufCreate(p, neww, newh))
172 			return -1;
173 	}
174 
175 	return 0;
176 }
177 
178 
179 //=========================
180 // 画像読み込み
181 //=========================
182 
183 
184 typedef struct
185 {
186 	mLoadImage base;
187 	mPixbuf *img;
188 	uint8_t *dstbuf;
189 }LOADIMAGE_INFO;
190 
191 
192 /** 情報取得 */
193 
_loadimage_getinfo(mLoadImage * load,mLoadImageInfo * info)194 static int _loadimage_getinfo(mLoadImage *load,mLoadImageInfo *info)
195 {
196 	LOADIMAGE_INFO *p = (LOADIMAGE_INFO *)load;
197 
198 	p->img = mPixbufCreate(info->width, info->height);
199 	if(!p->img) return MLOADIMAGE_ERR_ALLOC;
200 
201 	p->dstbuf = p->img->buftop;
202 	if(info->bottomup) p->dstbuf += (info->height - 1) * p->img->pitch_dir;
203 
204 	return MLOADIMAGE_ERR_OK;
205 }
206 
207 /** Y1行取得 */
208 
_loadimage_getrow(mLoadImage * load,uint8_t * buf,int pitch)209 static int _loadimage_getrow(mLoadImage *load,uint8_t *buf,int pitch)
210 {
211 	LOADIMAGE_INFO *p = (LOADIMAGE_INFO *)load;
212 	mPixbuf *img;
213 	uint8_t *ps,*pd;
214 	int i;
215 
216 	img = p->img;
217 	ps = buf;
218 	pd = p->dstbuf;
219 
220 	for(i = load->info.width; i > 0; i--, ps += 3, pd += img->bpp)
221 		(img->setbuf)(pd, mRGBtoPix2(ps[0], ps[1], ps[2]));
222 
223 	p->dstbuf += (load->info.bottomup)? -(p->img->pitch_dir): p->img->pitch_dir;
224 
225 	return MLOADIMAGE_ERR_OK;
226 }
227 
228 /** ファイルまたはバッファから画像読み込み */
229 
mPixbufLoadImage(mLoadImageSource * src,mDefEmptyFunc loadfunc,char ** errmes)230 mPixbuf *mPixbufLoadImage(mLoadImageSource *src,mDefEmptyFunc loadfunc,char **errmes)
231 {
232 	LOADIMAGE_INFO *p;
233 	mPixbuf *img;
234 	mBool ret;
235 
236 	//mLoadImage
237 
238 	p = (LOADIMAGE_INFO *)mLoadImage_create(sizeof(LOADIMAGE_INFO));
239 	if(!p) return NULL;
240 
241 	p->base.format = MLOADIMAGE_FORMAT_RGB;
242 	p->base.src = *src;
243 	p->base.getinfo = _loadimage_getinfo;
244 	p->base.getrow = _loadimage_getrow;
245 
246 	//読み込み関数
247 
248 	ret = ((mLoadImageFunc)loadfunc)(M_LOADIMAGE(p));
249 
250 	//結果
251 
252 	img = p->img;
253 
254 	if(!ret)
255 	{
256 		mPixbufFree(img);
257 		img = NULL;
258 
259 		if(errmes) *errmes = mStrdup(p->base.message);
260 	}
261 
262 	mLoadImage_free(M_LOADIMAGE(p));
263 
264 	return img;
265 }
266 
267 
268 //======================
269 
270 
271 /** 指定位置のピクセルバッファ位置取得
272  *
273  * @return 範囲外は NULL */
274 
mPixbufGetBufPt(mPixbuf * p,int x,int y)275 uint8_t *mPixbufGetBufPt(mPixbuf *p,int x,int y)
276 {
277 	x += M_PIXBUFBASE(p)->p.offsetX;
278 	y += M_PIXBUFBASE(p)->p.offsetY;
279 
280 	if(x >= 0 && x < p->w && y >= 0 && y < p->h)
281 		return p->buftop + y * p->pitch_dir + x * p->bpp;
282 	else
283 		return NULL;
284 }
285 
286 /** 指定位置のピクセルバッファ位置取得 (範囲判定なし) */
287 
mPixbufGetBufPtFast(mPixbuf * p,int x,int y)288 uint8_t *mPixbufGetBufPtFast(mPixbuf *p,int x,int y)
289 {
290 	return p->buftop + (y + M_PIXBUFBASE(p)->p.offsetY) * p->pitch_dir
291 			+ (x + M_PIXBUFBASE(p)->p.offsetX) * p->bpp;
292 }
293 
294 /** 指定位置のピクセルバッファ位置取得 (絶対位置)
295  *
296  * @return 範囲外は NULL */
297 
mPixbufGetBufPt_abs(mPixbuf * p,int x,int y)298 uint8_t *mPixbufGetBufPt_abs(mPixbuf *p,int x,int y)
299 {
300 	if(x >= 0 && x < p->w && y >= 0 && y < p->h)
301 		return p->buftop + y * p->pitch_dir + x * p->bpp;
302 	else
303 		return NULL;
304 }
305 
306 /** 指定位置のピクセルバッファ位置取得 (絶対位置・範囲判定なし) */
307 
mPixbufGetBufPtFast_abs(mPixbuf * p,int x,int y)308 uint8_t *mPixbufGetBufPtFast_abs(mPixbuf *p,int x,int y)
309 {
310 	return p->buftop + y * p->pitch_dir + x * p->bpp;
311 }
312 
313 /** 指定位置の色 (RGB) を取得 */
314 
mPixbufGetPixelRGB(mPixbuf * p,int x,int y)315 mRgbCol mPixbufGetPixelRGB(mPixbuf *p,int x,int y)
316 {
317 	uint8_t *pd;
318 	uint32_t col = 0;
319 
320 	x += M_PIXBUFBASE(p)->p.offsetX;
321 	y += M_PIXBUFBASE(p)->p.offsetY;
322 
323 	if(x < 0 || x >= p->w || y < 0 || y >= p->h)
324 		return 0;
325 	else
326 	{
327 		pd = p->buftop + y * p->pitch_dir + x * p->bpp;
328 
329 		switch(p->bpp)
330 		{
331 			case 4:
332 				col = *((uint32_t *)pd);
333 				break;
334 			case 3:
335 			#ifdef MLIB_BIGENDIAN
336 				col = ((uint32_t)pd[0] << 16) | (pd[1] << 8) | pd[2];
337 			#else
338 				col = ((uint32_t)pd[2] << 16) | (pd[1] << 8) | pd[0];
339 			#endif
340 				break;
341 			case 2:
342 				col = *((uint16_t *)pd);
343 				break;
344 		}
345 
346 		return mPixtoRGB(col);
347 	}
348 }
349 
350 /** バッファ位置からRGB値を取得 */
351 
mPixbufGetPixelBufRGB(mPixbuf * p,uint8_t * buf,int * pr,int * pg,int * pb)352 void mPixbufGetPixelBufRGB(mPixbuf *p,uint8_t *buf,int *pr,int *pg,int *pb)
353 {
354 	uint32_t col;
355 
356 	switch(p->bpp)
357 	{
358 		case 4:
359 			col = *((uint32_t *)buf);
360 			break;
361 		case 3:
362 		#ifdef MLIB_BIGENDIAN
363 			col = ((uint32_t)buf[0] << 16) | (buf[1] << 8) | buf[2];
364 		#else
365 			col = ((uint32_t)buf[2] << 16) | (buf[1] << 8) | buf[0];
366 		#endif
367 			break;
368 		case 2:
369 			col = *((uint16_t *)buf);
370 			break;
371 	}
372 
373 	col = mPixtoRGB(col);
374 
375 	*pr = M_GET_R(col);
376 	*pg = M_GET_G(col);
377 	*pb = M_GET_B(col);
378 }
379 
380 /** オフセット位置セット
381  *
382  * @param pt 元のオフセット位置が入る。NULL 可。 */
383 
mPixbufSetOffset(mPixbuf * p,int x,int y,mPoint * pt)384 void mPixbufSetOffset(mPixbuf *p,int x,int y,mPoint *pt)
385 {
386 	if(pt)
387 	{
388 		pt->x = M_PIXBUFBASE(p)->p.offsetX;
389 		pt->y = M_PIXBUFBASE(p)->p.offsetY;
390 	}
391 
392 	M_PIXBUFBASE(p)->p.offsetX = x;
393 	M_PIXBUFBASE(p)->p.offsetY = y;
394 }
395 
396 
397 //============================
398 // クリッピング
399 //============================
400 
401 
402 /** (内部用) マスタークリッピング範囲セット */
403 
__mPixbufSetClipMaster(mPixbuf * p,mRect * rc)404 void __mPixbufSetClipMaster(mPixbuf *p,mRect *rc)
405 {
406 	if(rc)
407 	{
408 		M_PIXBUFBASE(p)->p.clipMaster = *rc;
409 		M_PIXBUFBASE(p)->p.clip = *rc;
410 		M_PIXBUFBASE(p)->p.flags |= MPIXBUF_F_CLIP | MPIXBUF_F_CLIP_MASTER;
411 	}
412 	else
413 	{
414 		M_PIXBUFBASE(p)->p.flags &= ~(MPIXBUF_F_CLIP | MPIXBUF_F_CLIP_MASTER);
415 	}
416 }
417 
418 
419 /** クリッピングをなしに */
420 
mPixbufClipNone(mPixbuf * p)421 void mPixbufClipNone(mPixbuf *p)
422 {
423 	if(M_PIXBUFBASE(p)->p.flags & MPIXBUF_F_CLIP_MASTER)
424 		M_PIXBUFBASE(p)->p.clip = M_PIXBUFBASE(p)->p.clipMaster;
425 	else
426 		M_PIXBUFBASE(p)->p.flags &= ~MPIXBUF_F_CLIP;
427 }
428 
429 /** クリッピング範囲セット
430  *
431  * @return 描画範囲があるか */
432 
mPixbufSetClipBox_d(mPixbuf * p,int x,int y,int w,int h)433 mBool mPixbufSetClipBox_d(mPixbuf *p,int x,int y,int w,int h)
434 {
435 	mPixbufBase *pb = M_PIXBUFBASE(p);
436 	mBool ret;
437 
438 	mRectSetBox_d(&pb->p.clip, x + pb->p.offsetX, y + pb->p.offsetY, w, h);
439 
440 	if(pb->p.flags & MPIXBUF_F_CLIP_MASTER)
441 		ret = mRectClipRect(&pb->p.clip, &pb->p.clipMaster);
442 	else
443 		ret = mRectClipBox_d(&pb->p.clip, 0, 0, p->w, p->h);
444 
445 	pb->p.flags |= MPIXBUF_F_CLIP;
446 
447 	return ret;
448 }
449 
450 /** クリッピング範囲セット (mBox)
451  *
452  * @return 描画範囲があるか */
453 
mPixbufSetClipBox_box(mPixbuf * p,mBox * box)454 mBool mPixbufSetClipBox_box(mPixbuf *p,mBox *box)
455 {
456 	return mPixbufSetClipBox_d(p, box->x, box->y, box->w, box->h);
457 }
458 
459 /** 点がクリッピング範囲内にあるか (絶対位置) */
460 
mPixbufIsInClip_abs(mPixbuf * p,int x,int y)461 mBool mPixbufIsInClip_abs(mPixbuf *p,int x,int y)
462 {
463 	if(M_PIXBUFBASE(p)->p.flags & MPIXBUF_F_CLIP)
464 	{
465 		if(mRectIsEmpty(&M_PIXBUFBASE(p)->p.clip))
466 			return FALSE;
467 		else
468 			return (M_PIXBUFBASE(p)->p.clip.x1 <= x && x <= M_PIXBUFBASE(p)->p.clip.x2
469 				&& M_PIXBUFBASE(p)->p.clip.y1 <= y && y <= M_PIXBUFBASE(p)->p.clip.y2);
470 	}
471 	else
472 	{
473 		return (x >= 0 && x < p->w && y >= 0 && y < p->h);
474 	}
475 }
476 
477 /** クリッピングを行った範囲を取得 (mRect で) */
478 
mPixbufGetClipRect_d(mPixbuf * p,mRect * rc,int x,int y,int w,int h)479 mBool mPixbufGetClipRect_d(mPixbuf *p,mRect *rc,int x,int y,int w,int h)
480 {
481 	mRect rc1;
482 	int offx,offy;
483 	mBool ret;
484 
485 	offx = M_PIXBUFBASE(p)->p.offsetX;
486 	offy = M_PIXBUFBASE(p)->p.offsetY;
487 
488 	rc1.x1 = x + offx;
489 	rc1.y1 = y + offy;
490 	rc1.x2 = rc1.x1 + w - 1;
491 	rc1.y2 = rc1.y1 + h - 1;
492 
493 	if(M_PIXBUFBASE(p)->p.flags & MPIXBUF_F_CLIP)
494 		ret = mRectClipRect(&rc1, &M_PIXBUFBASE(p)->p.clip);
495 	else
496 		ret = mRectClipBox_d(&rc1, 0, 0, p->w, p->h);
497 
498 	if(ret)
499 	{
500 		rc1.x1 -= offx;
501 		rc1.x2 -= offx;
502 		rc1.y1 -= offy;
503 		rc1.y2 -= offy;
504 
505 		*rc = rc1;
506 	}
507 
508 	return ret;
509 }
510 
511 /** クリッピングを行った範囲を取得 (mBox で) */
512 
mPixbufGetClipBox_d(mPixbuf * p,mBox * box,int x,int y,int w,int h)513 mBool mPixbufGetClipBox_d(mPixbuf *p,mBox *box,int x,int y,int w,int h)
514 {
515 	mRect rc;
516 
517 	if(!mPixbufGetClipRect_d(p, &rc, x, y, w, h))
518 		return FALSE;
519 	else
520 	{
521 		box->x = rc.x1, box->y = rc.y1;
522 		box->w = rc.x2 - rc.x1 + 1;
523 		box->h = rc.y2 - rc.y1 + 1;
524 
525 		return TRUE;
526 	}
527 }
528 
529 /** クリッピングを行った範囲を取得 (mBox -> mBox) */
530 
mPixbufGetClipBox_box(mPixbuf * p,mBox * box,mBox * boxsrc)531 mBool mPixbufGetClipBox_box(mPixbuf *p,mBox *box,mBox *boxsrc)
532 {
533 	return mPixbufGetClipBox_d(p, box,
534 			boxsrc->x, boxsrc->y, boxsrc->w, boxsrc->h);
535 }
536 
537 
538 //=============================
539 // 描画 (バッファに直接)
540 //=============================
541 
542 
543 /** 水平線描画 */
544 
mPixbufRawLineH(mPixbuf * p,uint8_t * buf,int w,mPixCol pix)545 void mPixbufRawLineH(mPixbuf *p,uint8_t *buf,int w,mPixCol pix)
546 {
547 	uint32_t *p32;
548 	uint16_t *p16;
549 	uint8_t c1,c2,c3;
550 
551 	if(pix == MPIXBUF_COL_XOR)
552 	{
553 		//XOR
554 
555 		switch(p->bpp)
556 		{
557 			case 4:
558 				for(p32 = (uint32_t *)buf; w > 0; w--)
559 					*(p32++) ^= 0xffffffff;
560 				break;
561 			case 3:
562 				for(; w > 0; w--, buf += 3)
563 				{
564 					buf[0] ^= 0xff;
565 					buf[1] ^= 0xff;
566 					buf[2] ^= 0xff;
567 				}
568 				break;
569 			case 2:
570 				for(p16 = (uint16_t *)buf; w > 0; w--)
571 					*(p16++) ^= 0xffff;
572 				break;
573 		}
574 	}
575 	else
576 	{
577 		//通常
578 
579 		switch(p->bpp)
580 		{
581 			case 4:
582 				for(p32 = (uint32_t *)buf; w > 0; w--)
583 					*(p32++) = pix;
584 				break;
585 			case 3:
586 			#ifdef MLIB_BIGENDIAN
587 				c1 = (uint8_t)(pix >> 16);
588 				c2 = (uint8_t)(pix >> 8);
589 				c3 = (uint8_t)pix;
590 			#else
591 				c1 = (uint8_t)pix;
592 				c2 = (uint8_t)(pix >> 8);
593 				c3 = (uint8_t)(pix >> 16);
594 			#endif
595 
596 				for(; w > 0; w--, buf += 3)
597 					buf[0] = c1, buf[1] = c2, buf[2] = c3;
598 				break;
599 			case 2:
600 				for(p16 = (uint16_t *)buf; w > 0; w--)
601 					*(p16++) = (uint16_t)pix;
602 				break;
603 		}
604 	}
605 }
606 
607 /** 垂直線描画 */
608 
mPixbufRawLineV(mPixbuf * p,uint8_t * buf,int h,mPixCol pix)609 void mPixbufRawLineV(mPixbuf *p,uint8_t *buf,int h,mPixCol pix)
610 {
611 	uint8_t c1,c2,c3;
612 	int pitch;
613 
614 	pitch = p->pitch_dir;
615 
616 	if(pix == MPIXBUF_COL_XOR)
617 	{
618 		//XOR
619 
620 		switch(p->bpp)
621 		{
622 			case 4:
623 				for(; h > 0; h--, buf += pitch)
624 					*((uint32_t *)buf) ^= 0xffffffff;
625 				break;
626 			case 3:
627 				for(; h > 0; h--, buf += pitch)
628 				{
629 					buf[0] ^= 0xff;
630 					buf[1] ^= 0xff;
631 					buf[2] ^= 0xff;
632 				}
633 				break;
634 			case 2:
635 				for(; h > 0; h--, buf += pitch)
636 					*((uint16_t *)buf) ^= 0xffff;
637 				break;
638 		}
639 	}
640 	else
641 	{
642 		//通常
643 
644 		switch(p->bpp)
645 		{
646 			case 4:
647 				for(; h > 0; h--, buf += pitch)
648 					*((uint32_t *)buf) = pix;
649 				break;
650 			case 3:
651 			#ifdef MLIB_BIGENDIAN
652 				c1 = (uint8_t)(pix >> 16);
653 				c2 = (uint8_t)(pix >> 8);
654 				c3 = (uint8_t)pix;
655 			#else
656 				c1 = (uint8_t)pix;
657 				c2 = (uint8_t)(pix >> 8);
658 				c3 = (uint8_t)(pix >> 16);
659 			#endif
660 
661 				for(; h > 0; h--, buf += pitch)
662 					buf[0] = c1, buf[1] = c2, buf[2] = c3;
663 				break;
664 			case 2:
665 				for(; h > 0; h--, buf += pitch)
666 					*((uint16_t *)buf) = (uint16_t)pix;
667 				break;
668 		}
669 	}
670 }
671 
672 
673 //=============================
674 // 描画
675 //=============================
676 
677 
678 /** 全体を埋める */
679 
mPixbufFill(mPixbuf * p,mPixCol pix)680 void mPixbufFill(mPixbuf *p,mPixCol pix)
681 {
682 	uint8_t *pd;
683 	int i;
684 
685 	//Y1行分を埋める
686 
687 	mPixbufRawLineH(p, p->buf, p->w, pix);
688 
689 	//残りは上1行を順にコピー
690 
691 	pd = p->buf;
692 
693 	for(i = p->h - 1; i > 0; i--, pd += p->pitch)
694 		memcpy(pd + p->pitch, pd, p->pitch);
695 }
696 
697 /** 点を置く */
698 
mPixbufSetPixel(mPixbuf * p,int x,int y,mPixCol pix)699 void mPixbufSetPixel(mPixbuf *p,int x,int y,mPixCol pix)
700 {
701 	x += M_PIXBUFBASE(p)->p.offsetX;
702 	y += M_PIXBUFBASE(p)->p.offsetY;
703 
704 	if(mPixbufIsInClip_abs(p, x, y))
705 		(p->setbuf)(p->buftop + y * p->pitch_dir + x * p->bpp, pix);
706 }
707 
708 /** 点を置く (RGB) */
709 
mPixbufSetPixelRGB(mPixbuf * p,int x,int y,mRgbCol rgb)710 void mPixbufSetPixelRGB(mPixbuf *p,int x,int y,mRgbCol rgb)
711 {
712 	x += M_PIXBUFBASE(p)->p.offsetX;
713 	y += M_PIXBUFBASE(p)->p.offsetY;
714 
715 	if(mPixbufIsInClip_abs(p, x, y))
716 		(p->setbuf)(p->buftop + y * p->pitch_dir + x * p->bpp, mRGBtoPix(rgb));
717 }
718 
719 /** 複数の点を置く */
720 
mPixbufSetPixels(mPixbuf * p,mPoint * pt,int ptcnt,mPixCol pix)721 void mPixbufSetPixels(mPixbuf *p,mPoint *pt,int ptcnt,mPixCol pix)
722 {
723 	int x,y;
724 
725 	for(; ptcnt > 0; ptcnt--, pt++)
726 	{
727 		x = pt->x + M_PIXBUFBASE(p)->p.offsetX;
728 		y = pt->y + M_PIXBUFBASE(p)->p.offsetY;
729 
730 		if(mPixbufIsInClip_abs(p, x, y))
731 			(p->setbuf)(p->buftop + y * p->pitch_dir + x * p->bpp, pix);
732 	}
733 }
734 
735 /** RGB合成して点をセット
736  *
737  * @param col 下位は RGB。24bitより上位が不透明度 (0-128) */
738 
mPixbufSetPixel_blend128(mPixbuf * p,int x,int y,uint32_t col)739 void mPixbufSetPixel_blend128(mPixbuf *p,int x,int y,uint32_t col)
740 {
741 	uint8_t *pd;
742 	int r,g,b,a;
743 
744 	x += M_PIXBUFBASE(p)->p.offsetX;
745 	y += M_PIXBUFBASE(p)->p.offsetY;
746 
747 	if(!mPixbufIsInClip_abs(p, x, y)) return;
748 
749 	if((pd = mPixbufGetBufPt_abs(p, x, y)))
750 	{
751 		mPixbufGetPixelBufRGB(p, pd, &r, &g, &b);
752 
753 		a = col >> 24;
754 		r = ((M_GET_R(col) - r) * a >> 7) + r;
755 		g = ((M_GET_G(col) - g) * a >> 7) + g;
756 		b = ((M_GET_B(col) - b) * a >> 7) + b;
757 
758 		(p->setbuf)(pd, mRGBtoPix2(r, g, b));
759 	}
760 }
761 
762 /** RGB合成して点をセット (バッファ位置) */
763 
mPixbufSetPixelBuf_blend128(mPixbuf * p,uint8_t * buf,uint32_t col)764 void mPixbufSetPixelBuf_blend128(mPixbuf *p,uint8_t *buf,uint32_t col)
765 {
766 	int r,g,b,a;
767 
768 	mPixbufGetPixelBufRGB(p, buf, &r, &g, &b);
769 
770 	a = col >> 24;
771 	r = ((M_GET_R(col) - r) * a >> 7) + r;
772 	g = ((M_GET_G(col) - g) * a >> 7) + g;
773 	b = ((M_GET_B(col) - b) * a >> 7) + b;
774 
775 	(p->setbuf)(buf, mRGBtoPix2(r, g, b));
776 }
777 
778 
779 //========================
780 
781 
782 /** 水平線描画 */
783 
mPixbufLineH(mPixbuf * p,int x,int y,int w,mPixCol pix)784 void mPixbufLineH(mPixbuf *p,int x,int y,int w,mPixCol pix)
785 {
786 	mRect rc;
787 
788 	if(mPixbufGetClipRect_d(p, &rc, x, y, w, 1))
789 	{
790 		mPixbufRawLineH(p,
791 			mPixbufGetBufPtFast(p, rc.x1, rc.y1), rc.x2 - rc.x1 + 1, pix);
792 	}
793 }
794 
795 /** 垂直線描画 */
796 
mPixbufLineV(mPixbuf * p,int x,int y,int h,mPixCol pix)797 void mPixbufLineV(mPixbuf *p,int x,int y,int h,mPixCol pix)
798 {
799 	mRect rc;
800 
801 	if(mPixbufGetClipRect_d(p, &rc, x, y, 1, h))
802 	{
803 		mPixbufRawLineV(p,
804 			mPixbufGetBufPtFast(p, rc.x1, rc.y1), rc.y2 - rc.y1 + 1, pix);
805 	}
806 }
807 
808 /** 水平線描画 (指定不透明度で合成)
809  *
810  * @param opacity 256 = 1.0 */
811 
mPixbufLineH_blend(mPixbuf * p,int x,int y,int w,mRgbCol rgb,int opacity)812 void mPixbufLineH_blend(mPixbuf *p,int x,int y,int w,mRgbCol rgb,int opacity)
813 {
814 	mRect rc;
815 	uint8_t *pd;
816 	int ix,r,g,b,sr,sg,sb;
817 
818 	if(!mPixbufGetClipRect_d(p, &rc, x, y, w, 1))
819 		return;
820 
821 	pd = mPixbufGetBufPtFast(p, rc.x1, rc.y1);
822 
823 	sr = M_GET_R(rgb);
824 	sg = M_GET_G(rgb);
825 	sb = M_GET_B(rgb);
826 
827 	for(ix = rc.x1; ix <= rc.x2; ix++, pd += p->bpp)
828 	{
829 		mPixbufGetPixelBufRGB(p, pd, &r, &g, &b);
830 
831 		r = ((sr - r) * opacity >> 8) + r;
832 		g = ((sg - g) * opacity >> 8) + g;
833 		b = ((sb - b) * opacity >> 8) + b;
834 
835 		(p->setbuf)(pd, mRGBtoPix2(r, g, b));
836 	}
837 }
838 
839 /** 垂直線描画 (指定不透明度で合成) */
840 
mPixbufLineV_blend(mPixbuf * p,int x,int y,int h,mRgbCol rgb,int opacity)841 void mPixbufLineV_blend(mPixbuf *p,int x,int y,int h,mRgbCol rgb,int opacity)
842 {
843 	mRect rc;
844 	uint8_t *pd;
845 	int iy,r,g,b,sr,sg,sb;
846 
847 	if(!mPixbufGetClipRect_d(p, &rc, x, y, 1, h))
848 		return;
849 
850 	pd = mPixbufGetBufPtFast(p, rc.x1, rc.y1);
851 
852 	sr = M_GET_R(rgb);
853 	sg = M_GET_G(rgb);
854 	sb = M_GET_B(rgb);
855 
856 	for(iy = rc.y1; iy <= rc.y2; iy++, pd += p->pitch_dir)
857 	{
858 		mPixbufGetPixelBufRGB(p, pd, &r, &g, &b);
859 
860 		r = ((sr - r) * opacity >> 8) + r;
861 		g = ((sg - g) * opacity >> 8) + g;
862 		b = ((sb - b) * opacity >> 8) + b;
863 
864 		(p->setbuf)(pd, mRGBtoPix2(r, g, b));
865 	}
866 }
867 
868 /** 直線描画 */
869 
_draw_line(mPixbuf * p,int x1,int y1,int x2,int y2,mPixCol pix,mBool noend)870 static void _draw_line(mPixbuf *p,int x1,int y1,int x2,int y2,mPixCol pix,mBool noend)
871 {
872 	int sx,sy,dx,dy,a,a1,e;
873 
874 	if(x1 == x2 && y1 == y2 && !noend)
875 	{
876 		mPixbufSetPixel(p, x1, y1, pix);
877 		return;
878 	}
879 
880 	//
881 
882 	dx = (x1 < x2)? x2 - x1: x1 - x2;
883 	dy = (y1 < y2)? y2 - y1: y1 - y2;
884 	sx = (x1 <= x2)? 1: -1;
885 	sy = (y1 <= y2)? 1: -1;
886 
887 	if(dx >= dy)
888 	{
889 		a  = 2 * dy;
890 		a1 = a - 2 * dx;
891 		e  = a - dx;
892 
893 		while(x1 != x2)
894 		{
895 			mPixbufSetPixel(p, x1, y1, pix);
896 
897 			if(e >= 0)
898 				y1 += sy, e += a1;
899 			else
900 				e += a;
901 
902 			x1 += sx;
903 		}
904 	}
905 	else
906 	{
907 		a  = 2 * dx;
908 		a1 = a - 2 * dy;
909 		e  = a - dy;
910 
911 		while(y1 != y2)
912 		{
913 			mPixbufSetPixel(p, x1, y1, pix);
914 
915 			if(e >= 0)
916 				x1 += sx, e += a1;
917 			else
918 				e += a;
919 
920 			y1 += sy;
921 		}
922 	}
923 
924 	if(!noend) mPixbufSetPixel(p, x1, y1, pix);
925 }
926 
927 /** 直線描画 */
928 
mPixbufLine(mPixbuf * p,int x1,int y1,int x2,int y2,mPixCol pix)929 void mPixbufLine(mPixbuf *p,int x1,int y1,int x2,int y2,mPixCol pix)
930 {
931 	_draw_line(p, x1, y1, x2, y2, pix, FALSE);
932 }
933 
934 /** 直線描画 (終点を描画しない) */
935 
mPixbufLine_noend(mPixbuf * p,int x1,int y1,int x2,int y2,mPixCol pix)936 void mPixbufLine_noend(mPixbuf *p,int x1,int y1,int x2,int y2,mPixCol pix)
937 {
938 	_draw_line(p, x1, y1, x2, y2, pix, TRUE);
939 }
940 
941 /** 複数点をつなげた直線を描画
942  *
943  * [0]-[1], [1]-[2], ... [n-2]-[n-1]
944  *
945  * @param num 点の数 */
946 
mPixbufLines(mPixbuf * p,mPoint * pt,int num,mPixCol pix)947 void mPixbufLines(mPixbuf *p,mPoint *pt,int num,mPixCol pix)
948 {
949 	for(; num > 1; num--, pt++)
950 		mPixbufLine(p, pt->x, pt->y, pt[1].x, pt[1].y, pix);
951 }
952 
953 /** 四角形枠 */
954 
mPixbufBox(mPixbuf * p,int x,int y,int w,int h,mPixCol pix)955 void mPixbufBox(mPixbuf *p,int x,int y,int w,int h,mPixCol pix)
956 {
957 	mRect rc;
958 	int ww,hh;
959 
960 	if(!mPixbufGetClipRect_d(p, &rc, x, y, w, h)) return;
961 
962 	ww = rc.x2 - rc.x1 + 1;
963 	hh = rc.y2 - rc.y1 + 1;
964 
965 	//左
966 
967 	if(rc.x1 == x)
968 		mPixbufRawLineV(p, mPixbufGetBufPtFast(p, rc.x1, rc.y1), hh, pix);
969 
970 	//右
971 
972 	if(rc.x2 == x + w - 1)
973 		mPixbufRawLineV(p, mPixbufGetBufPtFast(p, rc.x2, rc.y1), hh, pix);
974 
975 	//上
976 
977 	if(rc.y1 == y)
978 		mPixbufRawLineH(p, mPixbufGetBufPtFast(p, rc.x1, rc.y1), ww, pix);
979 
980 	//下
981 
982 	if(rc.y2 == y + h - 1)
983 		mPixbufRawLineH(p, mPixbufGetBufPtFast(p, rc.x1, rc.y2), ww, pix);
984 }
985 
986 /** 四角形枠 (低速版)
987  *
988  * XOR で描画する場合はこちらを使う */
989 
mPixbufBoxSlow(mPixbuf * p,int x,int y,int w,int h,mPixCol pix)990 void mPixbufBoxSlow(mPixbuf *p,int x,int y,int w,int h,mPixCol pix)
991 {
992 	int i,n;
993 
994 	//横線
995 
996 	n = y + h - 1;
997 
998 	for(i = 0; i < w; i++)
999 	{
1000 		mPixbufSetPixel(p, x + i, y, pix);
1001 
1002 		if(h > 1) mPixbufSetPixel(p, x + i, n, pix);
1003 	}
1004 
1005 	//縦線
1006 
1007 	n = x + w - 1;
1008 
1009 	for(i = 1; i < h - 1; i++)
1010 	{
1011 		mPixbufSetPixel(p, x, y + i, pix);
1012 
1013 		if(w > 1) mPixbufSetPixel(p, n, y + i, pix);
1014 	}
1015 }
1016 
1017 /** 四角形枠・破線 (1px) */
1018 
mPixbufBoxDash(mPixbuf * p,int x,int y,int w,int h,mPixCol pix)1019 void mPixbufBoxDash(mPixbuf *p,int x,int y,int w,int h,mPixCol pix)
1020 {
1021 	int i,n,f = 1;
1022 
1023 	//上
1024 
1025 	for(i = 0; i < w; i++, f ^= 1)
1026 	{
1027 		if(f) mPixbufSetPixel(p, x + i, y, pix);
1028 	}
1029 
1030 	//右
1031 
1032 	for(i = 1, n = x + w - 1; i < h; i++, f ^= 1)
1033 	{
1034 		if(f) mPixbufSetPixel(p, n, y + i, pix);
1035 	}
1036 
1037 	//下
1038 
1039 	for(i = w - 2, n = y + h - 1; i >= 0; i--, f ^= 1)
1040 	{
1041 		if(f) mPixbufSetPixel(p, x + i, n, pix);
1042 	}
1043 
1044 	//左
1045 
1046 	for(i = h - 2; i > 0; i--, f ^= 1)
1047 	{
1048 		if(f) mPixbufSetPixel(p, x, y + i, pix);
1049 	}
1050 }
1051 
1052 /** 四角形塗りつぶし */
1053 
mPixbufFillBox(mPixbuf * p,int x,int y,int w,int h,mPixCol pix)1054 void mPixbufFillBox(mPixbuf *p,int x,int y,int w,int h,mPixCol pix)
1055 {
1056 	mBox box;
1057 	uint8_t *pd;
1058 	int i;
1059 
1060 	if(!mPixbufGetClipBox_d(p, &box, x, y, w, h)) return;
1061 
1062 	//Y1列分を塗りつぶし
1063 
1064 	pd = mPixbufGetBufPtFast(p, box.x, box.y);
1065 
1066 	mPixbufRawLineH(p, pd, box.w, pix);
1067 
1068 	//以降、前の列をコピー
1069 
1070 	w = box.w * p->bpp;
1071 
1072 	for(i = box.h - 1; i > 0; i--, pd += p->pitch_dir)
1073 		memcpy(pd + p->pitch_dir, pd, w);
1074 }
1075 
1076 /** 2x2 のパターンで四角形塗りつぶし */
1077 
mPixbufFillBox_pat2x2(mPixbuf * p,int x,int y,int w,int h,mPixCol pix)1078 void mPixbufFillBox_pat2x2(mPixbuf *p,int x,int y,int w,int h,mPixCol pix)
1079 {
1080 	mRect rc;
1081 	uint8_t *pd;
1082 	int ix,iy,pitch,fy;
1083 
1084 	if(!mPixbufGetClipRect_d(p, &rc, x, y, w, h)) return;
1085 
1086 	pd = mPixbufGetBufPtFast(p, rc.x1, rc.y1);
1087 	pitch = p->pitch_dir - (rc.x2 - rc.x1 + 1) * p->bpp;
1088 
1089 	for(iy = rc.y1; iy <= rc.y2; iy++)
1090 	{
1091 		fy = iy & 1;
1092 
1093 		for(ix = rc.x1; ix <= rc.x2; ix++, pd += p->bpp)
1094 		{
1095 			if(!((ix & 1) ^ fy))
1096 				(p->setbuf)(pd, pix);
1097 		}
1098 
1099 		pd += pitch;
1100 	}
1101 }
1102 
1103 /** 4x4の格子柄で四角形塗りつぶし (描画開始位置を原点とする) */
1104 
mPixbufFillBox_checkers4x4_originx(mPixbuf * p,int x,int y,int w,int h,mPixCol pix1,mPixCol pix2)1105 void mPixbufFillBox_checkers4x4_originx(mPixbuf *p,
1106 	int x,int y,int w,int h,mPixCol pix1,mPixCol pix2)
1107 {
1108 	mBox box;
1109 	int ix,iy,fy,pitch;
1110 	uint8_t *pd;
1111 	mPixCol col[2];
1112 
1113 	if(!mPixbufGetClipBox_d(p, &box, x, y, w, h))
1114 		return;
1115 
1116 	pd = mPixbufGetBufPtFast(p, box.x, box.y);
1117 	pitch = p->pitch_dir - box.w * p->bpp;
1118 
1119 	col[0] = pix1, col[1] = pix2;
1120 
1121 	for(iy = 0; iy < box.h; iy++)
1122 	{
1123 		fy = (iy & 7) >> 2;
1124 
1125 		for(ix = 0; ix < box.w; ix++, pd += p->bpp)
1126 			(p->setbuf)(pd, col[fy ^ ((ix & 7) >> 2)]);
1127 
1128 		pd += pitch;
1129 	}
1130 }
1131 
1132 /** 楕円 */
1133 
mPixbufEllipse(mPixbuf * p,int x1,int y1,int x2,int y2,mPixCol pix)1134 void mPixbufEllipse(mPixbuf *p,int x1,int y1,int x2,int y2,mPixCol pix)
1135 {
1136 	double dx,dy,e,e2;
1137 	int a,b,b1;
1138 
1139 	if(x1 == x2 && y1 == y2)
1140 	{
1141 		mPixbufSetPixel(p, x1, y1, pix);
1142 		return;
1143 	}
1144 
1145 	a = (x1 < x2)? x2 - x1: x1 - x2;
1146 	b = (y1 < y2)? y2 - y1: y1 - y2;
1147 
1148 	if(a >= b)
1149 	{
1150 		//横長
1151 
1152 		b1 = b & 1;
1153 		dx = 4.0 * (1 - a) * b * b;
1154 		dy = 4.0 * (b1 + 1) * a * a;
1155 		e = dx + dy + b1 * a * a;
1156 
1157 		if(x1 > x2) x1 = x2, x2 += a;
1158 		if(y1 > y2) y1 = y2;
1159 
1160 		y1 += (b + 1) / 2;
1161 		y2 = y1 - b1;
1162 
1163 		a *= 8 * a;
1164 		b1 = 8 * b * b;
1165 
1166 		do
1167 		{
1168 			mPixbufSetPixel(p, x2, y1, pix);
1169 			if(x1 != x2) mPixbufSetPixel(p, x1, y1, pix);
1170 			if(y1 != y2) mPixbufSetPixel(p, x1, y2, pix);
1171 			if(x1 != x2 && y1 != y2) mPixbufSetPixel(p, x2, y2, pix);
1172 
1173 			e2 = 2 * e;
1174 			if(e2 <= dy) { y1++; y2--; e += dy += a; }
1175 			if(e2 >= dx || 2 * e > dy) { x1++; x2--; e += dx += b1; }
1176 		}while(x1 <= x2);
1177 	}
1178 	else
1179 	{
1180 		//縦長
1181 
1182 		b1 = a & 1;
1183 		dy = 4.0 * (1 - b) * a * a;
1184 		dx = 4.0 * (b1 + 1) * b * b;
1185 		e = dx + dy + b1 * b * b;
1186 
1187 		if(y1 > y2) y1 = y2, y2 += b;
1188 		if(x1 > x2) x1 = x2;
1189 
1190 		x1 += (a + 1) / 2;
1191 		x2 = x1 - b1;
1192 
1193 		b *= 8 * b;
1194 		b1 = 8 * a * a;
1195 
1196 		do
1197 		{
1198 			mPixbufSetPixel(p, x2, y1, pix);
1199 			if(x1 != x2) mPixbufSetPixel(p, x1, y1, pix);
1200 			if(y1 != y2) mPixbufSetPixel(p, x1, y2, pix);
1201 			if(x1 != x2 && y1 != y2) mPixbufSetPixel(p, x2, y2, pix);
1202 
1203 			e2 = 2 * e;
1204 			if(e2 <= dx) { x1++; x2--; e += dx += b; }
1205 			if(e2 >= dy || 2 * e > dx) { y1++; y2--; e += dy += b1; }
1206 		}while(y1 <= y2);
1207 	}
1208 }
1209 
1210 
1211 //==========================
1212 // 転送
1213 //==========================
1214 
1215 
1216 /** クリッピング */
1217 
__mPixbufBltClip(mPixbufBltInfo * p,mPixbuf * dst,int dx,int dy,int sx,int sy,int w,int h)1218 mBool __mPixbufBltClip(mPixbufBltInfo *p,
1219 	mPixbuf *dst,int dx,int dy,int sx,int sy,int w,int h)
1220 {
1221 	mBox box;
1222 
1223 	//クリッピング範囲適用
1224 
1225 	if(!mPixbufGetClipBox_d(dst, &box, dx, dy, w, h)) return FALSE;
1226 
1227 	//左上がずれた分はソース位置もずらす
1228 
1229 	sx += box.x - dx;
1230 	sy += box.y - dy;
1231 
1232 	//セット
1233 
1234 	p->dx = box.x, p->dy = box.y;
1235 	p->w = box.w, p->h = box.h;
1236 	p->sx = sx, p->sy = sy;
1237 
1238 	return TRUE;
1239 }
1240 
1241 
1242 /** mPixbuf から転送
1243  *
1244  * @param w,h 負の値で src の幅・高さ */
1245 
mPixbufBlt(mPixbuf * dst,int dx,int dy,mPixbuf * src,int sx,int sy,int w,int h)1246 void mPixbufBlt(mPixbuf *dst,int dx,int dy,mPixbuf *src,int sx,int sy,int w,int h)
1247 {
1248 	mPixbufBltInfo info;
1249 	int iy,size;
1250 	uint8_t *ps,*pd;
1251 
1252 	if(w < 0) w = src->w;
1253 	if(h < 0) h = src->h;
1254 
1255 	if(!__mPixbufBltClip(&info, dst, dx, dy, sx, sy, w, h)) return;
1256 
1257 	pd = mPixbufGetBufPtFast(dst, info.dx, info.dy);
1258 	ps = mPixbufGetBufPt(src, info.sx, info.sy);
1259 	size = dst->bpp * info.w;
1260 
1261 	for(iy = info.h; iy > 0; iy--)
1262 	{
1263 		memcpy(pd, ps, size);
1264 
1265 		pd += dst->pitch_dir;
1266 		ps += src->pitch_dir;
1267 	}
1268 }
1269 
1270 /** グレイスケールのイメージデータから転送 */
1271 
mPixbufBltFromGray(mPixbuf * p,int dx,int dy,const uint8_t * srcimg,int sx,int sy,int w,int h,int srcw)1272 void mPixbufBltFromGray(mPixbuf *p,int dx,int dy,
1273 	const uint8_t *srcimg,int sx,int sy,int w,int h,int srcw)
1274 {
1275 	mPixbufBltInfo info;
1276 	uint8_t *pd;
1277 	const uint8_t *ps;
1278 	int pitchs,pitchd,ix,iy,c;
1279 
1280 	if(!__mPixbufBltClip(&info, p, dx, dy, sx, sy, w, h)) return;
1281 
1282 	pd = mPixbufGetBufPtFast(p, info.dx, info.dy);
1283 	ps = srcimg + info.sy * srcw + info.sx;
1284 	pitchd = p->pitch_dir - info.w * p->bpp;
1285 	pitchs = srcw - info.w;
1286 
1287 	for(iy = info.h; iy; iy--)
1288 	{
1289 		for(ix = info.w; ix; ix--, pd += p->bpp)
1290 		{
1291 			c = *(ps++);
1292 
1293 			(p->setbuf)(pd, mRGBtoPix2(c,c,c));
1294 		}
1295 
1296 		pd += pitchd;
1297 		ps += pitchs;
1298 	}
1299 }
1300 
1301 /** 1bit パターンから転送 */
1302 
mPixbufBltFrom1bit(mPixbuf * p,int dx,int dy,const uint8_t * pat,int sx,int sy,int w,int h,int patw,mPixCol col_1,mPixCol col_0)1303 void mPixbufBltFrom1bit(mPixbuf *p,int dx,int dy,
1304 	const uint8_t *pat,int sx,int sy,int w,int h,int patw,mPixCol col_1,mPixCol col_0)
1305 {
1306 	mPixbufBltInfo info;
1307 	uint8_t *pd,fleft,f;
1308 	const uint8_t *ps,*psY;
1309 	int ix,iy,pitchDst,pitchSrc;
1310 
1311 	if(!__mPixbufBltClip(&info, p, dx, dy, sx, sy, w, h)) return;
1312 
1313 	pd = mPixbufGetBufPtFast(p, info.dx, info.dy);
1314 
1315 	pitchDst = p->pitch_dir - info.w * p->bpp;
1316 	pitchSrc = (patw + 7) >> 3;
1317 
1318 	psY = pat + info.sy * pitchSrc + (info.sx >> 3);
1319 	fleft = 1 << (info.sx & 7);
1320 
1321 	for(iy = info.h; iy; iy--, pd += pitchDst, psY += pitchSrc)
1322 	{
1323 		ps = psY;
1324 		f = fleft;
1325 
1326 		for(ix = info.w; ix; ix--, pd += p->bpp)
1327 		{
1328 			(p->setbuf)(pd, (*ps & f)? col_1: col_0);
1329 
1330 			f <<= 1;
1331 			if(!f) f = 1, ps++;
1332 		}
1333 	}
1334 }
1335 
1336 /** 2bit パターンから転送 (最大4色) */
1337 
mPixbufBltFrom2bit(mPixbuf * p,int dx,int dy,const uint8_t * pat,int sx,int sy,int w,int h,int patw,mPixCol * col)1338 void mPixbufBltFrom2bit(mPixbuf *p,int dx,int dy,
1339 	const uint8_t *pat,int sx,int sy,int w,int h,int patw,mPixCol *col)
1340 {
1341 	mPixbufBltInfo info;
1342 	uint8_t *pd;
1343 	const uint8_t *ps,*ps_y;
1344 	int ix,iy,pitchDst,pitchSrc,bit_left,bit;
1345 
1346 	if(!__mPixbufBltClip(&info, p, dx, dy, sx, sy, w, h)) return;
1347 
1348 	pd = mPixbufGetBufPtFast(p, info.dx, info.dy);
1349 
1350 	pitchDst = p->pitch_dir - info.w * p->bpp;
1351 	pitchSrc = (patw + 3) >> 2;
1352 
1353 	ps_y = pat + info.sy * pitchSrc + (info.sx >> 2);
1354 	bit_left = (info.sx & 3) << 1;
1355 
1356 	for(iy = info.h; iy; iy--, pd += pitchDst, ps_y += pitchSrc)
1357 	{
1358 		ps = ps_y;
1359 		bit = bit_left;
1360 
1361 		for(ix = info.w; ix; ix--, pd += p->bpp)
1362 		{
1363 			(p->setbuf)(pd, col[(*ps >> bit) & 3]);
1364 
1365 			bit += 2;
1366 			if(bit == 8) { bit = 0; ps++; }
1367 		}
1368 	}
1369 }
1370 
1371 
1372 //==========================
1373 // 図形描画
1374 //==========================
1375 
1376 
1377 /** 3D枠描画 */
1378 
mPixbufDraw3DFrame(mPixbuf * p,int x,int y,int w,int h,mPixCol col_lt,mPixCol col_dk)1379 void mPixbufDraw3DFrame(mPixbuf *p,int x,int y,int w,int h,mPixCol col_lt,mPixCol col_dk)
1380 {
1381 	mPixbufLineH(p, x, y, w, col_lt);
1382 	mPixbufLineV(p, x, y + 1, h - 1, col_lt);
1383 
1384 	mPixbufLineH(p, x + 1, y + h - 1, w - 1, col_dk);
1385 	mPixbufLineV(p, x + w - 1, y + 1, h - 2, col_dk);
1386 }
1387 
1388 /** ビットパターンから描画
1389  *
1390  * ビット順は下位 -> 上位の順。\n
1391  * bit=1 は col で描画。bit=0 は描画しない。 */
1392 
mPixbufDrawBitPattern(mPixbuf * p,int x,int y,const uint8_t * pat,int patw,int path,mPixCol col)1393 void mPixbufDrawBitPattern(mPixbuf *p,int x,int y,
1394 	const uint8_t *pat,int patw,int path,mPixCol col)
1395 {
1396 	mBox box;
1397 	uint8_t *pd,f,fleft;
1398 	const uint8_t *ps,*ps_y;
1399 	int ix,iy,pitchDst,pitchSrc;
1400 
1401 	if(!mPixbufGetClipBox_d(p, &box, x, y, patw, path)) return;
1402 
1403 	pd = mPixbufGetBufPtFast(p, box.x, box.y);
1404 
1405 	pitchDst = p->pitch_dir - box.w * p->bpp;
1406 	pitchSrc = (patw + 7) >> 3;
1407 
1408 	x = box.x - x;
1409 	y = box.y - y;
1410 
1411 	ps_y = pat + y * pitchSrc + (x >> 3);
1412 	fleft = 1 << (x & 7);
1413 
1414 	for(iy = box.h; iy; iy--, pd += pitchDst, ps_y += pitchSrc)
1415 	{
1416 		ps = ps_y;
1417 		f  = fleft;
1418 
1419 		for(ix = box.w; ix; ix--, pd += p->bpp)
1420 		{
1421 			if(*ps & f)
1422 				(p->setbuf)(pd, col);
1423 
1424 			f <<= 1;
1425 			if(!f) f = 1, ps++;
1426 		}
1427 	}
1428 }
1429 
1430 /** 横にひと続きのビットパターンから指定番号のパターンを複数描画 (1bit)
1431  *
1432  * @param number 255 で終了 */
1433 
mPixbufDrawBitPatternSum(mPixbuf * p,int x,int y,const uint8_t * pat,int patw,int path,int eachw,const uint8_t * number,mPixCol col)1434 void mPixbufDrawBitPatternSum(mPixbuf *p,int x,int y,
1435 	const uint8_t *pat,int patw,int path,int eachw,const uint8_t *number,mPixCol col)
1436 {
1437 	const uint8_t *ps,*psY;
1438 	int ix,iy,pitchs,sx,f,fleft;
1439 
1440 	pitchs = (patw + 7) >> 3;
1441 
1442 	for(; *number != 255; x += eachw)
1443 	{
1444 		sx = *(number++) * eachw;
1445 		if(sx >= patw) break;
1446 
1447 		psY = pat + (sx >> 3);
1448 		fleft = 1 << (sx & 7);
1449 
1450 		for(iy = 0; iy < path; iy++, psY += pitchs)
1451 		{
1452 			for(ix = 0, ps = psY, f = fleft; ix < eachw; ix++)
1453 			{
1454 				if(*ps & f)
1455 					mPixbufSetPixel(p, x + ix, y + iy, col);
1456 
1457 				f <<= 1;
1458 				if(f == 256) f = 1, ps++;
1459 			}
1460 		}
1461 	}
1462 }
1463 
1464 /** 2bit のイメージパターンから描画
1465  *
1466  * @param pcol 4色分の色。全ビットが 1 で透過。 */
1467 
mPixbufDraw2bitPattern(mPixbuf * p,int x,int y,const uint8_t * pat,int patw,int path,mPixCol * pcol)1468 void mPixbufDraw2bitPattern(mPixbuf *p,int x,int y,const uint8_t *pat,int patw,int path,mPixCol *pcol)
1469 {
1470 	mPixbufBltInfo info;
1471 	uint8_t *pd;
1472 	const uint8_t *ps,*ps_y;
1473 	int ix,iy,pitchDst,pitchSrc,bit_left,bit;
1474 	mPixCol col;
1475 
1476 	if(!__mPixbufBltClip(&info, p, x, y, 0, 0, patw, path)) return;
1477 
1478 	pd = mPixbufGetBufPtFast(p, info.dx, info.dy);
1479 
1480 	pitchDst = p->pitch_dir - info.w * p->bpp;
1481 	pitchSrc = (patw + 3) >> 2;
1482 
1483 	ps_y = pat + info.sy * pitchSrc + (info.sx >> 2);
1484 	bit_left = (info.sx & 3) << 1;
1485 
1486 	for(iy = info.h; iy; iy--, pd += pitchDst, ps_y += pitchSrc)
1487 	{
1488 		ps = ps_y;
1489 		bit = bit_left;
1490 
1491 		for(ix = info.w; ix; ix--, pd += p->bpp)
1492 		{
1493 			col = pcol[(*ps >> bit) & 3];
1494 
1495 			if(col != (mPixCol)-1)
1496 				(p->setbuf)(pd, col);
1497 
1498 			bit += 2;
1499 			if(bit == 8) { bit = 0; ps++; }
1500 		}
1501 	}
1502 }
1503 
1504 /** 横にひと続きのビットパターンから指定番号のパターンを複数描画 (2bit)
1505  *
1506  * @param number 255 で終了
1507  * @param pcol  全ビットONで透過 */
1508 
mPixbufDraw2BitPatternSum(mPixbuf * p,int x,int y,const uint8_t * pat,int patw,int path,int eachw,const uint8_t * number,mPixCol * pcol)1509 void mPixbufDraw2BitPatternSum(mPixbuf *p,int x,int y,
1510 	const uint8_t *pat,int patw,int path,int eachw,const uint8_t *number,mPixCol *pcol)
1511 {
1512 	const uint8_t *ps,*psY;
1513 	int ix,iy,pitchs,sx,bitleft,bit;
1514 	mPixCol col;
1515 
1516 	pitchs = (patw + 3) >> 2;
1517 
1518 	for(; *number != 255; x += eachw)
1519 	{
1520 		sx = *(number++) * eachw;
1521 		if(sx >= patw) break;
1522 
1523 		//
1524 
1525 		psY = pat + (sx >> 2);
1526 		bitleft = (sx & 3) << 1;
1527 
1528 		for(iy = 0; iy < path; iy++, psY += pitchs)
1529 		{
1530 			ps = psY;
1531 			bit = bitleft;
1532 
1533 			for(ix = 0; ix < eachw; ix++)
1534 			{
1535 				col = pcol[(*ps >> bit) & 3];
1536 
1537 				if(col != (mPixCol)-1)
1538 					mPixbufSetPixel(p, x + ix, y + iy, col);
1539 
1540 				bit += 2;
1541 				if(bit == 8) { bit = 0; ps++; }
1542 			}
1543 		}
1544 	}
1545 }
1546 
1547 /** 数字とドットをテキストから描画
1548  *
1549  * 数字は 5x7。ドットは 3x7。 */
1550 
mPixbufDrawNumber_5x7(mPixbuf * p,int x,int y,const char * text,mPixCol col)1551 void mPixbufDrawNumber_5x7(mPixbuf *p,int x,int y,const char *text,mPixCol col)
1552 {
1553 	uint8_t pat[42] = {
1554 		0x6f,0xff,0xf9,0xff,0xff,0x00, 0x49,0x88,0x19,0x91,0x99,0x00,
1555 		0x49,0x88,0x19,0x91,0x99,0x00, 0x49,0xff,0xff,0x8f,0xff,0x00,
1556 		0x49,0x81,0x88,0x89,0x89,0x00, 0x49,0x81,0x88,0x89,0x89,0x03,
1557 		0xef,0xff,0xf8,0x8f,0x8f,0x03 };
1558 	int w,sx,ix,iy;
1559 	uint8_t f,fleft,*ps,*psY;
1560 
1561 	for(; *text; text++)
1562 	{
1563 		if(*text == '.')
1564 			sx = 4 * 10, w = 2;
1565 		else if(*text >= '0' && *text <= '9')
1566 			sx = (*text - '0') * 4, w = 4;
1567 		else
1568 			continue;
1569 
1570 		//
1571 
1572 		psY = pat + (sx >> 3);
1573 		fleft = 1 << (sx & 7);
1574 
1575 		for(iy = 0; iy < 7; iy++)
1576 		{
1577 			ps = psY;
1578 			f = fleft;
1579 
1580 			for(ix = 0; ix < w; ix++)
1581 			{
1582 				if(*ps & f)
1583 					mPixbufSetPixel(p, x + ix, y + iy, col);
1584 
1585 				f <<= 1;
1586 				if(f == 0) f = 1, ps++;
1587 			}
1588 
1589 			psY += 6;
1590 		}
1591 
1592 		x += w + 1;
1593 	}
1594 }
1595 
1596 /** チェック描画 (10x9) */
1597 
mPixbufDrawChecked(mPixbuf * p,int x,int y,mPixCol col)1598 void mPixbufDrawChecked(mPixbuf *p,int x,int y,mPixCol col)
1599 {
1600 	uint8_t pat[] = {
1601 		0x00,0x02,0x00,0x03,0x80,0x03,0xc3,0x03,0xe7,0x01,0xff,0x00,0x7e,0x00,0x3c,0x00,0x18,0x00
1602 	};
1603 
1604 	mPixbufDrawBitPattern(p, x, y, pat, 10, 9, col);
1605 }
1606 
1607 /** メニュー用チェック描画 (8x7) */
1608 
mPixbufDrawMenuChecked(mPixbuf * p,int x,int y,mPixCol col)1609 void mPixbufDrawMenuChecked(mPixbuf *p,int x,int y,mPixCol col)
1610 {
1611 	uint8_t pat[] = { 0x80,0xc0,0x60,0x31,0x1b,0x0e,0x04 };
1612 
1613 	mPixbufDrawBitPattern(p, x, y, pat, 8, 7, col);
1614 }
1615 
1616 /** メニュー用ラジオ描画 (5x5) */
1617 
mPixbufDrawMenuRadio(mPixbuf * p,int x,int y,mPixCol col)1618 void mPixbufDrawMenuRadio(mPixbuf *p,int x,int y,mPixCol col)
1619 {
1620 	uint8_t pat[] = { 0x0e,0x1f,0x1f,0x1f,0x0e };
1621 
1622 	mPixbufDrawBitPattern(p, x, y, pat, 5, 5, col);
1623 }
1624 
1625 /** ボタン描画 */
1626 
mPixbufDrawButton(mPixbuf * p,int x,int y,int w,int h,uint32_t flags)1627 void mPixbufDrawButton(mPixbuf *p,int x,int y,int w,int h,uint32_t flags)
1628 {
1629 	mPixCol col;
1630 
1631 	//背景
1632 
1633 	mPixbufFillBox(p, x, y, w, h,
1634 		(flags & MPIXBUF_DRAWBTT_FOCUS)? MSYSCOL(FACE_FOCUS): MSYSCOL(FACE_DARK));
1635 
1636 	//枠色
1637 
1638 	if(flags & MPIXBUF_DRAWBTT_DISABLE)
1639 		col = MSYSCOL(FRAME_LIGHT);
1640 	else if(flags & (MPIXBUF_DRAWBTT_DEFAULT_BUTTON | MPIXBUF_DRAWBTT_FOCUS))
1641 		col = MSYSCOL(FRAME_FOCUS);
1642 	else
1643 		col = MSYSCOL(FRAME);
1644 
1645 	//枠とフォーカス
1646 
1647 	if(flags & MPIXBUF_DRAWBTT_PRESS)
1648 	{
1649 		mPixbufLineH(p, x, y, w, col);
1650 		mPixbufLineV(p, x, y + 1, h - 1, col);
1651 	}
1652 	else
1653 	{
1654 		mPixbufBox(p, x, y, w, h, col);
1655 
1656 		if(flags & MPIXBUF_DRAWBTT_FOCUS)
1657 			mPixbufBoxDash(p, x + 2, y + 2, w - 4, h - 4, MSYSCOL(TEXT));
1658 	}
1659 }
1660 
1661 /** チェックボックス描画 (13x13) */
1662 
mPixbufDrawCheckBox(mPixbuf * p,int x,int y,uint32_t flags)1663 void mPixbufDrawCheckBox(mPixbuf *p,int x,int y,uint32_t flags)
1664 {
1665 	mPixCol colframe,col;
1666 	mPoint pt[4];
1667 
1668 	colframe = (flags & MPIXBUF_DRAWCKBOX_DISABLE)?
1669 			MSYSCOL(FRAME_LIGHT): MSYSCOL(FRAME_DARK);
1670 
1671 	//背景
1672 
1673 	mPixbufFillBox(p, x + 1, y + 1, 11, 11, MSYSCOL(FACE_LIGHTEST));
1674 
1675 	//
1676 
1677 	col = (flags & MPIXBUF_DRAWCKBOX_DISABLE)? MSYSCOL(TEXT_DISABLE): MSYSCOL(TEXT);
1678 
1679 	if(flags & MPIXBUF_DRAWCKBOX_RADIO)
1680 	{
1681 		//------ ラジオ
1682 
1683 		//枠
1684 
1685 		mPixbufLineH(p, x + 2, y, 9, colframe);
1686 		mPixbufLineH(p, x + 2, y + 12, 9, colframe);
1687 		mPixbufLineV(p, x, y + 2, 9, colframe);
1688 		mPixbufLineV(p, x + 12, y + 2, 9, colframe);
1689 
1690 		pt[0].x = x + 1;  pt[0].y = y + 1;
1691 		pt[1].x = x + 11; pt[1].y = y + 1;
1692 		pt[2].x = x + 11; pt[2].y = y + 11;
1693 		pt[3].x = x + 1;  pt[3].y = y + 11;
1694 
1695 		mPixbufSetPixels(p, pt, 4, colframe);
1696 
1697 		//
1698 
1699 		if(flags & MPIXBUF_DRAWCKBOX_CHECKED)
1700 		{
1701 			mPixbufFillBox(p, x + 2, y + 3, 9, 7, col);
1702 			mPixbufLineH(p, x + 3, y + 2, 7, col);
1703 			mPixbufLineH(p, x + 3, y + 10, 7, col);
1704 		}
1705 	}
1706 	else
1707 	{
1708 		//----- 通常
1709 
1710 		mPixbufBox(p, x, y, 13, 13, colframe);
1711 
1712 		if(flags & MPIXBUF_DRAWCKBOX_CHECKED)
1713 			mPixbufDrawChecked(p, x + 2, y + 2, col);
1714 	}
1715 }
1716 
1717 /** 下矢印描画 (5x3) */
1718 
mPixbufDrawArrowDown(mPixbuf * p,int ctx,int cty,mPixCol col)1719 void mPixbufDrawArrowDown(mPixbuf *p,int ctx,int cty,mPixCol col)
1720 {
1721 	uint8_t pat[] = { 0x1f,0x0e,0x04 };
1722 
1723 	mPixbufDrawBitPattern(p, ctx - 2, cty - 1, pat, 5, 3, col);
1724 }
1725 
1726 /** 上矢印描画 (5x3) */
1727 
mPixbufDrawArrowUp(mPixbuf * p,int ctx,int cty,mPixCol col)1728 void mPixbufDrawArrowUp(mPixbuf *p,int ctx,int cty,mPixCol col)
1729 {
1730 	uint8_t pat[] = { 0x04,0x0e,0x1f };
1731 
1732 	mPixbufDrawBitPattern(p, ctx - 2, cty - 1, pat, 5, 3, col);
1733 }
1734 
1735 /** 左矢印描画 (3x5) */
1736 
mPixbufDrawArrowLeft(mPixbuf * p,int ctx,int cty,mPixCol col)1737 void mPixbufDrawArrowLeft(mPixbuf *p,int ctx,int cty,mPixCol col)
1738 {
1739 	uint8_t pat[] = { 0x04,0x06,0x07,0x06,0x04 };
1740 
1741 	mPixbufDrawBitPattern(p, ctx - 1, cty - 2, pat, 3, 5, col);
1742 }
1743 
1744 /** 右矢印描画 (3x5) */
1745 
mPixbufDrawArrowRight(mPixbuf * p,int ctx,int cty,mPixCol col)1746 void mPixbufDrawArrowRight(mPixbuf *p,int ctx,int cty,mPixCol col)
1747 {
1748 	uint8_t pat[] = { 0x01,0x03,0x07,0x03,0x01 };
1749 
1750 	mPixbufDrawBitPattern(p, ctx - 1, cty - 2, pat, 3, 5, col);
1751 }
1752 
1753 /** 下矢印(小)描画 (3x2)*/
1754 
mPixbufDrawArrowDown_small(mPixbuf * p,int ctx,int y,mPixCol col)1755 void mPixbufDrawArrowDown_small(mPixbuf *p,int ctx,int y,mPixCol col)
1756 {
1757 	uint8_t pat[] = {0x07,0x02};
1758 
1759 	mPixbufDrawBitPattern(p, ctx - 1, y, pat, 3, 2, col);
1760 }
1761 
1762 /** 上矢印(小)描画 (3x2)*/
1763 
mPixbufDrawArrowUp_small(mPixbuf * p,int ctx,int y,mPixCol col)1764 void mPixbufDrawArrowUp_small(mPixbuf *p,int ctx,int y,mPixCol col)
1765 {
1766 	uint8_t pat[] = {0x02,0x07};
1767 
1768 	mPixbufDrawBitPattern(p, ctx - 1, y, pat, 3, 2, col);
1769 }
1770 
1771 /** 下矢印描画 (7x4) */
1772 
mPixbufDrawArrowDown_7x4(mPixbuf * p,int x,int y,mPixCol col)1773 void mPixbufDrawArrowDown_7x4(mPixbuf *p,int x,int y,mPixCol col)
1774 {
1775 	uint8_t pat[] = { 0x7f,0x3e,0x1c,0x08 };
1776 
1777 	mPixbufDrawBitPattern(p, x, y, pat, 7, 4, col);
1778 }
1779 
1780 /** 右矢印描画 (4x7) */
1781 
mPixbufDrawArrowRight_4x7(mPixbuf * p,int x,int y,mPixCol col)1782 void mPixbufDrawArrowRight_4x7(mPixbuf *p,int x,int y,mPixCol col)
1783 {
1784 	uint8_t pat[] = { 0x01,0x03,0x07,0x0f,0x07,0x03,0x01 };
1785 
1786 	mPixbufDrawBitPattern(p, x, y, pat, 4, 7, col);
1787 }
1788 
1789 /** 下矢印描画 (13x7) */
1790 
mPixbufDrawArrowDown_13x7(mPixbuf * p,int ctx,int cty,mPixCol col)1791 void mPixbufDrawArrowDown_13x7(mPixbuf *p,int ctx,int cty,mPixCol col)
1792 {
1793 	uint8_t pat[] = { 0xff,0x1f,0xfe,0x0f,0xfc,0x07,0xf8,0x03,0xf0,0x01,0xe0,0x00,0x40,0x00 };
1794 
1795 	mPixbufDrawBitPattern(p, ctx - 6, cty - 3, pat, 13, 7, col);
1796 }
1797 
1798 /** 下矢印描画 (13x7) */
1799 
mPixbufDrawArrowUp_13x7(mPixbuf * p,int ctx,int cty,mPixCol col)1800 void mPixbufDrawArrowUp_13x7(mPixbuf *p,int ctx,int cty,mPixCol col)
1801 {
1802 	uint8_t pat[] = { 0x40,0x00,0xe0,0x00,0xf0,0x01,0xf8,0x03,0xfc,0x07,0xfe,0x0f,0xff,0x1f };
1803 
1804 	mPixbufDrawBitPattern(p, ctx - 6, cty - 3, pat, 13, 7, col);
1805 }
1806 
1807 /** 左矢印描画 (7x13) */
1808 
mPixbufDrawArrowLeft_7x13(mPixbuf * p,int ctx,int cty,mPixCol col)1809 void mPixbufDrawArrowLeft_7x13(mPixbuf *p,int ctx,int cty,mPixCol col)
1810 {
1811 	uint8_t pat[] = { 0x40,0x60,0x70,0x78,0x7c,0x7e,0x7f,0x7e,0x7c,0x78,0x70,0x60,0x40 };
1812 
1813 	mPixbufDrawBitPattern(p, ctx - 3, cty - 6, pat, 7, 13, col);
1814 }
1815 
1816 /** 右矢印描画 (7x13) */
1817 
mPixbufDrawArrowRight_7x13(mPixbuf * p,int ctx,int cty,mPixCol col)1818 void mPixbufDrawArrowRight_7x13(mPixbuf *p,int ctx,int cty,mPixCol col)
1819 {
1820 	uint8_t pat[] = { 0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01 };
1821 
1822 	mPixbufDrawBitPattern(p, ctx - 3, cty - 6, pat, 7, 13, col);
1823 }
1824 
1825 /** @} */
1826