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