1 /* Copyright (C) 2000-2012 by George Williams */
2 /*
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5
6 * Redistributions of source code must retain the above copyright notice, this
7 * list of conditions and the following disclaimer.
8
9 * Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12
13 * The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <fontforge-config.h>
29
30 #if !defined(X_DISPLAY_MISSING) && !defined(FONTFORGE_CAN_USE_GDK)
31
32 #include "gxcdrawP.h"
33 #include "gxdrawP.h"
34
35 #include <math.h>
36 #include <string.h>
37
38 /* On the cygwin X server masking with mono images is broken */
39 #ifdef _BrokenBitmapImages
40 # undef FAST_BITS
41 # define FAST_BITS 0
42 #endif
43
44 /* On some X displays (my linux box for instance) bitmap drawing is very */
45 /* slow when compared to 24bit drawing. So if FAST_BITS is set then use */
46 /* 1 bit masks otherwise use the depth of the screen */
47 #ifndef FAST_BITS
48 #define FAST_BITS 0
49 #endif
50
intersect_rectangles(GRect * rect,GRect * clip)51 static void intersect_rectangles(GRect *rect, GRect *clip) {
52 if ( rect->x < clip->x ) {
53 rect->width -= (clip->x - rect->x);
54 if ( rect->width < 0 ) rect->width = 0;
55 rect->x = clip->x;
56 }
57 if ( rect->x + rect->width > clip->x + clip->width ) {
58 rect->width = clip->x + clip->width - rect->x;
59 if ( rect->width < 0 ) rect->width = 0;
60 }
61 if ( rect->y < clip->y ) {
62 rect->height -= (clip->y - rect->y);
63 if ( rect->height < 0 ) rect->height = 0;
64 rect->y = clip->y;
65 }
66 if ( rect->y + rect->height > clip->y + clip->height ) {
67 rect->height = clip->y + clip->height - rect->y;
68 if ( rect->height < 0 ) rect->height = 0;
69 }
70 }
71
gdraw_8_on_1_nomag_dithered_masked(GXDisplay * gdisp,GImage * image,GRect * src)72 static void gdraw_8_on_1_nomag_dithered_masked(GXDisplay *gdisp,GImage *image,
73 GRect *src) {
74 struct gcol clut[256];
75 int i,j, index;
76 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
77 int trans = base->trans;
78 unsigned char *pt, *ipt, *mpt;
79 short *g_d;
80 register int gd;
81 struct gcol *pos;
82 int bit;
83
84 _GDraw_getimageclut(base,clut);
85
86 for ( i=src->width-1; i>=0; --i )
87 gdisp->gg.green_dith[i] = 0;
88
89 for ( i=src->y; i<src->y+src->height; ++i ) {
90 pt = (unsigned char *) (base->data) + i*base->bytes_per_line + src->x;
91 ipt = (unsigned char *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
92 mpt = (unsigned char *) (gdisp->gg.mask->data) + (i-src->y)*gdisp->gg.mask->bytes_per_line;
93 if ( gdisp->gg.img->bitmap_bit_order == MSBFirst )
94 bit = 0x80;
95 else
96 bit = 0x1;
97 gd = 0;
98 g_d = gdisp->gg.green_dith;
99 for ( j=src->width-1; j>=0; --j ) {
100 index = *pt++;
101 if ( index==trans ) {
102 *mpt |= bit;
103 *ipt &= ~bit;
104 ++g_d;
105 } else {
106 *mpt &= ~bit;
107 pos = &clut[index];
108 gd += *g_d + pos->red + pos->green + pos->blue;
109 if ( gd<3*128 ) {
110 *ipt &= ~bit;
111 *g_d++ = gd /= 2;
112 } else {
113 *ipt |= bit;
114 *g_d++ = gd = (gd - 3*255)/2;
115 }
116 }
117 if ( gdisp->gg.img->bitmap_bit_order == MSBFirst ) {
118 if (( bit>>=1 )==0 ) {bit=0x80; ++ipt; ++mpt;};
119 } else {
120 if (( bit<<=1 )==256 ) {bit=0x1; ++ipt; ++mpt;};
121 }
122 }
123 }
124 }
125
gdraw_32_on_1_nomag_dithered_masked(GXDisplay * gdisp,GImage * image,GRect * src)126 static void gdraw_32_on_1_nomag_dithered_masked(GXDisplay *gdisp, GImage *image, GRect *src) {
127 int i,j, index;
128 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
129 int trans = base->trans;
130 uint32 *pt;
131 uint8 *ipt, *mpt;
132 short *g_d;
133 register int gd;
134 int bit;
135
136 for ( i=src->width-1; i>=0; --i )
137 gdisp->gg.green_dith[i] = 0;
138
139 for ( i=src->y; i<src->y+src->height; ++i ) {
140 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
141 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
142 mpt = (uint8 *) (gdisp->gg.mask->data) + (i-src->y)*gdisp->gg.mask->bytes_per_line;
143 if ( gdisp->gg.img->bitmap_bit_order == MSBFirst )
144 bit = 0x80;
145 else
146 bit = 0x1;
147 gd = 0;
148 g_d = gdisp->gg.green_dith;
149 for ( j=src->width-1; j>=0; --j ) {
150 index = *pt++;
151 if ( index==trans ) {
152 *mpt |= bit;
153 *ipt &= ~bit;
154 ++g_d;
155 } else {
156 *mpt &= ~bit;
157 gd += *g_d + COLOR_RED(index) + COLOR_GREEN(index) + COLOR_BLUE(index);
158 if ( gd<3*128 ) {
159 *ipt &= ~bit;
160 *g_d++ = gd /= 2;
161 } else {
162 *ipt |= bit;
163 *g_d++ = gd = (gd - 3*255)/2;
164 }
165 }
166 if ( gdisp->gg.img->bitmap_bit_order == MSBFirst ) {
167 if (( bit>>=1 )==0 ) {bit=0x80; ++ipt; ++mpt;};
168 } else {
169 if (( bit<<=1 )==256 ) {bit=0x1; ++ipt; ++mpt;};
170 }
171 }
172 }
173 }
174
gdraw_32a_on_1_nomag_dithered(GXDisplay * gdisp,GImage * image,GRect * src)175 static void gdraw_32a_on_1_nomag_dithered(GXDisplay *gdisp, GImage *image, GRect *src) {
176 int i,j;
177 unsigned int index;
178 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
179 int trans = base->trans;
180 uint32 *pt;
181 uint8 *ipt, *mpt;
182 short *g_d;
183 register int gd;
184 int bit;
185
186 for ( i=src->width-1; i>=0; --i )
187 gdisp->gg.green_dith[i] = 0;
188
189 for ( i=src->y; i<src->y+src->height; ++i ) {
190 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
191 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
192 mpt = (uint8 *) (gdisp->gg.mask->data) + (i-src->y)*gdisp->gg.mask->bytes_per_line;
193 if ( gdisp->gg.img->bitmap_bit_order == MSBFirst )
194 bit = 0x80;
195 else
196 bit = 0x1;
197 gd = 0;
198 g_d = gdisp->gg.green_dith;
199 for ( j=src->width-1; j>=0; --j ) {
200 index = *pt++;
201 if ( index==trans || (index>>24)<0x80 ) {
202 *mpt |= bit;
203 *ipt &= ~bit;
204 ++g_d;
205 } else {
206 *mpt &= ~bit;
207 gd += *g_d + COLOR_RED(index) + COLOR_GREEN(index) + COLOR_BLUE(index);
208 if ( gd<3*128 ) {
209 *ipt &= ~bit;
210 *g_d++ = gd /= 2;
211 } else {
212 *ipt |= bit;
213 *g_d++ = gd = (gd - 3*255)/2;
214 }
215 }
216 if ( gdisp->gg.img->bitmap_bit_order == MSBFirst ) {
217 if (( bit>>=1 )==0 ) {bit=0x80; ++ipt; ++mpt;};
218 } else {
219 if (( bit<<=1 )==256 ) {bit=0x1; ++ipt; ++mpt;};
220 }
221 }
222 }
223 }
224
gdraw_8_on_1_nomag_dithered_nomask(GXDisplay * gdisp,GImage * image,GRect * src)225 static void gdraw_8_on_1_nomag_dithered_nomask(GXDisplay *gdisp, GImage *image, GRect *src) {
226 struct gcol clut[256];
227 int i,j, index;
228 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
229 unsigned char *pt, *ipt;
230 short *g_d;
231 register int gd;
232 struct gcol *pos;
233 int bit;
234
235 _GDraw_getimageclut(base,clut);
236
237 for ( i=src->width-1; i>=0; --i )
238 gdisp->gg.green_dith[i] = 0;
239
240 for ( i=src->y; i<src->y+src->height; ++i ) {
241 pt = (unsigned char *) (base->data) + i*base->bytes_per_line + src->x;
242 ipt = (unsigned char *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
243 if ( gdisp->gg.img->bitmap_bit_order == MSBFirst )
244 bit = 0x80;
245 else
246 bit = 0x1;
247 gd = 0;
248 g_d = gdisp->gg.green_dith;
249 for ( j=src->width-1; j>=0; --j ) {
250 index = *pt++;
251 pos = &clut[index];
252 gd += *g_d + pos->red + pos->green + pos->blue;
253 if ( gd<3*128 ) {
254 *ipt &= ~bit;
255 *g_d++ = gd /= 2;
256 } else {
257 *ipt |= bit;
258 *g_d++ = gd = (gd - 3*255)/2;
259 }
260 if ( gdisp->gg.img->bitmap_bit_order == MSBFirst ) {
261 if (( bit>>=1 )==0 ) {bit=0x80; ++ipt;};
262 } else {
263 if (( bit<<=1 )==256 ) {bit=0x1; ++ipt;};
264 }
265 }
266 }
267 }
268
gdraw_32_on_1_nomag_dithered_nomask(GXDisplay * gdisp,GImage * image,GRect * src)269 static void gdraw_32_on_1_nomag_dithered_nomask(GXDisplay *gdisp, GImage *image, GRect *src) {
270 struct gcol clut[256];
271 int i,j, index;
272 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
273 uint32 *pt;
274 uint8 *ipt;
275 short *g_d;
276 register int gd;
277 int bit;
278
279 _GDraw_getimageclut(base,clut);
280
281 for ( i=src->width-1; i>=0; --i )
282 gdisp->gg.green_dith[i] = 0;
283
284 for ( i=src->y; i<src->y+src->height; ++i ) {
285 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
286 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
287 if ( gdisp->gg.img->bitmap_bit_order == MSBFirst )
288 bit = 0x80;
289 else
290 bit = 0x1;
291 gd = 0;
292 g_d = gdisp->gg.green_dith;
293 for ( j=src->width-1; j>=0; --j ) {
294 index = *pt++;
295 gd += *g_d + COLOR_RED(index) + COLOR_GREEN(index) + COLOR_BLUE(index);
296 if ( gd<3*128 ) {
297 *ipt &= ~bit;
298 *g_d++ = gd /= 2;
299 } else {
300 *ipt |= bit;
301 *g_d++ = gd = (gd - 3*255)/2;
302 }
303 if ( gdisp->gg.img->bitmap_bit_order == MSBFirst ) {
304 if (( bit>>=1 )==0 ) {bit=0x80; ++ipt;};
305 } else {
306 if (( bit<<=1 )==256 ) {bit=0x1; ++ipt;};
307 }
308 }
309 }
310 }
311
gdraw_8_on_8_nomag_dithered_masked(GXDisplay * gdisp,GImage * image,GRect * src)312 static void gdraw_8_on_8_nomag_dithered_masked(GXDisplay *gdisp, GImage *image, GRect *src) {
313 struct gcol clut[256];
314 int i,j, index;
315 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
316 int trans = base->trans;
317 uint8 *pt, *ipt, *mpt;
318 short *r_d, *g_d, *b_d;
319 register int rd, gd, bd;
320 const struct gcol *pos;
321 #if FAST_BITS
322 int mbit;
323 #endif
324
325 _GDraw_getimageclut(base,clut);
326
327 for ( i=src->width-1; i>=0; --i )
328 gdisp->gg.red_dith[i]= gdisp->gg.green_dith[i] = gdisp->gg.blue_dith[i] = 0;
329
330 for ( i=src->y; i<src->y+src->height; ++i ) {
331 pt = (uint8 *) (base->data) + i*base->bytes_per_line + src->x;
332 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
333 mpt = (uint8 *) (gdisp->gg.mask->data) + (i-src->y)*gdisp->gg.mask->bytes_per_line;
334 #if FAST_BITS
335 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst )
336 mbit = 0x80;
337 else
338 mbit = 0x1;
339 #endif
340 rd = gd = bd = 0;
341 r_d = gdisp->gg.red_dith; g_d = gdisp->gg.green_dith; b_d = gdisp->gg.blue_dith;
342 for ( j=src->width-1; j>=0; --j ) {
343 index = *pt++;
344 if ( index==trans ) {
345 #if FAST_BITS==0
346 *mpt++ = 0xff;
347 #else
348 *mpt |= mbit;
349 #endif
350 *ipt++ = 0x00;
351 ++r_d; ++g_d; ++b_d;
352 } else {
353 pos = &clut[index];
354 rd += *r_d + pos->red; if ( rd<0 ) rd=0; else if ( rd>255 ) rd = 255;
355 gd += *g_d + pos->green; if ( gd<0 ) gd=0; else if ( gd>255 ) gd = 255;
356 bd += *b_d + pos->blue; if ( bd<0 ) bd=0; else if ( bd>255 ) bd = 255;
357 pos = _GImage_GetIndexedPixel(COLOR_CREATE(rd,gd,bd), gdisp->cs.rev);
358 *ipt++ = pos->pixel;
359 *r_d++ = rd = (rd - pos->red)/2;
360 *g_d++ = gd = (gd - pos->green)/2;
361 *b_d++ = bd = (bd - pos->blue)/2;
362 #if FAST_BITS==0
363 *mpt++ = 0;
364 #else
365 *mpt &= ~mbit;
366 #endif
367 }
368 #if FAST_BITS
369 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst ) {
370 if (( mbit>>=1 )==0 ) {mbit=0x80; ++mpt;};
371 } else {
372 if (( mbit<<=1 )==256 ) {mbit=0x1; ++mpt;};
373 }
374 #endif
375 }
376 }
377 }
378
gdraw_8_on_8_nomag_nodithered_masked(GXDisplay * gdisp,GImage * image,GRect * src)379 static void gdraw_8_on_8_nomag_nodithered_masked(GXDisplay *gdisp, GImage *image, GRect *src) {
380 struct gcol clut[256];
381 register int j;
382 int i,index;
383 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
384 int trans = base->trans;
385 register uint8 *pt, *ipt, *mpt;
386 struct gcol *pos; const struct gcol *temp;
387 #if FAST_BITS
388 int mbit;
389 #endif
390
391 _GDraw_getimageclut(base,clut);
392 for ( i=base->clut->clut_len-1; i>=0; --i ) {
393 pos = &clut[i];
394 temp = _GImage_GetIndexedPixel(COLOR_CREATE(pos->red,pos->green,pos->blue),gdisp->cs.rev);
395 pos->pixel = temp->pixel;
396 }
397
398 for ( i=src->y; i<src->y+src->height; ++i ) {
399 pt = (uint8 *) (base->data) + i*base->bytes_per_line + src->x;
400 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
401 mpt = (uint8 *) (gdisp->gg.mask->data) + (i-src->y)*gdisp->gg.mask->bytes_per_line;
402 #if FAST_BITS
403 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst )
404 mbit = 0x80;
405 else
406 mbit = 0x1;
407 #endif
408 for ( j=src->width-1; j>=0; --j ) {
409 index = *pt++;
410 if ( index==trans ) {
411 #if FAST_BITS==0
412 *mpt++ = 0xff;
413 #else
414 *mpt |= mbit;
415 #endif
416 *ipt++ = 0x00;
417 } else {
418 *ipt++ = clut[index].pixel;
419 #if FAST_BITS==0
420 *mpt++ = 0;
421 #else
422 *mpt &= ~mbit;
423 #endif
424 }
425 #if FAST_BITS
426 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst ) {
427 if (( mbit>>=1 )==0 ) {mbit=0x80; ++mpt;};
428 } else {
429 if (( mbit<<=1 )==256 ) {mbit=0x1; ++mpt;};
430 }
431 #endif
432 }
433 }
434 }
435
gdraw_32_on_8_nomag_dithered_masked(GXDisplay * gdisp,GImage * image,GRect * src)436 static void gdraw_32_on_8_nomag_dithered_masked(GXDisplay *gdisp, GImage *image, GRect *src) {
437 int i,j;
438 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
439 int trans = base->trans;
440 uint32 *pt, index;
441 uint8 *ipt, *mpt;
442 short *r_d, *g_d, *b_d;
443 register int rd, gd, bd;
444 const struct gcol *pos;
445 #if FAST_BITS
446 int mbit;
447 #endif
448
449 for ( i=src->width-1; i>=0; --i )
450 gdisp->gg.red_dith[i]= gdisp->gg.green_dith[i] = gdisp->gg.blue_dith[i] = 0;
451
452 for ( i=src->y; i<src->y+src->height; ++i ) {
453 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
454 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
455 mpt = (uint8 *) (gdisp->gg.mask->data) + (i-src->y)*gdisp->gg.mask->bytes_per_line;
456 #if FAST_BITS
457 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst )
458 mbit = 0x80;
459 else
460 mbit = 0x1;
461 #endif
462 rd = gd = bd = 0;
463 r_d = gdisp->gg.red_dith; g_d = gdisp->gg.green_dith; b_d = gdisp->gg.blue_dith;
464 for ( j=src->width-1; j>=0; --j ) {
465 index = *pt++;
466 if ( index==trans ) {
467 #if FAST_BITS==0
468 *mpt++ = 0xff;
469 #else
470 *mpt |= mbit;
471 #endif
472 *ipt++ = 0x00;
473 ++r_d; ++g_d; ++b_d;
474 } else {
475 rd += *r_d + ((index>>16)&0xff); if ( rd<0 ) rd=0; else if ( rd>255 ) rd = 255;
476 gd += *g_d + ((index>>8)&0xff); if ( gd<0 ) gd=0; else if ( gd>255 ) gd = 255;
477 bd += *b_d + (index&0xff); if ( bd<0 ) bd=0; else if ( bd>255 ) bd = 255;
478 pos = _GImage_GetIndexedPixel(COLOR_CREATE(rd,gd,bd),gdisp->cs.rev);
479 *ipt++ = pos->pixel;
480 *r_d++ = rd = (rd - pos->red)/2;
481 *g_d++ = gd = (gd - pos->green)/2;
482 *b_d++ = bd = (bd - pos->blue)/2;
483 #if FAST_BITS==0
484 *mpt++ = 0;
485 #else
486 *mpt &= ~mbit;
487 #endif
488 }
489 #if FAST_BITS
490 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst ) {
491 if (( mbit>>=1 )==0 ) {mbit=0x80; ++mpt;};
492 } else {
493 if (( mbit<<=1 )==256 ) {mbit=0x1; ++mpt;};
494 }
495 #endif
496 }
497 }
498 }
499
gdraw_32a_on_8_nomag_dithered(GXDisplay * gdisp,GImage * image,GRect * src)500 static void gdraw_32a_on_8_nomag_dithered(GXDisplay *gdisp, GImage *image, GRect *src) {
501 int i,j;
502 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
503 int trans = base->trans;
504 uint32 *pt, index;
505 uint8 *ipt, *mpt;
506 short *r_d, *g_d, *b_d;
507 register int rd, gd, bd;
508 const struct gcol *pos;
509 #if FAST_BITS
510 int mbit;
511 #endif
512
513 for ( i=src->width-1; i>=0; --i )
514 gdisp->gg.red_dith[i]= gdisp->gg.green_dith[i] = gdisp->gg.blue_dith[i] = 0;
515
516 for ( i=src->y; i<src->y+src->height; ++i ) {
517 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
518 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
519 mpt = (uint8 *) (gdisp->gg.mask->data) + (i-src->y)*gdisp->gg.mask->bytes_per_line;
520 #if FAST_BITS
521 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst )
522 mbit = 0x80;
523 else
524 mbit = 0x1;
525 #endif
526 rd = gd = bd = 0;
527 r_d = gdisp->gg.red_dith; g_d = gdisp->gg.green_dith; b_d = gdisp->gg.blue_dith;
528 for ( j=src->width-1; j>=0; --j ) {
529 index = *pt++;
530 if ( index==trans || (index>>24)<0x80 ) {
531 #if FAST_BITS==0
532 *mpt++ = 0xff;
533 #else
534 *mpt |= mbit;
535 #endif
536 *ipt++ = 0x00;
537 ++r_d; ++g_d; ++b_d;
538 } else {
539 rd += *r_d + ((index>>16)&0xff); if ( rd<0 ) rd=0; else if ( rd>255 ) rd = 255;
540 gd += *g_d + ((index>>8)&0xff); if ( gd<0 ) gd=0; else if ( gd>255 ) gd = 255;
541 bd += *b_d + (index&0xff); if ( bd<0 ) bd=0; else if ( bd>255 ) bd = 255;
542 pos = _GImage_GetIndexedPixel(COLOR_CREATE(rd,gd,bd),gdisp->cs.rev);
543 *ipt++ = pos->pixel;
544 *r_d++ = rd = (rd - pos->red)/2;
545 *g_d++ = gd = (gd - pos->green)/2;
546 *b_d++ = bd = (bd - pos->blue)/2;
547 #if FAST_BITS==0
548 *mpt++ = 0;
549 #else
550 *mpt &= ~mbit;
551 #endif
552 }
553 #if FAST_BITS
554 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst ) {
555 if (( mbit>>=1 )==0 ) {mbit=0x80; ++mpt;};
556 } else {
557 if (( mbit<<=1 )==256 ) {mbit=0x1; ++mpt;};
558 }
559 #endif
560 }
561 }
562 }
563
gdraw_32_on_8_nomag_nodithered_masked(GXDisplay * gdisp,GImage * image,GRect * src)564 static void gdraw_32_on_8_nomag_nodithered_masked(GXDisplay *gdisp, GImage *image, GRect *src) {
565 int i,j;
566 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
567 int trans = base->trans;
568 uint32 *pt, index;
569 register uint8 *ipt, *mpt;
570 #if FAST_BITS
571 int mbit;
572 #endif
573
574 for ( i=src->y; i<src->y+src->height; ++i ) {
575 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
576 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
577 mpt = (uint8 *) (gdisp->gg.mask->data) + (i-src->y)*gdisp->gg.mask->bytes_per_line;
578 #if FAST_BITS
579 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst )
580 mbit = 0x80;
581 else
582 mbit = 0x1;
583 #endif
584 for ( j=src->width-1; j>=0; --j ) {
585 index = *pt++;
586 if ( index==trans ) {
587 #if FAST_BITS==0
588 *mpt++ = 0xff;
589 #else
590 *mpt |= mbit;
591 #endif
592 *ipt++ = 0x00;
593 } else {
594 *ipt++ = _GXDraw_GetScreenPixel(gdisp,index);
595 #if FAST_BITS==0
596 *mpt++ = 0;
597 #else
598 *mpt &= ~mbit;
599 #endif
600 }
601 #if FAST_BITS
602 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst ) {
603 if (( mbit>>=1 )==0 ) {mbit=0x80; ++mpt;};
604 } else {
605 if (( mbit<<=1 )==256 ) {mbit=0x1; ++mpt;};
606 }
607 #endif
608 }
609 }
610 }
611
gdraw_32a_on_8_nomag_nodithered(GXDisplay * gdisp,GImage * image,GRect * src)612 static void gdraw_32a_on_8_nomag_nodithered(GXDisplay *gdisp, GImage *image, GRect *src) {
613 int i,j;
614 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
615 int trans = base->trans;
616 uint32 *pt, index;
617 register uint8 *ipt, *mpt;
618 #if FAST_BITS
619 int mbit;
620 #endif
621
622 for ( i=src->y; i<src->y+src->height; ++i ) {
623 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
624 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
625 mpt = (uint8 *) (gdisp->gg.mask->data) + (i-src->y)*gdisp->gg.mask->bytes_per_line;
626 #if FAST_BITS
627 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst )
628 mbit = 0x80;
629 else
630 mbit = 0x1;
631 #endif
632 for ( j=src->width-1; j>=0; --j ) {
633 index = *pt++;
634 if ( (index==trans && trans!=-1 ) || (index>>24)<0x80 ) {
635 #if FAST_BITS==0
636 *mpt++ = 0xff;
637 #else
638 *mpt |= mbit;
639 #endif
640 *ipt++ = 0x00;
641 } else {
642 *ipt++ = _GXDraw_GetScreenPixel(gdisp,index);
643 #if FAST_BITS==0
644 *mpt++ = 0;
645 #else
646 *mpt &= ~mbit;
647 #endif
648 }
649 #if FAST_BITS
650 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst ) {
651 if (( mbit>>=1 )==0 ) {mbit=0x80; ++mpt;};
652 } else {
653 if (( mbit<<=1 )==256 ) {mbit=0x1; ++mpt;};
654 }
655 #endif
656 }
657 }
658 }
659
gdraw_8_on_8_nomag_dithered_nomask(GXDisplay * gdisp,GImage * image,GRect * src)660 static void gdraw_8_on_8_nomag_dithered_nomask(GXDisplay *gdisp, GImage *image, GRect *src) {
661 struct gcol clut[256];
662 int i,j, index;
663 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
664 uint8 *pt, *ipt;
665 short *r_d, *g_d, *b_d;
666 register int rd, gd, bd;
667 const struct gcol *pos;
668
669 _GDraw_getimageclut(base,clut);
670
671 for ( i=src->width-1; i>=0; --i )
672 gdisp->gg.red_dith[i]= gdisp->gg.green_dith[i] = gdisp->gg.blue_dith[i] = 0;
673
674 for ( i=src->y; i<src->y+src->height; ++i ) {
675 pt = (uint8 *) (base->data) + i*base->bytes_per_line + src->x;
676 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
677 rd = gd = bd = 0;
678 r_d = gdisp->gg.red_dith; g_d = gdisp->gg.green_dith; b_d = gdisp->gg.blue_dith;
679 for ( j=src->width-1; j>=0; --j ) {
680 index = *pt++;
681 pos = &clut[index];
682 rd += *r_d + pos->red; if ( rd<0 ) rd=0; else if ( rd>255 ) rd = 255;
683 gd += *g_d + pos->green; if ( gd<0 ) gd=0; else if ( gd>255 ) gd = 255;
684 bd += *b_d + pos->blue; if ( bd<0 ) bd=0; else if ( bd>255 ) bd = 255;
685 pos = _GImage_GetIndexedPixel(COLOR_CREATE(rd,gd,bd),gdisp->cs.rev);
686 *ipt++ = pos->pixel;
687 *r_d++ = rd = (rd - pos->red)/2;
688 *g_d++ = gd = (gd - pos->green)/2;
689 *b_d++ = bd = (bd - pos->blue)/2;
690 }
691 }
692 }
693
gdraw_8_on_8_nomag_nodithered_nomask(GXDisplay * gdisp,GImage * image,GRect * src)694 static void gdraw_8_on_8_nomag_nodithered_nomask(GXDisplay *gdisp, GImage *image, GRect *src) {
695 struct gcol clut[256];
696 register int j;
697 int i,index;
698 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
699 register uint8 *pt, *ipt;
700 struct gcol *pos; const struct gcol *temp;
701
702 _GDraw_getimageclut(base,clut);
703 for ( i=base->clut->clut_len-1; i>=0; --i ) {
704 pos = &clut[i];
705 temp = _GImage_GetIndexedPixel(COLOR_CREATE(pos->red,pos->green,pos->blue),gdisp->cs.rev);
706 pos->pixel = temp->pixel;
707 }
708
709 for ( i=src->y; i<src->y+src->height; ++i ) {
710 pt = (uint8 *) (base->data) + i*base->bytes_per_line + src->x;
711 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
712 for ( j=src->width-1; j>=0; --j ) {
713 index = *pt++;
714 *ipt++ = clut[index].pixel;
715 }
716 }
717 }
718
gdraw_32_on_8_nomag_dithered_nomask(GXDisplay * gdisp,GImage * image,GRect * src)719 static void gdraw_32_on_8_nomag_dithered_nomask(GXDisplay *gdisp, GImage *image, GRect *src) {
720 int i,j;
721 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
722 uint32 *pt, index;
723 uint8 *ipt;
724 short *r_d, *g_d, *b_d;
725 register int rd, gd, bd;
726 const struct gcol *pos;
727
728 for ( i=src->width-1; i>=0; --i )
729 gdisp->gg.red_dith[i]= gdisp->gg.green_dith[i] = gdisp->gg.blue_dith[i] = 0;
730
731 for ( i=src->y; i<src->y+src->height; ++i ) {
732 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
733 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
734 rd = gd = bd = 0;
735 r_d = gdisp->gg.red_dith; g_d = gdisp->gg.green_dith; b_d = gdisp->gg.blue_dith;
736 for ( j=src->width-1; j>=0; --j ) {
737 index = *pt++;
738 rd += *r_d + COLOR_RED(index); if ( rd<0 ) rd=0; else if ( rd>255 ) rd = 255;
739 gd += *g_d + COLOR_GREEN(index); if ( gd<0 ) gd=0; else if ( gd>255 ) gd = 255;
740 bd += *b_d + COLOR_BLUE(index); if ( bd<0 ) bd=0; else if ( bd>255 ) bd = 255;
741 pos = _GImage_GetIndexedPixel(COLOR_CREATE(rd,gd,bd),gdisp->cs.rev);
742 *ipt++ = pos->pixel;
743 *r_d++ = rd = (rd - pos->red)/2;
744 *g_d++ = gd = (gd - pos->green)/2;
745 *b_d++ = bd = (bd - pos->blue)/2;
746 }
747 }
748 }
749
gdraw_32_on_8_nomag_nodithered_nomask(GXDisplay * gdisp,GImage * image,GRect * src)750 static void gdraw_32_on_8_nomag_nodithered_nomask(GXDisplay *gdisp, GImage *image, GRect *src) {
751 int i,j;
752 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
753 uint32 *pt, index;
754 register uint8 *ipt;
755
756 for ( i=src->y; i<src->y+src->height; ++i ) {
757 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
758 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
759 for ( j=src->width-1; j>=0; --j ) {
760 index = *pt++;
761 *ipt++ = _GXDraw_GetScreenPixel(gdisp,index);
762 }
763 }
764 }
765
gdraw_8_on_16_nomag_masked(GXDisplay * gdisp,GImage * image,GRect * src)766 static void gdraw_8_on_16_nomag_masked(GXDisplay *gdisp, GImage *image, GRect *src) {
767 struct gcol clut[256];
768 register int j;
769 int i,index;
770 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
771 int trans = base->trans;
772 #if FAST_BITS==0
773 uint16 *mpt;
774 #else
775 int mbit;
776 uint8 *mpt;
777 #endif
778 register uint8 *pt;
779 uint16 *ipt;
780 struct gcol *pos;
781 Color col;
782
783 _GDraw_getimageclut(base,clut);
784 for ( i=base->clut->clut_len-1; i>=0; --i ) {
785 pos = &clut[i];
786 col = (pos->red<<16)|(pos->green<<8)|pos->blue;
787 pos->pixel = Pixel16(gdisp,col);
788 if ( gdisp->endian_mismatch )
789 pos->pixel = FixEndian16(pos->pixel);
790 }
791
792 for ( i=src->y; i<src->y+src->height; ++i ) {
793 pt = (uint8 *) (base->data) + i*base->bytes_per_line + src->x;
794 ipt = (uint16 *) (gdisp->gg.img->data + (i-src->y)*gdisp->gg.img->bytes_per_line);
795 #if FAST_BITS==0
796 mpt = (uint16 *) (gdisp->gg.mask->data + (i-src->y)*gdisp->gg.mask->bytes_per_line);
797 #else
798 mpt = (uint8 *) (gdisp->gg.mask->data + (i-src->y)*gdisp->gg.mask->bytes_per_line);
799 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst )
800 mbit = 0x80;
801 else
802 mbit = 0x1;
803 #endif
804 for ( j=src->width-1; j>=0; --j ) {
805 index = *pt++;
806 if ( index==trans ) {
807 #if FAST_BITS==0
808 *mpt++ = 0xffff;
809 #else
810 *mpt |= mbit;
811 #endif
812 *ipt++ = 0x00;
813 } else {
814 *ipt++ = clut[index].pixel;
815 #if FAST_BITS==0
816 *mpt++ = 0;
817 #else
818 *mpt &= ~mbit;
819 #endif
820 }
821 #if FAST_BITS
822 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst ) {
823 if (( mbit>>=1 )==0 ) {mbit=0x80; ++mpt;};
824 } else {
825 if (( mbit<<=1 )==256 ) {mbit=0x1; ++mpt;};
826 }
827 #endif
828 }
829 }
830 }
831
gdraw_32_on_16_nomag_masked(GXDisplay * gdisp,GImage * image,GRect * src)832 static void gdraw_32_on_16_nomag_masked(GXDisplay *gdisp, GImage *image, GRect *src) {
833 int i,j;
834 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
835 int trans = base->trans;
836 register uint32 *pt, index;
837 register uint16 *ipt;
838 int endian_mismatch = gdisp->endian_mismatch;
839 #if FAST_BITS==0
840 register uint16 *mpt;
841 #else
842 register uint8 *mpt;
843 int mbit;
844 #endif
845
846 for ( i=src->y; i<src->y+src->height; ++i ) {
847 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
848 ipt = (uint16 *) (gdisp->gg.img->data + (i-src->y)*gdisp->gg.img->bytes_per_line);
849 #if FAST_BITS==0
850 mpt = (uint16 *) (gdisp->gg.mask->data + (i-src->y)*gdisp->gg.mask->bytes_per_line);
851 #else
852 mpt = (uint8 *) (gdisp->gg.mask->data + (i-src->y)*gdisp->gg.mask->bytes_per_line);
853 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst )
854 mbit = 0x80;
855 else
856 mbit = 0x1;
857 #endif
858 for ( j=src->width-1; j>=0; --j ) {
859 index = *pt++;
860 if ( index==trans ) {
861 *ipt++ = 0x00;
862 #if FAST_BITS==0
863 *mpt++ = 0xffff;
864 #else
865 *mpt |= mbit;
866 #endif
867 } else {
868 *ipt++ = Pixel16(gdisp,index);
869 if ( endian_mismatch )
870 ipt[-1] = FixEndian16(ipt[-1]);
871 #if FAST_BITS==0
872 *mpt++ = 0;
873 #else
874 *mpt &= ~mbit;
875 #endif
876 }
877 #if FAST_BITS
878 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst ) {
879 if (( mbit>>=1 )==0 ) {mbit=0x80; ++mpt;};
880 } else {
881 if (( mbit<<=1 )==256 ) {mbit=0x1; ++mpt;};
882 }
883 #endif
884 }
885 }
886 }
887
gdraw_32a_on_16_nomag(GXDisplay * gdisp,GImage * image,GRect * src)888 static void gdraw_32a_on_16_nomag(GXDisplay *gdisp, GImage *image, GRect *src) {
889 int i,j;
890 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
891 int trans = base->trans;
892 register uint32 *pt, index;
893 register uint16 *ipt;
894 int endian_mismatch = gdisp->endian_mismatch;
895 #if FAST_BITS==0
896 register uint16 *mpt;
897 #else
898 register uint8 *mpt;
899 int mbit;
900 #endif
901
902 for ( i=src->y; i<src->y+src->height; ++i ) {
903 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
904 ipt = (uint16 *) (gdisp->gg.img->data + (i-src->y)*gdisp->gg.img->bytes_per_line);
905 #if FAST_BITS==0
906 mpt = (uint16 *) (gdisp->gg.mask->data + (i-src->y)*gdisp->gg.mask->bytes_per_line);
907 #else
908 mpt = (uint8 *) (gdisp->gg.mask->data + (i-src->y)*gdisp->gg.mask->bytes_per_line);
909 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst )
910 mbit = 0x80;
911 else
912 mbit = 0x1;
913 #endif
914 for ( j=src->width-1; j>=0; --j ) {
915 index = *pt++;
916 if ( (index==trans && trans!=-1 ) || (index>>24)<0x80 ) {
917 *ipt++ = 0x00;
918 #if FAST_BITS==0
919 *mpt++ = 0xffff;
920 #else
921 *mpt |= mbit;
922 #endif
923 } else {
924 *ipt++ = Pixel16(gdisp,index);
925 if ( endian_mismatch )
926 ipt[-1] = FixEndian16(ipt[-1]);
927 #if FAST_BITS==0
928 *mpt++ = 0;
929 #else
930 *mpt &= ~mbit;
931 #endif
932 }
933 #if FAST_BITS
934 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst ) {
935 if (( mbit>>=1 )==0 ) {mbit=0x80; ++mpt;};
936 } else {
937 if (( mbit<<=1 )==256 ) {mbit=0x1; ++mpt;};
938 }
939 #endif
940 }
941 }
942 }
943
gdraw_8_on_16_nomag_nomask(GXDisplay * gdisp,GImage * image,GRect * src)944 static void gdraw_8_on_16_nomag_nomask(GXDisplay *gdisp, GImage *image, GRect *src) {
945 struct gcol clut[256];
946 register int j;
947 int i,index;
948 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
949 register uint8 *pt;
950 uint16 *ipt;
951 struct gcol *pos;
952 Color col;
953
954 _GDraw_getimageclut(base,clut);
955 for ( i=base->clut->clut_len-1; i>=0; --i ) {
956 pos = &clut[i];
957 col = (pos->red<<16)|(pos->green<<8)|pos->blue;
958 pos->pixel = Pixel16(gdisp,col);
959 if ( gdisp->endian_mismatch )
960 pos->pixel = FixEndian16(pos->pixel);
961 }
962
963 for ( i=src->y; i<src->y+src->height; ++i ) {
964 pt = (uint8 *) (base->data) + i*base->bytes_per_line + src->x;
965 ipt = (uint16 *) (gdisp->gg.img->data + (i-src->y)*gdisp->gg.img->bytes_per_line);
966 for ( j=src->width-1; j>=0; --j ) {
967 index = *pt++;
968 *ipt++ = clut[index].pixel;
969 }
970 }
971 }
972
gdraw_32_on_16_nomag_nomask(GXDisplay * gdisp,GImage * image,GRect * src)973 static void gdraw_32_on_16_nomag_nomask(GXDisplay *gdisp, GImage *image, GRect *src) {
974 int i,j;
975 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
976 register uint32 *pt, index;
977 register uint16 *ipt;
978 int endian_mismatch = gdisp->endian_mismatch;
979
980 for ( i=src->y; i<src->y+src->height; ++i ) {
981 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
982 ipt = (uint16 *) (gdisp->gg.img->data + (i-src->y)*gdisp->gg.img->bytes_per_line);
983 for ( j=src->width-1; j>=0; --j ) {
984 index = *pt++;
985 *ipt++ = Pixel16(gdisp,index);
986 if ( endian_mismatch )
987 ipt[-1] = FixEndian16(ipt[-1]);
988 }
989 }
990 }
991
gdraw_8_on_any_nomag_glyph(GXDisplay * gdisp,GImage * image,GRect * src)992 static void gdraw_8_on_any_nomag_glyph(GXDisplay *gdisp, GImage *image, GRect *src) {
993 struct gcol clut[256];
994 register int j;
995 int i,index;
996 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
997 int trans = base->trans;
998 register uint8 *pt;
999 struct gcol *pos;
1000 Color col;
1001 int msbf = gdisp->gg.img->byte_order == MSBFirst/*,
1002 msBf = gdisp->gg.mask->bitmap_bit_order == MSBFirst*/;
1003
1004 _GDraw_getimageclut(base,clut);
1005
1006 if ( gdisp->pixel_size==16 ) {
1007 uint16 *ipt;
1008 for ( i=base->clut->clut_len-1; i>=0; --i ) {
1009 pos = &clut[i];
1010 col = (pos->red<<16)|(pos->green<<8)|pos->blue;
1011 pos->pixel = Pixel16(gdisp,col);
1012 if ( i==trans )
1013 pos->pixel = Pixel16(gdisp,0xffffff);
1014 if ( gdisp->endian_mismatch )
1015 pos->pixel = FixEndian16(pos->pixel);
1016 }
1017
1018 for ( i=src->y; i<src->y+src->height; ++i ) {
1019 pt = (uint8 *) (base->data) + i*base->bytes_per_line + src->x;
1020 ipt = (uint16 *) (gdisp->gg.img->data + (i-src->y)*gdisp->gg.img->bytes_per_line);
1021 for ( j=src->width-1; j>=0; --j ) {
1022 index = *pt++;
1023 *ipt++ = clut[index].pixel;
1024 }
1025 }
1026 } else if ( gdisp->pixel_size==24 ) {
1027 uint8 *ipt;
1028 for ( i=base->clut->clut_len-1; i>=0; --i ) {
1029 pos = &clut[i];
1030 pos->pixel = Pixel24(gdisp,COLOR_CREATE(pos->red,pos->green,pos->blue));
1031 if ( i==trans )
1032 pos->pixel = Pixel24(gdisp,0xffffff);
1033 }
1034
1035 for ( i=src->y; i<src->y+src->height; ++i ) {
1036 pt = (uint8 *) (base->data) + i*base->bytes_per_line + src->x;
1037 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
1038 for ( j=src->width-1; j>=0; --j ) {
1039 register uint32 col;
1040 index = *pt++;
1041 col = clut[index].pixel;
1042 if ( msbf ) {
1043 *ipt++ = col>>16;
1044 *ipt++ = (col>>8)&0xff;
1045 *ipt++ = col&0xff;
1046 } else {
1047 *ipt++ = col&0xff;
1048 *ipt++ = (col>>8)&0xff;
1049 *ipt++ = col>>16;
1050 }
1051 }
1052 }
1053 } else {
1054 uint32 *ipt;
1055 for ( i=base->clut->clut_len-1; i>=0; --i ) {
1056 pos = &clut[i];
1057 pos->pixel = Pixel32(gdisp,COLOR_CREATE(pos->red,pos->green,pos->blue));
1058 if ( i==trans )
1059 pos->pixel = 0xffffffff;
1060 if ( gdisp->endian_mismatch )
1061 pos->pixel = FixEndian32(pos->pixel);
1062 }
1063
1064 for ( i=src->y; i<src->y+src->height; ++i ) {
1065 pt = (uint8 *) (base->data) + i*base->bytes_per_line + src->x;
1066 ipt = (uint32 *) (gdisp->gg.img->data + (i-src->y)*gdisp->gg.img->bytes_per_line);
1067 for ( j=src->width-1; j>=0; --j ) {
1068 index = *pt++;
1069 *ipt++ = clut[index].pixel;
1070 }
1071 }
1072 }
1073 }
1074
gdraw_8_on_24_nomag_masked(GXDisplay * gdisp,GImage * image,GRect * src)1075 static void gdraw_8_on_24_nomag_masked(GXDisplay *gdisp, GImage *image, GRect *src) {
1076 struct gcol clut[256];
1077 register int j;
1078 int i,index;
1079 #if FAST_BITS
1080 int mbit;
1081 #endif
1082 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
1083 int trans = base->trans;
1084 register uint8 *ipt;
1085 register uint8 *pt, *mpt;
1086 struct gcol *pos;
1087 int msbf = gdisp->gg.img->byte_order == MSBFirst/*,
1088 msBf = gdisp->gg.mask->bitmap_bit_order == MSBFirst*/;
1089
1090 _GDraw_getimageclut(base,clut);
1091 for ( i=base->clut->clut_len-1; i>=0; --i ) {
1092 pos = &clut[i];
1093 pos->pixel = Pixel24(gdisp,COLOR_CREATE(pos->red,pos->green,pos->blue));
1094 }
1095
1096 for ( i=src->y; i<src->y+src->height; ++i ) {
1097 pt = (uint8 *) (base->data) + i*base->bytes_per_line + src->x;
1098 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
1099 mpt = (uint8 *) (gdisp->gg.mask->data) + (i-src->y)*gdisp->gg.mask->bytes_per_line;
1100 #if FAST_BITS
1101 if ( msBf )
1102 mbit = 0x80;
1103 else
1104 mbit = 0x1;
1105 #endif
1106 for ( j=src->width-1; j>=0; --j ) {
1107 index = *pt++;
1108 if ( index==trans ) {
1109 #if FAST_BITS==0
1110 *mpt++ = 0xff; *mpt++ = 0xff; *mpt++ = 0xff;
1111 #else
1112 *mpt |= mbit;
1113 #endif
1114 *ipt++ = 0x00; *ipt++ = 0x00; *ipt++ = 0x00;
1115 } else {
1116 register uint32 col = clut[index].pixel;
1117 if ( msbf ) {
1118 *ipt++ = col>>16;
1119 *ipt++ = (col>>8)&0xff;
1120 *ipt++ = col&0xff;
1121 } else {
1122 *ipt++ = col&0xff;
1123 *ipt++ = (col>>8)&0xff;
1124 *ipt++ = col>>16;
1125 }
1126 #if FAST_BITS==0
1127 *mpt++ = 0; *mpt++ = 0; *mpt++ = 0;
1128 #else
1129 *mpt &= ~mbit;
1130 #endif
1131 }
1132 #if FAST_BITS
1133 if ( msBf ) {
1134 if (( mbit>>=1 )==0 ) {mbit=0x80; ++mpt; };
1135 } else {
1136 if (( mbit<<=1 )==256 ) {mbit=0x1; ++mpt;};
1137 }
1138 #endif
1139 }
1140 }
1141 }
1142
gdraw_32_on_24_nomag_masked(GXDisplay * gdisp,GImage * image,GRect * src)1143 static void gdraw_32_on_24_nomag_masked(GXDisplay *gdisp, GImage *image, GRect *src) {
1144 int i,j;
1145 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
1146 int trans = base->trans;
1147 register uint32 *pt, index;
1148 register uint8 *mpt, *ipt;
1149 #if FAST_BITS
1150 int mbit;
1151 #endif
1152 int msbf = gdisp->gg.img->byte_order == MSBFirst;
1153
1154 for ( i=src->y; i<src->y+src->height; ++i ) {
1155 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
1156 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
1157 mpt = (uint8 *) (gdisp->gg.mask->data + (i-src->y)*gdisp->gg.mask->bytes_per_line);
1158 #if FAST_BITS
1159 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst )
1160 mbit = 0x80;
1161 else
1162 mbit = 0x1;
1163 #endif
1164 for ( j=src->width-1; j>=0; --j ) {
1165 index = *pt++;
1166 if ( index==trans ) {
1167 *ipt++ = 0x00; *ipt++ = 0x00; *ipt++ = 0x00;
1168 #if FAST_BITS==0
1169 *mpt++ = 0xff; *mpt++ = 0xff; *mpt++ = 0xff;
1170 #else
1171 *mpt |= mbit;
1172 #endif
1173 } else {
1174 index = Pixel24(gdisp,index);
1175 if ( msbf ) {
1176 *ipt++ = index>>16;
1177 *ipt++ = (index>>8)&0xff;
1178 *ipt++ = index&0xff;
1179 } else {
1180 *ipt++ = index&0xff;
1181 *ipt++ = (index>>8)&0xff;
1182 *ipt++ = index>>16;
1183 }
1184 #if FAST_BITS==0
1185 *mpt++ = 0; *mpt++ = 0; *mpt++ = 0;
1186 #else
1187 *mpt &= ~mbit;
1188 #endif
1189 }
1190 #if FAST_BITS
1191 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst ) {
1192 if (( mbit>>=1 )==0 ) {mbit=0x80; ++mpt;};
1193 } else {
1194 if (( mbit<<=1 )==256 ) {mbit=0x1; ++mpt;};
1195 }
1196 #endif
1197 }
1198 }
1199 }
1200
gdraw_32a_on_24_nomag(GXDisplay * gdisp,GImage * image,GRect * src)1201 static void gdraw_32a_on_24_nomag(GXDisplay *gdisp, GImage *image, GRect *src) {
1202 int i,j;
1203 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
1204 int trans = base->trans;
1205 register uint32 *pt, index;
1206 register uint8 *mpt, *ipt;
1207 #if FAST_BITS
1208 int mbit;
1209 #endif
1210 int msbf = gdisp->gg.img->byte_order == MSBFirst;
1211
1212 for ( i=src->y; i<src->y+src->height; ++i ) {
1213 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
1214 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
1215 mpt = (uint8 *) (gdisp->gg.mask->data + (i-src->y)*gdisp->gg.mask->bytes_per_line);
1216 #if FAST_BITS
1217 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst )
1218 mbit = 0x80;
1219 else
1220 mbit = 0x1;
1221 #endif
1222 for ( j=src->width-1; j>=0; --j ) {
1223 index = *pt++;
1224 if ( (index==trans && trans!=-1) || (index>>24)<0x80 ) {
1225 *ipt++ = 0x00; *ipt++ = 0x00; *ipt++ = 0x00;
1226 #if FAST_BITS==0
1227 *mpt++ = 0xff; *mpt++ = 0xff; *mpt++ = 0xff;
1228 #else
1229 *mpt |= mbit;
1230 #endif
1231 } else {
1232 index = Pixel24(gdisp,index);
1233 if ( msbf ) {
1234 *ipt++ = index>>16;
1235 *ipt++ = (index>>8)&0xff;
1236 *ipt++ = index&0xff;
1237 } else {
1238 *ipt++ = index&0xff;
1239 *ipt++ = (index>>8)&0xff;
1240 *ipt++ = index>>16;
1241 }
1242 #if FAST_BITS==0
1243 *mpt++ = 0; *mpt++ = 0; *mpt++ = 0;
1244 #else
1245 *mpt &= ~mbit;
1246 #endif
1247 }
1248 #if FAST_BITS
1249 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst ) {
1250 if (( mbit>>=1 )==0 ) {mbit=0x80; ++mpt;};
1251 } else {
1252 if (( mbit<<=1 )==256 ) {mbit=0x1; ++mpt;};
1253 }
1254 #endif
1255 }
1256 }
1257 }
1258
gdraw_8_on_24_nomag_nomask(GXDisplay * gdisp,GImage * image,GRect * src)1259 static void gdraw_8_on_24_nomag_nomask(GXDisplay *gdisp, GImage *image, GRect *src) {
1260 struct gcol clut[256];
1261 register uint8 *ipt;
1262 register uint8 *pt;
1263 register int index, j;
1264 int i;
1265 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
1266 struct gcol *pos;
1267
1268 _GDraw_getimageclut(base,clut);
1269 for ( i=base->clut->clut_len-1; i>=0; --i ) {
1270 pos = &clut[i];
1271 pos->pixel = Pixel24(gdisp,COLOR_CREATE(pos->red,pos->green,pos->blue));
1272 }
1273
1274 for ( i=src->y; i<src->y+src->height; ++i ) {
1275 pt = (uint8 *) (base->data) + i*base->bytes_per_line + src->x;
1276 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
1277 if ( gdisp->gg.img->byte_order == MSBFirst ) {
1278 for ( j=src->width-1; j>=0; --j ) {
1279 index = *pt++;
1280 index = clut[index].pixel;
1281 *ipt++ = index>>16;
1282 *ipt++ = (index>>8)&0xff;
1283 *ipt++ = index&0xff;
1284 }
1285 } else {
1286 for ( j=src->width-1; j>=0; --j ) {
1287 index = *pt++;
1288 index = clut[index].pixel;
1289 *ipt++ = index&0xff;
1290 *ipt++ = (index>>8)&0xff;
1291 *ipt++ = index>>16;
1292 }
1293 }
1294 }
1295 }
1296
gdraw_32_on_24_nomag_nomask(GXDisplay * gdisp,GImage * image,GRect * src)1297 static void gdraw_32_on_24_nomag_nomask(GXDisplay *gdisp, GImage *image, GRect *src) {
1298 int i,j;
1299 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
1300 register uint32 *pt, index;
1301 register uint8 *ipt;
1302
1303 for ( i=src->y; i<src->y+src->height; ++i ) {
1304 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
1305 ipt = (uint8 *) (gdisp->gg.img->data) + (i-src->y)*gdisp->gg.img->bytes_per_line;
1306 if ( gdisp->gg.img->byte_order == MSBFirst ) {
1307 for ( j=src->width-1; j>=0; --j ) {
1308 index = *pt++;
1309 index = Pixel24(gdisp,index);
1310 *ipt++ = index>>16;
1311 *ipt++ = (index>>8)&0xff;
1312 *ipt++ = index&0xff;
1313 }
1314 } else {
1315 for ( j=src->width-1; j>=0; --j ) {
1316 index = *pt++;
1317 index = Pixel24(gdisp,index);
1318 *ipt++ = index&0xff;
1319 *ipt++ = (index>>8)&0xff;
1320 *ipt++ = index>>16;
1321 }
1322 }
1323 }
1324 }
1325
gdraw_8_on_32a_nomag(GXDisplay * gdisp,GImage * image,GRect * src)1326 static void gdraw_8_on_32a_nomag(GXDisplay *gdisp, GImage *image, GRect *src) {
1327 struct gcol clut[256];
1328 register int j;
1329 int i,index;
1330 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
1331 int trans = base->trans;
1332 register uint8 *pt;
1333 uint32 *ipt;
1334 struct gcol *pos;
1335
1336 _GDraw_getimageclut(base,clut);
1337 for ( i=base->clut->clut_len-1; i>=0; --i ) {
1338 pos = &clut[i];
1339 pos->pixel = Pixel32(gdisp,COLOR_CREATE(pos->red,pos->green,pos->blue));
1340 if ( i==trans )
1341 pos->pixel = 0x00000000;
1342 if ( gdisp->endian_mismatch )
1343 pos->pixel = FixEndian32(pos->pixel);
1344 }
1345
1346 for ( i=src->y; i<src->y+src->height; ++i ) {
1347 pt = (uint8 *) (base->data) + i*base->bytes_per_line + src->x;
1348 ipt = (uint32 *) (gdisp->gg.img->data + (i-src->y)*gdisp->gg.img->bytes_per_line);
1349 for ( j=src->width-1; j>=0; --j ) {
1350 index = *pt++;
1351 *ipt++ = clut[index].pixel;
1352 }
1353 }
1354 }
1355
gdraw_8a_on_32a_nomag(GXDisplay * gdisp,GImage * image,GRect * src,Color fg)1356 static void gdraw_8a_on_32a_nomag(GXDisplay *gdisp, GImage *image, GRect *src,
1357 Color fg) {
1358 register int j;
1359 int i,index;
1360 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
1361 register uint8 *pt;
1362 uint32 *ipt;
1363 uint32 fg_pixel = Pixel32(gdisp,fg) & 0xffffff;
1364
1365 for ( i=src->y; i<src->y+src->height; ++i ) {
1366 pt = (uint8 *) (base->data) + i*base->bytes_per_line + src->x;
1367 ipt = (uint32 *) (gdisp->gg.img->data + (i-src->y)*gdisp->gg.img->bytes_per_line);
1368 for ( j=src->width-1; j>=0; --j ) {
1369 index = *pt++;
1370 *ipt++ = fg_pixel | (index<<24);
1371 }
1372 }
1373 }
1374
gdraw_32_on_32a_nomag(GXDisplay * gdisp,GImage * image,GRect * src)1375 static void gdraw_32_on_32a_nomag(GXDisplay *gdisp, GImage *image, GRect *src) {
1376 int i,j;
1377 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
1378 int trans = base->trans;
1379 register uint32 *pt, index, *ipt;
1380 int endian_mismatch = gdisp->endian_mismatch;
1381 int has_alpha = base->image_type == it_rgba;
1382
1383 for ( i=src->y; i<src->y+src->height; ++i ) {
1384 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
1385 ipt = (uint32 *) (gdisp->gg.img->data + (i-src->y)*gdisp->gg.img->bytes_per_line);
1386 for ( j=src->width-1; j>=0; --j ) {
1387 index = *pt++;
1388 if ( index==trans ) {
1389 *ipt++ = 0x00000000;
1390 } else {
1391 if ( has_alpha )
1392 *ipt++ = Pixel16(gdisp,(index&0xffffff)) | (index&0xff000000);
1393 else
1394 *ipt++ = Pixel32(gdisp,index);
1395 if ( endian_mismatch )
1396 ipt[-1] = FixEndian32(ipt[-1]);
1397 }
1398 }
1399 }
1400 }
1401
gdraw_8_on_32_nomag_masked(GXDisplay * gdisp,GImage * image,GRect * src)1402 static void gdraw_8_on_32_nomag_masked(GXDisplay *gdisp, GImage *image, GRect *src) {
1403 struct gcol clut[256];
1404 register int j;
1405 int i,index;
1406 #if FAST_BITS==0
1407 register uint32 *mpt;
1408 #else
1409 int mbit;
1410 register uint8 *mpt;
1411 #endif
1412 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
1413 int trans = base->trans;
1414 register uint8 *pt;
1415 uint32 *ipt;
1416 struct gcol *pos;
1417
1418 _GDraw_getimageclut(base,clut);
1419 for ( i=base->clut->clut_len-1; i>=0; --i ) {
1420 pos = &clut[i];
1421 pos->pixel = Pixel32(gdisp,COLOR_CREATE(pos->red,pos->green,pos->blue));
1422 if ( gdisp->endian_mismatch )
1423 pos->pixel = FixEndian32(pos->pixel);
1424 }
1425
1426 for ( i=src->y; i<src->y+src->height; ++i ) {
1427 pt = (uint8 *) (base->data) + i*base->bytes_per_line + src->x;
1428 ipt = (uint32 *) (gdisp->gg.img->data + (i-src->y)*gdisp->gg.img->bytes_per_line);
1429 #if FAST_BITS==0
1430 mpt = (uint32 *) (gdisp->gg.mask->data + (i-src->y)*gdisp->gg.mask->bytes_per_line);
1431 #else
1432 mpt = (uint8 *) (gdisp->gg.mask->data) + (i-src->y)*gdisp->gg.mask->bytes_per_line;
1433 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst )
1434 mbit = 0x80;
1435 else
1436 mbit = 0x1;
1437 #endif
1438 for ( j=src->width-1; j>=0; --j ) {
1439 index = *pt++;
1440 if ( index==trans ) {
1441 #if FAST_BITS==0
1442 *mpt++ = 0xffffffff;
1443 #else
1444 *mpt |= mbit;
1445 #endif
1446 *ipt++ = 0x00;
1447 } else {
1448 *ipt++ = clut[index].pixel;
1449 #if FAST_BITS==0
1450 *mpt++ = 0;
1451 #else
1452 *mpt &= ~mbit;
1453 #endif
1454 }
1455 #if FAST_BITS
1456 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst ) {
1457 if (( mbit>>=1 )==0 ) {mbit=0x80; ++mpt;};
1458 } else {
1459 if (( mbit<<=1 )==256 ) {mbit=0x1; ++mpt;};
1460 }
1461 #endif
1462 }
1463 }
1464 }
1465
gdraw_32_on_32_nomag_masked(GXDisplay * gdisp,GImage * image,GRect * src)1466 static void gdraw_32_on_32_nomag_masked(GXDisplay *gdisp, GImage *image, GRect *src) {
1467 int i,j;
1468 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
1469 int trans = base->trans;
1470 register uint32 *pt, index, *ipt;
1471 int endian_mismatch = gdisp->endian_mismatch;
1472 #if FAST_BITS==0
1473 register uint32 *mpt;
1474 #else
1475 register uint8 *mpt;
1476 int mbit;
1477 #endif
1478
1479 for ( i=src->y; i<src->y+src->height; ++i ) {
1480 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
1481 ipt = (uint32 *) (gdisp->gg.img->data + (i-src->y)*gdisp->gg.img->bytes_per_line);
1482 #if FAST_BITS==0
1483 mpt = (uint32 *) (gdisp->gg.mask->data + (i-src->y)*gdisp->gg.mask->bytes_per_line);
1484 #else
1485 mpt = (uint8 *) (gdisp->gg.mask->data + (i-src->y)*gdisp->gg.mask->bytes_per_line);
1486 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst )
1487 mbit = 0x80;
1488 else
1489 mbit = 0x1;
1490 #endif
1491 for ( j=src->width-1; j>=0; --j ) {
1492 index = *pt++;
1493 if ( index==trans ) {
1494 *ipt++ = Pixel32(gdisp,0);
1495 #if FAST_BITS==0
1496 *mpt++ = 0xffffffff;
1497 #else
1498 *mpt |= mbit;
1499 #endif
1500 } else {
1501 *ipt++ = Pixel32(gdisp,index);
1502 if ( endian_mismatch )
1503 ipt[-1] = FixEndian32(ipt[-1]);
1504 #if FAST_BITS==0
1505 *mpt++ = 0;
1506 #else
1507 *mpt &= ~mbit;
1508 #endif
1509 }
1510 #if FAST_BITS
1511 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst ) {
1512 if (( mbit>>=1 )==0 ) {mbit=0x80; ++mpt;};
1513 } else {
1514 if (( mbit<<=1 )==256 ) {mbit=0x1; ++mpt;};
1515 }
1516 #endif
1517 }
1518 }
1519 }
1520
gdraw_32a_on_32_nomag(GXDisplay * gdisp,GImage * image,GRect * src)1521 static void gdraw_32a_on_32_nomag(GXDisplay *gdisp, GImage *image, GRect *src) {
1522 int i,j;
1523 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
1524 int trans = base->trans;
1525 register uint32 *pt, index, *ipt;
1526 int endian_mismatch = gdisp->endian_mismatch;
1527 #if FAST_BITS==0
1528 register uint32 *mpt;
1529 #else
1530 register uint8 *mpt;
1531 int mbit;
1532 #endif
1533
1534 for ( i=src->y; i<src->y+src->height; ++i ) {
1535 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
1536 ipt = (uint32 *) (gdisp->gg.img->data + (i-src->y)*gdisp->gg.img->bytes_per_line);
1537 #if FAST_BITS==0
1538 mpt = (uint32 *) (gdisp->gg.mask->data + (i-src->y)*gdisp->gg.mask->bytes_per_line);
1539 #else
1540 mpt = (uint8 *) (gdisp->gg.mask->data + (i-src->y)*gdisp->gg.mask->bytes_per_line);
1541 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst )
1542 mbit = 0x80;
1543 else
1544 mbit = 0x1;
1545 #endif
1546 for ( j=src->width-1; j>=0; --j ) {
1547 index = *pt++;
1548 if ( (index==trans && trans!=-1) || (index>>24)<0x80 ) {
1549 *ipt++ = Pixel32(gdisp,0);
1550 #if FAST_BITS==0
1551 *mpt++ = 0xffffffff;
1552 #else
1553 *mpt |= mbit;
1554 #endif
1555 } else {
1556 *ipt++ = Pixel32(gdisp,index);
1557 if ( endian_mismatch )
1558 ipt[-1] = FixEndian32(ipt[-1]);
1559 #if FAST_BITS==0
1560 *mpt++ = 0;
1561 #else
1562 *mpt &= ~mbit;
1563 #endif
1564 }
1565 #if FAST_BITS
1566 if ( gdisp->gg.mask->bitmap_bit_order == MSBFirst ) {
1567 if (( mbit>>=1 )==0 ) {mbit=0x80; ++mpt;};
1568 } else {
1569 if (( mbit<<=1 )==256 ) {mbit=0x1; ++mpt;};
1570 }
1571 #endif
1572 }
1573 }
1574 }
1575
gdraw_8_on_32_nomag_nomask(GXDisplay * gdisp,GImage * image,GRect * src)1576 static void gdraw_8_on_32_nomag_nomask(GXDisplay *gdisp, GImage *image, GRect *src) {
1577 struct gcol clut[256];
1578 register int j;
1579 int i,index;
1580 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
1581 register uint8 *pt;
1582 uint32 *ipt;
1583 struct gcol *pos;
1584
1585 _GDraw_getimageclut(base,clut);
1586 for ( i=base->clut->clut_len-1; i>=0; --i ) {
1587 pos = &clut[i];
1588 pos->pixel = Pixel32(gdisp,COLOR_CREATE(pos->red,pos->green,pos->blue));
1589 if ( gdisp->endian_mismatch )
1590 pos->pixel = FixEndian32(pos->pixel);
1591 }
1592
1593 for ( i=src->y; i<src->y+src->height; ++i ) {
1594 pt = (uint8 *) (base->data) + i*base->bytes_per_line + src->x;
1595 ipt = (uint32 *) (gdisp->gg.img->data + (i-src->y)*gdisp->gg.img->bytes_per_line);
1596 for ( j=src->width-1; j>=0; --j ) {
1597 index = *pt++;
1598 *ipt++ = clut[index].pixel;
1599 }
1600 }
1601 }
1602
gdraw_32_on_32_nomag_nomask(GXDisplay * gdisp,GImage * image,GRect * src)1603 static void gdraw_32_on_32_nomag_nomask(GXDisplay *gdisp, GImage *image, GRect *src) {
1604 int i,j;
1605 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
1606 register uint32 *pt, index, *ipt;
1607 int endian_mismatch = gdisp->endian_mismatch;
1608
1609 for ( i=src->y; i<src->y+src->height; ++i ) {
1610 pt = (uint32 *) (base->data + i*base->bytes_per_line) + src->x;
1611 ipt = (uint32 *) (gdisp->gg.img->data + (i-src->y)*gdisp->gg.img->bytes_per_line);
1612 for ( j=src->width-1; j>=0; --j ) {
1613 index = *pt++;
1614 *ipt++ = Pixel32(gdisp,index);
1615 if ( endian_mismatch )
1616 ipt[-1] = FixEndian32(ipt[-1]);
1617 }
1618 }
1619 }
1620
gdraw_xbitmap(GXWindow w,XImage * xi,GClut * clut,Color trans,GRect * src,int x,int y)1621 static void gdraw_xbitmap(GXWindow w, XImage *xi, GClut *clut,
1622 Color trans, GRect *src, int x, int y) {
1623 GXDisplay *gdisp = w->display;
1624 Display *display = gdisp->display;
1625 GC gc = gdisp->gcstate[w->ggc->bitmap_col].gc;
1626 Color fg, bg;
1627
1628 if ( trans!=COLOR_UNKNOWN ) {
1629 XSetFunction(display,gc,GXand);
1630 if ( trans==1 ) {
1631 XSetForeground(display,gc, ~gdisp->cs.alpha_bits );
1632 XSetBackground(display,gc, 0 );
1633 } else {
1634 XSetForeground(display,gc, 0 );
1635 XSetBackground(display,gc, ~gdisp->cs.alpha_bits );
1636 }
1637 XPutImage(display,w->w,gc,xi,src->x,src->y,
1638 x,y, src->width, src->height );
1639 fg = trans==1?0:_GXDraw_GetScreenPixel(gdisp,clut!=NULL?clut->clut[1]:COLOR_CREATE(0xff,0xff,0xff));
1640 bg = trans==0?0:_GXDraw_GetScreenPixel(gdisp,clut!=NULL?clut->clut[0]:COLOR_CREATE(0,0,0));
1641 fg |= (gdisp)->cs.alpha_bits;
1642 bg |= (gdisp)->cs.alpha_bits;
1643 if ( /*bg!=fg || fg!=0*/ true ) {
1644 #ifdef _BrokenBitmapImages
1645 /* See the comment at _GXDraw_Image about why this works */
1646 XSetFunction(display,gc,GXxor);
1647 #else
1648 XSetFunction(display,gc,GXor);
1649 #endif
1650 XSetForeground(display,gc,fg);
1651 XSetBackground(display,gc,bg);
1652 }
1653 } else {
1654 XSetForeground(display,gc,
1655 _GXDraw_GetScreenPixel(gdisp,
1656 clut!=NULL?clut->clut[1]:COLOR_CREATE(0xff,0xff,0xff)) | (gdisp)->cs.alpha_bits);
1657 XSetBackground(display,gc,
1658 _GXDraw_GetScreenPixel(gdisp,
1659 clut!=NULL?clut->clut[0]:COLOR_CREATE(0,0,0)) | (gdisp)->cs.alpha_bits);
1660 }
1661 XPutImage(display,w->w,gc,xi,src->x,src->y,
1662 x,y, src->width, src->height );
1663 XSetFunction(display,gc,GXcopy);
1664 gdisp->gcstate[w->ggc->bitmap_col].fore_col = COLOR_UNKNOWN;
1665 }
1666
gdraw_bitmap(GXWindow w,struct _GImage * image,GClut * clut,Color trans,GRect * src,int x,int y)1667 static void gdraw_bitmap(GXWindow w, struct _GImage *image, GClut *clut,
1668 Color trans, GRect *src, int x, int y) {
1669 XImage *xi;
1670 GXDisplay *gdisp = w->display;
1671 uint8 *newdata = NULL;
1672
1673 xi = XCreateImage(gdisp->display,gdisp->visual,1,XYBitmap,0,(char *) (image->data),
1674 image->width, image->height,8,image->bytes_per_line);
1675 if ( xi->bitmap_bit_order==LSBFirst ) {
1676 /* sigh. The server doesn't use our convention. I might be able just */
1677 /* to change this field but it doesn't say, so best not to */
1678 int len = image->bytes_per_line*image->height;
1679 uint8 *pt, *ipt, *end;
1680 int m1,m2,val;
1681
1682 for ( ipt = image->data, pt=newdata=malloc(len), end=pt+len; pt<end; ++pt, ++ipt ) {
1683 val = 0;
1684 for ( m1=1, m2=0x80; m2!=0; m1<<=1, m2>>=1 )
1685 if ( *ipt&m1 ) val|=m2;
1686 *pt = val;
1687 }
1688 xi->data = (char *) newdata;
1689 }
1690 gdraw_xbitmap(w,xi,clut,trans,src,x,y);
1691 if ( (uint8 *) (xi->data)==image->data || (uint8 *) (xi->data)==newdata ) xi->data = NULL;
1692 XDestroyImage(xi);
1693 }
1694
check_image_buffers(GXDisplay * gdisp,int neww,int newh,int is_bitmap)1695 static void check_image_buffers(GXDisplay *gdisp, int neww, int newh, int is_bitmap) {
1696 int width = gdisp->gg.iwidth, height = gdisp->gg.iheight;
1697 char *temp;
1698 int depth = gdisp->depth, pixel_size;
1699 union { int32 foo; uint8 bar[4]; } endian;
1700
1701 if ( is_bitmap ) depth=1;
1702 if ( neww > gdisp->gg.iwidth ) {
1703 width = neww;
1704 if ( width<400 ) width = 400;
1705 }
1706 if ( width > gdisp->gg.iwidth || (gdisp->gg.img!=NULL && depth!=gdisp->gg.img->depth) ) {
1707 free(gdisp->gg.red_dith);
1708 free(gdisp->gg.green_dith);
1709 free(gdisp->gg.blue_dith);
1710 if ( depth<=8 ) {
1711 gdisp->gg.red_dith = malloc(width*sizeof(short));
1712 gdisp->gg.green_dith = malloc(width*sizeof(short));
1713 gdisp->gg.blue_dith = malloc(width*sizeof(short));
1714 if ( gdisp->gg.red_dith==NULL || gdisp->gg.green_dith==NULL || gdisp->gg.blue_dith==NULL )
1715 gdisp->do_dithering = 0;
1716 } else {
1717 gdisp->gg.red_dith = NULL;
1718 gdisp->gg.green_dith = NULL;
1719 gdisp->gg.blue_dith = NULL;
1720 }
1721 }
1722 if ( newh > gdisp->gg.iheight ) {
1723 height = newh;
1724 if ( height<400 ) height = 400;
1725 }
1726
1727 if ( gdisp->gg.iwidth == width && gdisp->gg.iheight == height && depth==gdisp->gg.img->depth )
1728 return;
1729
1730 if ( gdisp->gg.img!=NULL ) {
1731 /* If gdisp->gg.img->data was allocated by GC_malloc rather
1732 than standard libc malloc then it must be set to NULL so
1733 that XDestroyImage() does not try to free it and crash.
1734
1735 If we no longer use libgc then the following conditional
1736 block can be removed, but in case it isn't, the enclosed
1737 free() will prevent a memory leak.
1738 */
1739 if (gdisp->gg.img->data) {
1740 free(gdisp->gg.img->data);
1741 gdisp->gg.img->data = NULL;
1742 }
1743 XDestroyImage(gdisp->gg.img);
1744 }
1745 if ( gdisp->gg.mask!=NULL ) {
1746 /* If gdisp->gg.mask->data was allocated by GC_malloc rather
1747 than standard libc malloc then it must be set to NULL so
1748 that XDestroyImage() does not try to free it and crash.
1749
1750 If we no longer use libgc then the following conditional
1751 block can be removed, but in case it isn't, the enclosed
1752 free() will prevent a memory leak.
1753 */
1754 if (gdisp->gg.mask->data) {
1755 free(gdisp->gg.mask->data);
1756 gdisp->gg.mask->data = NULL;
1757 }
1758 XDestroyImage(gdisp->gg.mask);
1759 }
1760 pixel_size = gdisp->pixel_size;
1761 temp = malloc(((width*pixel_size+gdisp->bitmap_pad-1)/gdisp->bitmap_pad)*
1762 (gdisp->bitmap_pad/8)*height);
1763 if ( temp==NULL ) {
1764 GDrawIError("Can't create image draw area");
1765 exit(1);
1766 }
1767 gdisp->gg.img = XCreateImage(gdisp->display,gdisp->visual,depth,
1768 depth==1?XYBitmap:ZPixmap,0,
1769 temp,width,height,gdisp->bitmap_pad,0);
1770 if ( gdisp->gg.img==NULL ) {
1771 GDrawIError("Can't create image draw area");
1772 exit(1);
1773 }
1774 if ( !FAST_BITS==0 ) pixel_size=1;
1775 temp = malloc(((width*pixel_size+gdisp->bitmap_pad-1)/gdisp->bitmap_pad)*
1776 (gdisp->bitmap_pad/8)*height);
1777 gdisp->gg.mask = NULL;
1778 if ( temp!=NULL ) {
1779 gdisp->gg.mask = XCreateImage(gdisp->display,gdisp->visual,depth,
1780 depth==1?XYBitmap:ZPixmap,
1781 0,temp,width,height,gdisp->bitmap_pad,0);
1782 if ( gdisp->gg.mask==NULL )
1783 free(temp);
1784 }
1785 gdisp->gg.iwidth = width; gdisp->gg.iheight = height;
1786 endian.foo = 0xff;
1787 if ( (gdisp->gg.img->byte_order==MSBFirst) != ( endian.bar[3]==0xff ))
1788 gdisp->endian_mismatch = true;
1789 }
1790
gximage_to_ximage(GXWindow gw,GImage * image,GRect * src)1791 static void gximage_to_ximage(GXWindow gw, GImage *image, GRect *src) {
1792 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
1793 GXDisplay *gdisp = gw->display;
1794 int depth;
1795
1796 depth = gdisp->pixel_size;
1797 if ( depth!=8 && depth!=16 && depth!=24 && depth!=32 )
1798 depth = 1;
1799 else if ( gw->ggc->bitmap_col )
1800 depth = 1;
1801
1802 check_image_buffers(gdisp, src->width, src->height,depth==1);
1803 if ( base->trans!=COLOR_UNKNOWN || base->image_type == it_rgba ||
1804 gdisp->supports_alpha_images ) {
1805 if ( base->image_type == it_index ) {
1806 switch ( depth ) {
1807 case 1:
1808 default:
1809 /* all servers can handle bitmaps, so if we don't know how to*/
1810 /* write to a 13bit screen, we can at least give a bitmap */
1811 gdraw_8_on_1_nomag_dithered_masked(gdisp,image,src);
1812 break;
1813 case 8:
1814 if ( gdisp->do_dithering && !gdisp->cs.is_grey )
1815 gdraw_8_on_8_nomag_dithered_masked(gdisp,image,src);
1816 else
1817 gdraw_8_on_8_nomag_nodithered_masked(gdisp,image,src);
1818 break;
1819 case 16:
1820 gdraw_8_on_16_nomag_masked(gdisp,image,src);
1821 break;
1822 case 24:
1823 gdraw_8_on_24_nomag_masked(gdisp,image,src);
1824 break;
1825 case 32:
1826 if ( gdisp->supports_alpha_images )
1827 gdraw_8_on_32a_nomag(gdisp,image,src);
1828 else
1829 gdraw_8_on_32_nomag_masked(gdisp,image,src);
1830 break;
1831 }
1832 } else if ( base->image_type == it_true ) {
1833 switch ( depth ) {
1834 case 1:
1835 default:
1836 /* all servers can handle bitmaps, so if we don't know how to*/
1837 /* write to a 13bit screen, we can at least give a bitmap */
1838 gdraw_32_on_1_nomag_dithered_masked(gdisp,image,src);
1839 break;
1840 case 8:
1841 if ( gdisp->do_dithering && !gdisp->cs.is_grey )
1842 gdraw_32_on_8_nomag_dithered_masked(gdisp,image,src);
1843 else
1844 gdraw_32_on_8_nomag_nodithered_masked(gdisp,image,src);
1845 break;
1846 case 16:
1847 gdraw_32_on_16_nomag_masked(gdisp,image,src);
1848 break;
1849 case 24:
1850 gdraw_32_on_24_nomag_masked(gdisp,image,src);
1851 break;
1852 case 32:
1853 if ( gdisp->supports_alpha_images )
1854 gdraw_32_on_32a_nomag(gdisp,image,src);
1855 else
1856 gdraw_32_on_32_nomag_masked(gdisp,image,src);
1857 break;
1858 }
1859 } else if ( base->image_type == it_rgba ) {
1860 switch ( depth ) {
1861 case 1:
1862 default:
1863 /* all servers can handle bitmaps, so if we don't know how to*/
1864 /* write to a 13bit screen, we can at least give a bitmap */
1865 gdraw_32a_on_1_nomag_dithered(gdisp,image,src);
1866 break;
1867 case 8:
1868 if ( gdisp->do_dithering && !gdisp->cs.is_grey )
1869 gdraw_32a_on_8_nomag_dithered(gdisp,image,src);
1870 else
1871 gdraw_32a_on_8_nomag_nodithered(gdisp,image,src);
1872 break;
1873 case 16:
1874 gdraw_32a_on_16_nomag(gdisp,image,src);
1875 break;
1876 case 24:
1877 gdraw_32a_on_24_nomag(gdisp,image,src);
1878 break;
1879 case 32:
1880 if ( gdisp->supports_alpha_images )
1881 gdraw_32_on_32a_nomag(gdisp,image,src);
1882 else
1883 gdraw_32a_on_32_nomag(gdisp,image,src);
1884 break;
1885 }
1886 }
1887 } else { /* no mask */
1888 if ( base->image_type == it_index ) {
1889 switch ( depth ) {
1890 case 1:
1891 default:
1892 gdraw_8_on_1_nomag_dithered_nomask(gdisp,image,src);
1893 break;
1894 case 8:
1895 if ( gdisp->do_dithering && !gdisp->cs.is_grey )
1896 gdraw_8_on_8_nomag_dithered_nomask(gdisp,image,src);
1897 else
1898 gdraw_8_on_8_nomag_nodithered_nomask(gdisp,image,src);
1899 break;
1900 case 16:
1901 gdraw_8_on_16_nomag_nomask(gdisp,image,src);
1902 break;
1903 case 24:
1904 gdraw_8_on_24_nomag_nomask(gdisp,image,src);
1905 break;
1906 case 32:
1907 gdraw_8_on_32_nomag_nomask(gdisp,image,src);
1908 break;
1909 }
1910 } else if ( base->image_type == it_true ) {
1911 switch ( depth ) {
1912 case 1:
1913 default:
1914 gdraw_32_on_1_nomag_dithered_nomask(gdisp,image,src);
1915 break;
1916 case 8:
1917 if ( gdisp->do_dithering && !gdisp->cs.is_grey )
1918 gdraw_32_on_8_nomag_dithered_nomask(gdisp,image,src);
1919 else
1920 gdraw_32_on_8_nomag_nodithered_nomask(gdisp,image,src);
1921 break;
1922 case 16:
1923 gdraw_32_on_16_nomag_nomask(gdisp,image,src);
1924 break;
1925 case 24:
1926 gdraw_32_on_24_nomag_nomask(gdisp,image,src);
1927 break;
1928 case 32:
1929 gdraw_32_on_32_nomag_nomask(gdisp,image,src);
1930 break;
1931 }
1932 }
1933 }
1934 }
1935
_GXDraw_Image(GWindow _w,GImage * image,GRect * src,int32 x,int32 y)1936 void _GXDraw_Image( GWindow _w, GImage *image, GRect *src, int32 x, int32 y) {
1937 GXWindow gw = (GXWindow) _w;
1938 GXDisplay *gdisp = gw->display;
1939 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
1940 Display *display=gdisp->display;
1941 Window w = gw->w;
1942 GC gc = gdisp->gcstate[gw->ggc->bitmap_col].gc;
1943 GRect rootPos = {0, 0, XDisplayWidth(display,gdisp->screen),
1944 XDisplayHeight(display,gdisp->screen)};
1945 GRect img_pos = {x+_w->pos.x, y+_w->pos.y, src->width, src->height};
1946 GRect win_pos = {x, y, src->width, src->height};
1947 GRect blend_src = {0, 0, src->width, src->height};
1948 GImage *blended = NULL;
1949 int depth;
1950
1951 #ifndef _NO_LIBCAIRO
1952 if ( gw->usecairo ) {
1953 _GXCDraw_Image(gw,image,src,x,y);
1954 return;
1955 }
1956 #endif
1957
1958 _GXDraw_SetClipFunc(gdisp,gw->ggc);
1959 depth = gdisp->pixel_size;
1960 if ( depth!=8 && depth!=16 && depth!=24 && depth!=32 )
1961 depth = 1;
1962 else if ( gw->ggc->bitmap_col )
1963 depth = 1;
1964
1965 if ( base->image_type == it_mono ) {
1966 /* Mono images are easy, because all X servers (no matter what their */
1967 /* depth) support 1 bit bitmaps */
1968 gdraw_bitmap(gw,image->u.image,base->clut,base->trans,src,x,y);
1969 return;
1970 }
1971
1972 /* Throws errors in Mac OS X */
1973 #ifndef __Mac
1974 /* Can we blend this with background to support an alpha channel? */
1975 /* it's slow, particularly so on network connections, but that's */
1976 /* all we can get without reworking GDraw to use XComposite ext. */
1977 if ((depth >= 16) && (base->image_type == it_rgba)) {
1978 /* This requires caution, as the rectangle being worked */
1979 /* must be contained within both screen and the window. */
1980 intersect_rectangles(&img_pos, &(_w->pos));
1981 intersect_rectangles(&img_pos, &rootPos);
1982 img_pos.x -= _w->pos.x;
1983 img_pos.y -= _w->pos.y;
1984 win_pos = img_pos;
1985 blend_src = img_pos;
1986 blend_src.x = blend_src.y = 0;
1987 img_pos.x = src->x + (win_pos.x - x);
1988 img_pos.y = src->y + (win_pos.y - y);
1989 src = &img_pos;
1990 x = win_pos.x;
1991 y = win_pos.y;
1992
1993 if (src->width>0 && src->height>0)
1994 blended = _GXDraw_CopyScreenToImage(_w, &win_pos);
1995
1996 if (blended != NULL) {
1997 GImageBlendOver(blended, image, src, 0, 0);
1998 image = blended;
1999 base = image->list_len==0?image->u.image:image->u.images[0];
2000 src = &blend_src;
2001 }
2002 }
2003 #endif
2004
2005 gximage_to_ximage(gw, image, src);
2006
2007 if ( !gdisp->supports_alpha_images && (blended == NULL) &&
2008 (base->trans!=COLOR_UNKNOWN || base->image_type==it_rgba )) {
2009
2010 /* ((destination & mask) | src) seems to me to yield the proper behavior */
2011 /* for transparent backgrounds. This is equivalent to: */
2012 /* ((destination GXorReverse mask) GXnand src) */
2013 /* Oh... I think xor works too because the mask and the src will never*/
2014 /* both be 1 on the same pixel. If the mask is set then the image will*/
2015 /* be clear. So xor and or are equivalent (the case on which they differ never occurs) */
2016 XSetFunction(display,gc,GXand);
2017 #if FAST_BITS
2018 XSetForeground(display,gc, ~((-1)<<gdisp->pixel_size) );
2019 XSetBackground(display,gc, 0 );
2020 #endif
2021 XPutImage(display,w,gc,gdisp->gg.mask,0,0,
2022 x,y, src->width, src->height );
2023 #ifdef _BrokenBitmapImages
2024 XSetFunction(display,gc,GXxor);
2025 #else
2026 XSetFunction(display,gc,GXor);
2027 #endif
2028 XPutImage(display,w,gc,gdisp->gg.img,0,0,
2029 x,y, src->width, src->height );
2030 XSetFunction(display,gc,GXcopy);
2031 gdisp->gcstate[gw->ggc->bitmap_col].fore_col = COLOR_UNKNOWN;
2032 } else { /* no mask */
2033 XPutImage(display,w,gc,gdisp->gg.img,0,0,
2034 x,y, src->width, src->height );
2035 }
2036
2037 if (blended != NULL)
2038 GImageDestroy(blended);
2039 }
2040
2041 /* When drawing an anti-aliased glyph, I've been pretending that it's an image*/
2042 /* with colors running from foreground to background and with background be- */
2043 /* ing transparent. That works reasonably well -- on a blank background, but */
2044 /* when two glyphs overlap (as in a script font, for instance) we get a faint*/
2045 /* light halo around the edge of the second glyph. */
2046 /* What we really want to do is use the grey levels as an alpha channel with */
2047 /* the foreground color as the color. But alpha channels haven't been avail- */
2048 /* able on most X-displays. An alternative is to do the composing ourselves */
2049 /* in an image that's as big as the window, and then transfer that when done */
2050 /* That sounds slow. */
2051 /* What should the composing look like? I'm not entirely but it should be */
2052 /* somewhere between a "max" and a "clipped add" applied component by component*/
2053 /* of the color. X does not support either of those as primitives -- but X */
2054 /* does support bitwise boolean operators, and an "or" will always produce */
2055 /* a value somewhere between those extremes. */
2056 /* Actually since the color values (black==foreground, white==background) */
2057 /* generally run in the oposite direction from the alpha channel (100%=fore, */
2058 /* 0%=back) we will need to reverse the "or" to be an "and", but the idea */
2059 /* is the same */
_GXDraw_Glyph(GWindow _w,GImage * image,GRect * src,int32 x,int32 y)2060 void _GXDraw_Glyph( GWindow _w, GImage *image, GRect *src, int32 x, int32 y) {
2061 GXWindow gw = (GXWindow) _w;
2062 GXDisplay *gdisp = gw->display;
2063 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
2064 Color fg = -1;
2065
2066 #ifndef _NO_LIBCAIRO
2067 if ( gw->usecairo ) {
2068 _GXCDraw_Glyph(gw,image,src,x,y);
2069 return;
2070 }
2071 #endif
2072
2073 if ( base->image_type==it_index )
2074 fg = base->clut->clut[base->clut->clut_len-1];
2075
2076 if ( base->image_type!=it_index )
2077 _GXDraw_Image(_w,image,src,x,y);
2078 else if ( gdisp->visual->class != TrueColor ||
2079 gdisp->pixel_size<16 || gw->ggc->bitmap_col || fg!=0 )
2080 _GXDraw_Image(_w,image,src,x,y);
2081 else {
2082 Display *display=gdisp->display;
2083 Window w = gw->w;
2084 GC gc = gdisp->gcstate[gw->ggc->bitmap_col].gc;
2085
2086 _GXDraw_SetClipFunc(gdisp,gw->ggc);
2087
2088 check_image_buffers(gdisp, src->width, src->height,false);
2089 if ( gdisp->supports_alpha_images ) {
2090 gdraw_8a_on_32a_nomag( gdisp, image, src, fg );
2091 } else {
2092 gdraw_8_on_any_nomag_glyph(gdisp, image, src);
2093 XSetFunction(display,gc,GXand);
2094 }
2095 XPutImage(display,w,gc,gdisp->gg.img,0,0,
2096 x,y, src->width, src->height );
2097 XSetFunction(display,gc,GXcopy);
2098 }
2099 }
2100
2101 /* ******************************** Magnified ******************************* */
2102
_GImageExtract(struct _GImage * base,GRect * src,GRect * size,double xscale,double yscale)2103 GImage *_GImageExtract(struct _GImage *base,GRect *src,GRect *size,
2104 double xscale, double yscale) {
2105 static GImage temp;
2106 static struct _GImage tbase;
2107 static uint8 *data;
2108 static int dlen;
2109 int r,c;
2110
2111 memset(&temp,0,sizeof(temp));
2112 tbase = *base;
2113 temp.u.image = &tbase;
2114 tbase.width = size->width; tbase.height = size->height;
2115 if ( base->image_type==it_mono )
2116 tbase.bytes_per_line = (size->width+7)/8;
2117 else if ( base->image_type==it_index )
2118 tbase.bytes_per_line = size->width;
2119 else
2120 tbase.bytes_per_line = 4*size->width;
2121 if ( tbase.bytes_per_line*size->height>dlen )
2122 data = realloc(data,dlen = tbase.bytes_per_line*size->height );
2123 tbase.data = data;
2124
2125 /* I used to use rint(x). Now I use floor(x). For normal images rint */
2126 /* might be better, but for text we need floor */
2127
2128 if ( base->image_type==it_mono ) {
2129 memset(data,0,tbase.height*tbase.bytes_per_line);
2130 for ( r=0; r<size->height; ++r ) {
2131 int or = ((int) floor( (r+size->y)/yscale ));
2132 uint8 *pt = data+r*tbase.bytes_per_line;
2133 uint8 *opt = base->data+or*base->bytes_per_line;
2134 for ( c=0; c<size->width; ++c ) {
2135 int oc = ((int) floor( (c+size->x)/xscale));
2136 if ( opt[oc>>3] & (0x80>>(oc&7)) )
2137 pt[c>>3] |= (0x80>>(c&7));
2138 }
2139 }
2140 } else if ( base->image_type==it_index ) {
2141 for ( r=0; r<size->height; ++r ) {
2142 int or = ((int) floor( (r+size->y)/yscale ));
2143 uint8 *pt = data+r*tbase.bytes_per_line;
2144 uint8 *opt = base->data+or*base->bytes_per_line;
2145 for ( c=0; c<size->width; ++c ) {
2146 int oc = ((int) floor( (c+size->x)/xscale));
2147 *pt++ = opt[oc];
2148 }
2149 }
2150 } else {
2151 for ( r=0; r<size->height; ++r ) {
2152 int or = ((int) floor( (r+size->y)/yscale ));
2153 uint32 *pt = (uint32 *) (data+r*tbase.bytes_per_line);
2154 uint32 *opt = (uint32 *) (base->data+or*base->bytes_per_line);
2155 for ( c=0; c<size->width; ++c ) {
2156 int oc = ((int) floor( (c+size->x)/xscale));
2157 *pt++ = opt[oc];
2158 }
2159 }
2160 }
2161 return( &temp );
2162 }
2163
2164 /* Given an image, magnify it so that its width/height are as specified */
2165 /* then extract the given given rectangle (in magnified coords) and */
2166 /* place it on the screen at x,y */
_GXDraw_ImageMagnified(GWindow _w,GImage * image,GRect * magsrc,int32 x,int32 y,int32 width,int32 height)2167 void _GXDraw_ImageMagnified(GWindow _w, GImage *image, GRect *magsrc,
2168 int32 x, int32 y, int32 width, int32 height) {
2169 GXWindow gw = (GXWindow) _w;
2170 GXDisplay *gdisp = gw->display;
2171 struct _GImage *base = image->list_len==0?image->u.image:image->u.images[0];
2172 double xscale, yscale;
2173 GRect full, viewable;
2174 GImage *temp;
2175 GRect src;
2176
2177 #ifndef _NO_LIBCAIRO
2178 if ( gw->usecairo ) {
2179 _GXCDraw_ImageMagnified(gw,image,magsrc,x,y,width,height);
2180 return;
2181 }
2182 #endif
2183
2184 _GXDraw_SetClipFunc(gdisp,gw->ggc);
2185 viewable = gw->ggc->clip;
2186 if ( viewable.width > gw->pos.width-viewable.x )
2187 viewable.width = gw->pos.width-viewable.x;
2188 if ( viewable.height > gw->pos.height-viewable.y )
2189 viewable.height = gw->pos.height-viewable.y;
2190
2191 xscale = (base->width>=1) ? ((double) (width))/(base->width) : 1;
2192 yscale = (base->height>=1) ? ((double) (height))/(base->height) : 1;
2193 /* Intersect the clip rectangle with the scaled image to find the */
2194 /* portion of screen that we want to draw */
2195 if ( viewable.x<x ) {
2196 viewable.width -= (x-viewable.x);
2197 viewable.x = x;
2198 }
2199 if ( viewable.y<y ) {
2200 viewable.height -= (y-viewable.y);
2201 viewable.y = y;
2202 }
2203 if ( viewable.x+viewable.width > x+width ) viewable.width = x+width - viewable.x;
2204 if ( viewable.y+viewable.height > y+height ) viewable.height = y+height - viewable.y;
2205 if ( viewable.height<0 || viewable.width<0 )
2206 return;
2207
2208 /* Now find that same rectangle in the coordinates of the unscaled image */
2209 /* (translation & scale) */
2210 viewable.x -= x; viewable.y -= y;
2211 full.x = viewable.x/xscale; full.y = viewable.y/yscale;
2212 full.width = viewable.width/xscale; full.height = viewable.height/yscale;
2213 if ( full.x+full.width>base->width ) full.width = base->width-full.x; /* Rounding errors */
2214 if ( full.y+full.height>base->height ) full.height = base->height-full.y; /* Rounding errors */
2215 /* Rounding errors */
2216
2217 temp = _GImageExtract(base,&full,&viewable,xscale,yscale);
2218 src.x = src.y = 0; src.width = viewable.width; src.height = viewable.height;
2219 _GXDraw_Image( _w, temp, &src, x+viewable.x, y+viewable.y);
2220 }
2221
xi1_to_gi1(GXDisplay * gdisp,XImage * xi)2222 static GImage *xi1_to_gi1(GXDisplay *gdisp,XImage *xi) {
2223 GImage *gi;
2224 struct _GImage *base;
2225
2226 gi = calloc(1,sizeof(GImage));
2227 if ( gi==NULL )
2228 return( NULL );
2229 base = malloc(sizeof(struct _GImage));
2230 if ( base==NULL ) {
2231 free(gi);
2232 return( NULL );
2233 }
2234 gi->u.image = base;
2235 base->image_type = it_mono;
2236 base->width = xi->width;
2237 base->height = xi->height;
2238 base->bytes_per_line = xi->bytes_per_line;
2239 base->data = (uint8 *) (xi->data);
2240 base->clut = NULL;
2241 base->trans = COLOR_UNKNOWN;
2242
2243 if ( xi->bitmap_bit_order==LSBFirst ) {
2244 /* sigh. The server doesn't use our convention. invert all bytes */
2245 int len = base->height*base->bytes_per_line;
2246 uint8 *newdata = malloc(len), *pt, *ipt, *end;
2247 int m1,m2,val;
2248
2249 for ( ipt = (uint8 *) xi->data, pt=newdata, end=pt+len; pt<end; ++pt, ++ipt ) {
2250 val = 0;
2251 for ( m1=1, m2=0x80; m2!=0; m1<<=1, m2>>=1 )
2252 if ( *ipt&m1 ) val|=m2;
2253 *pt = val;
2254 }
2255 base->data = newdata;
2256 } else
2257 xi->data = NULL;
2258 return( gi );
2259 }
2260
xi8_to_gi8(GXDisplay * gdisp,XImage * xi)2261 static GImage *xi8_to_gi8(GXDisplay *gdisp,XImage *xi) {
2262 GImage *gi;
2263 struct _GImage *base;
2264 GClut *clut;
2265 int i;
2266 XColor cols[256];
2267
2268 gi = calloc(1,sizeof(GImage));
2269 if ( gi==NULL )
2270 return( NULL );
2271 base = malloc(sizeof(struct _GImage));
2272 if ( base ==NULL ) {
2273 free(gi);
2274 return( NULL );
2275 }
2276 clut = malloc(sizeof(GClut));
2277 if ( clut ==NULL ) {
2278 free(base);
2279 free(gi);
2280 return( NULL );
2281 }
2282 gi->u.image = base;
2283 base->image_type = it_index;
2284 base->width = xi->width;
2285 base->height = xi->height;
2286 base->bytes_per_line = xi->bytes_per_line;
2287 base->data = (uint8 *) xi->data;
2288 base->clut = clut;
2289 base->trans = COLOR_UNKNOWN;
2290
2291 clut->clut_len = 256;
2292 for ( i=0; i<(1<<gdisp->pixel_size); ++i )
2293 cols[i].pixel = i;
2294 XQueryColors(gdisp->display,gdisp->cmap,cols,1<<gdisp->pixel_size);
2295 for ( i=0; i<(1<<gdisp->pixel_size); ++i )
2296 clut->clut[i] = COLOR_CREATE(cols[i].red>>8, cols[i].green>>8, cols[i].blue>>8);
2297 clut->is_grey = ( gdisp->visual->class==StaticGray || gdisp->visual->class==GrayScale );
2298 return( gi );
2299 }
2300
xi16_to_gi32(GXDisplay * gdisp,XImage * xi)2301 static GImage *xi16_to_gi32(GXDisplay *gdisp,XImage *xi) {
2302 GImage *gi;
2303 struct _GImage *base;
2304 uint16 *pt; uint32 *ipt, val;
2305 int i,j,rs,gs,bs;
2306 int rs2,gs2=0,bs2;
2307 int rm, gm, bm;
2308
2309 if (( gi = GImageCreate(it_true,xi->width,xi->height))==NULL )
2310 return( NULL );
2311 base = gi->u.image;
2312
2313 rs = gdisp->cs.red_shift; gs = gdisp->cs.green_shift; bs = gdisp->cs.blue_shift;
2314 rm = gdisp->visual->red_mask; gm = gdisp->visual->green_mask; bm = gdisp->visual->blue_mask;
2315 if ( rs>gs && rs>bs ) {
2316 rs2 = 8-(16-rs);
2317 if ( gs>bs ) {
2318 bs2 = 8-gs2;
2319 gs2 = 8-(rs-gs);
2320 } else {
2321 gs2 = 8-bs;
2322 bs2 = 8-(rs-bs);
2323 }
2324 } else if ( gs>rs && gs>bs ) {
2325 gs2 = 8-(16-gs);
2326 if ( rs>bs ) {
2327 bs2 = 8-rs;
2328 rs2 = 8-(gs-rs);
2329 } else {
2330 rs2 = 8-bs;
2331 bs2 = 8-(gs-bs);
2332 }
2333 } else {
2334 bs2 = 8-(16-bs);
2335 if ( rs>gs ) {
2336 gs2 = 8-rs;
2337 rs2 = 8-(bs-rs);
2338 } else {
2339 rs2 = 8-gs;
2340 gs2 = 8-(bs-gs);
2341 }
2342 }
2343
2344 for ( i=0; i<base->height; ++i ) {
2345 pt = (uint16 *) (xi->data + i*xi->bytes_per_line);
2346 ipt = (uint32 *) (base->data + i*base->bytes_per_line);
2347 for ( j=0; j<base->width; ++j ) {
2348 val = *pt++;
2349 if ( val!=0 )
2350 val = pt[-1];
2351 *ipt++ = COLOR_CREATE(((val&rm)>>rs)<<rs2,((val&gm)>>gs)<<gs2,((val&bm)>>bs)<<bs2);
2352 }
2353 }
2354 return( gi );
2355 }
2356
xi24_to_gi32(GXDisplay * gdisp,XImage * xi)2357 static GImage *xi24_to_gi32(GXDisplay *gdisp,XImage *xi) {
2358 GImage *gi;
2359 struct _GImage *base;
2360 uint8 *pt; uint32 *ipt, val;
2361 int i,j,rs,gs,bs;
2362
2363 if (( gi = GImageCreate(it_true,xi->width,xi->height))==NULL )
2364 return( NULL );
2365 base = gi->u.image;
2366
2367 rs = gdisp->cs.red_shift; gs = gdisp->cs.green_shift; bs = gdisp->cs.blue_shift;
2368 for ( i=0; i<base->height; ++i ) {
2369 pt = (uint8 *) xi->data + i*xi->bytes_per_line;
2370 ipt = (uint32 *) (base->data + i*base->bytes_per_line);
2371 for ( j=0; j<base->width; ++j ) {
2372 if ( xi->byte_order==MSBFirst ) {
2373 val = *pt++;
2374 val = (val<<8) + *pt++;
2375 val = (val<<8) + *pt++;
2376 } else {
2377 val = *pt++;
2378 val |= (*pt++<<8);
2379 val |= (*pt++<<16);
2380 }
2381 *ipt++ = COLOR_CREATE((val>>rs)&0xff,(val>>gs)&0xff,(val>>bs)&0xff);
2382 }
2383 }
2384 return( gi );
2385 }
2386
xi32_to_gi32(GXDisplay * gdisp,XImage * xi)2387 static GImage *xi32_to_gi32(GXDisplay *gdisp,XImage *xi) {
2388 GImage *gi;
2389 struct _GImage *base;
2390 uint32 *pt; uint32 *ipt, val;
2391 int i,j,rs,gs,bs;
2392
2393 if (( gi = GImageCreate(it_true,xi->width,xi->height))==NULL )
2394 return( NULL );
2395 base = gi->u.image;
2396
2397 rs = gdisp->cs.red_shift; gs = gdisp->cs.green_shift; bs = gdisp->cs.blue_shift;
2398 for ( i=0; i<base->height; ++i ) {
2399 pt = (uint32 *) (xi->data + i*xi->bytes_per_line);
2400 ipt = (uint32 *) (base->data + i*base->bytes_per_line);
2401 for ( j=0; j<base->width; ++j ) {
2402 val = *pt++;
2403 *ipt++ = COLOR_CREATE((val>>rs)&0xff,(val>>gs)&0xff,(val>>bs)&0xff);
2404 }
2405 }
2406 return( gi );
2407 }
2408
_GXDraw_CopyScreenToImage(GWindow _w,GRect * rect)2409 GImage *_GXDraw_CopyScreenToImage(GWindow _w, GRect *rect) {
2410 GXWindow gw = (GXWindow) _w;
2411 GXDisplay *gdisp = gw->display;
2412 Display *display=gdisp->display;
2413 Window w = gw->w;
2414 int depth;
2415 XImage *xi;
2416 GImage *gi=NULL;
2417
2418 depth = gdisp->pixel_size;
2419 if ( gw->ggc->bitmap_col ) depth = 1;
2420
2421 if ( depth!=1 && depth!=8 && depth!=16 && depth!=24 && depth!=32 )
2422 return( NULL );
2423 xi = XGetImage(display,w,rect->x,rect->y, rect->width, rect->height,
2424 -1,ZPixmap);
2425 if ( xi==NULL )
2426 return( NULL );
2427 switch ( xi->bits_per_pixel ) {
2428 case 1:
2429 gi = xi1_to_gi1(gdisp,xi);
2430 break;
2431 case 8:
2432 gi = xi8_to_gi8(gdisp,xi);
2433 break;
2434 case 16:
2435 gi = xi16_to_gi32(gdisp,xi);
2436 break;
2437 case 24:
2438 gi = xi24_to_gi32(gdisp,xi);
2439 break;
2440 case 32:
2441 gi = xi32_to_gi32(gdisp,xi);
2442 break;
2443 }
2444 XDestroyImage(xi);
2445 return( gi );
2446 }
2447 #else /* NO X */
2448 int gimagexdraw_a_file_must_define_something=3;
2449
2450 #endif
2451