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