LCOV - code coverage report
Current view: top level - gdraw - gimagexdraw.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 0 1312 0.0 %
Date: 2017-08-04 Functions: 0 50 0.0 %

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

Generated by: LCOV version 1.10