home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / x / x11r6-ch / xpm-3.4 / xpm-3 / xpm-3.4c / lib / create.c < prev    next >
C/C++ Source or Header  |  1994-06-06  |  41KB  |  1,520 lines

  1. /*
  2.  * Copyright (C) 1989-94 GROUPE BULL
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a copy
  5.  * of this software and associated documentation files (the "Software"), to
  6.  * deal in the Software without restriction, including without limitation the
  7.  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8.  * sell copies of the Software, and to permit persons to whom the Software is
  9.  * furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice shall be included in
  12.  * all copies or substantial portions of the Software.
  13.  *
  14.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17.  * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  18.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  19.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20.  *
  21.  * Except as contained in this notice, the name of GROUPE BULL shall not be
  22.  * used in advertising or otherwise to promote the sale, use or other dealings
  23.  * in this Software without prior written authorization from GROUPE BULL.
  24.  */
  25.  
  26. /*****************************************************************************\
  27. * create.c:                                                                   *
  28. *                                                                             *
  29. *  XPM library                                                                *
  30. *  Create an X image and possibly its related shape mask                      *
  31. *  from the given xpmInternAttrib.                                            *
  32. *                                                                             *
  33. *  Developed by Arnaud Le Hors                                                *
  34. \*****************************************************************************/
  35.  
  36. /*
  37.  * The code related to FOR_MSW has been added by
  38.  * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
  39.  */
  40.  
  41. #include "xpmP.h"
  42. #ifdef VMS
  43. #include "sys$library:ctype.h"
  44. #else
  45. #include <ctype.h>
  46. #endif
  47.  
  48. LFUNC(xpmVisualType, int, (Visual *visual));
  49.  
  50. #ifndef FOR_MSW
  51. LFUNC(SetCloseColor, int, (Display *display, Colormap colormap,
  52.                Visual *visual, XColor *col,
  53.                Pixel *image_pixel, Pixel *mask_pixel,
  54.                Pixel **pixels, unsigned int *npixels,
  55.                XpmAttributes *attributes,
  56.                XColor *cols, int ncols));
  57. #else
  58. /* let the window system take care of close colors */
  59. #endif
  60.  
  61. LFUNC(SetColor, int, (Display *display, Colormap colormap, Visual *visual,
  62.               char *colorname, unsigned int color_index,
  63.               Pixel *image_pixel, Pixel *mask_pixel,
  64.               unsigned int *mask_pixel_index, Pixel **pixels,
  65.               unsigned int *npixels, XpmAttributes *attributes,
  66.               XColor *cols, int ncols));
  67.  
  68. LFUNC(CreateXImage, int, (Display *display, Visual *visual,
  69.               unsigned int depth, unsigned int width,
  70.               unsigned int height, XImage **image_return));
  71.  
  72. LFUNC(CreateColors, int, (Display *display, XpmAttributes *attributes,
  73.               XpmColor *ct, unsigned int ncolors, Pixel *ip,
  74.               Pixel *mp, unsigned int *mask_pixel,
  75.               Pixel **pixels, unsigned int *npixels));
  76.  
  77. #ifndef FOR_MSW
  78. /* XImage pixel routines */
  79. LFUNC(SetImagePixels, void, (XImage *image, unsigned int width,
  80.                  unsigned int height, unsigned int *pixelindex,
  81.                  Pixel *pixels));
  82.  
  83. LFUNC(SetImagePixels32, void, (XImage *image, unsigned int width,
  84.                    unsigned int height, unsigned int *pixelindex,
  85.                    Pixel *pixels));
  86.  
  87. LFUNC(SetImagePixels16, void, (XImage *image, unsigned int width,
  88.                    unsigned int height, unsigned int *pixelindex,
  89.                    Pixel *pixels));
  90.  
  91. LFUNC(SetImagePixels8, void, (XImage *image, unsigned int width,
  92.                   unsigned int height, unsigned int *pixelindex,
  93.                   Pixel *pixels));
  94.  
  95. LFUNC(SetImagePixels1, void, (XImage *image, unsigned int width,
  96.                   unsigned int height, unsigned int *pixelindex,
  97.                   Pixel *pixels));
  98. #else  /* ndef FOR_MSW */
  99. /* FOR_MSW pixel routine */
  100. LFUNC(MSWSetImagePixels, void, (Display *dc, XImage *image,
  101.                 unsigned int width, unsigned int height,
  102.                 unsigned int *pixelindex, Pixel *pixels));
  103. #endif /* ndef FOR_MSW */
  104.  
  105. #ifdef NEED_STRCASECMP
  106. FUNC(strcasecmp, int, (char *s1, char *s2));
  107.  
  108. /*
  109.  * in case strcasecmp is not provided by the system here is one
  110.  * which does the trick
  111.  */
  112. int
  113. strcasecmp(s1, s2)
  114.     register char *s1, *s2;
  115. {
  116.     register int c1, c2;
  117.  
  118.     while (*s1 && *s2) {
  119.     c1 = tolower(*s1);
  120.     c2 = tolower(*s2);
  121.     if (c1 != c2)
  122.         return (c1 - c2);
  123.     s1++;
  124.     s2++;
  125.     }
  126.     return (int) (*s1 - *s2);
  127. }
  128.  
  129. #endif
  130.  
  131. /*
  132.  * return the default color key related to the given visual
  133.  */
  134. static int
  135. xpmVisualType(visual)
  136.     Visual *visual;
  137. {
  138. #ifndef FOR_MSW
  139.     switch (visual->class) {
  140.     case StaticGray:
  141.     case GrayScale:
  142.     switch (visual->map_entries) {
  143.     case 2:
  144.         return (XPM_MONO);
  145.     case 4:
  146.         return (XPM_GRAY4);
  147.     default:
  148.         return (XPM_GRAY);
  149.     }
  150.     default:
  151.     return (XPM_COLOR);
  152.     }
  153. #else
  154.     /* there should be a similar switch for MSW */
  155.     return (XPM_COLOR);
  156. #endif
  157. }
  158.  
  159.  
  160. typedef struct {
  161.     int cols_index;
  162.     long closeness;
  163. }      CloseColor;
  164.  
  165. static int
  166. closeness_cmp(a, b)
  167.     void *a, *b;
  168. {
  169.     CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b;
  170.  
  171.     /* cast to int as qsort requires */
  172.     return (int) (x->closeness - y->closeness);
  173. }
  174.  
  175. #ifndef FOR_MSW
  176. /*
  177.  * set a close color in case the exact one can't be set
  178.  * return 0 if success, 1 otherwise.
  179.  */
  180.  
  181. static int
  182. SetCloseColor(display, colormap, visual, col,
  183.           image_pixel, mask_pixel, pixels, npixels, attributes,
  184.           cols, ncols)
  185.     Display *display;
  186.     Colormap colormap;
  187.     Visual *visual;
  188.     XColor *col;
  189.     Pixel *image_pixel, *mask_pixel;
  190.     Pixel **pixels;
  191.     unsigned int *npixels;
  192.     XpmAttributes *attributes;
  193.     XColor *cols;
  194.     int ncols;
  195. {
  196.  
  197.     /*
  198.      * Allocation failed, so try close colors. To get here the visual must
  199.      * be GreyScale, PseudoColor or DirectColor (or perhaps StaticColor?
  200.      * What about sharing systems like QDSS?). Beware: we have to treat
  201.      * DirectColor differently.
  202.      */
  203.  
  204.  
  205.     long int red_closeness, green_closeness, blue_closeness;
  206.     int n;
  207.  
  208.     if (attributes && (attributes->valuemask & XpmCloseness))
  209.     red_closeness = green_closeness = blue_closeness =
  210.         attributes->closeness;
  211.     else {
  212.     red_closeness = attributes->red_closeness;
  213.     green_closeness = attributes->green_closeness;
  214.     blue_closeness = attributes->blue_closeness;
  215.     }
  216.  
  217.  
  218.     /*
  219.      * We sort the colormap by closeness and try to allocate the color
  220.      * closest to the target. If the allocation of this close color fails,
  221.      * which almost never happens, then one of two scenarios is possible.
  222.      * Either the colormap must have changed (since the last close color
  223.      * allocation or possibly while we were sorting the colormap), or the
  224.      * color is allocated as Read/Write by some other client. (Note: X
  225.      * _should_ allow clients to check if a particular color is Read/Write,
  226.      * but it doesn't! :-( ). We cannot determine which of these scenarios
  227.      * occurred, so we try the next closest color, and so on, until no more
  228.      * colors are within closeness of the target. If we knew that the
  229.      * colormap had changed, we could skip this sequence.
  230.      * 
  231.      * If _none_ of the colors within closeness of the target can be allocated,
  232.      * then we can finally be pretty sure that the colormap has actually
  233.      * changed. In this case we try to allocate the original color (again),
  234.      * then try the closecolor stuff (again)...
  235.      * 
  236.      * In theory it would be possible for an infinite loop to occur if another
  237.      * process kept changing the colormap every time we sorted it, so we set
  238.      * a maximum on the number of iterations. After this many tries, we use
  239.      * XGrabServer() to ensure that the colormap remains unchanged.
  240.      * 
  241.      * This approach gives particularly bad worst case performance - as many as
  242.      * <MaximumIterations> colormap reads and sorts may be needed, and as
  243.      * many as <MaximumIterations> * <ColormapSize> attempted allocations
  244.      * may fail. On an 8-bit system, this means as many as 3 colormap reads,
  245.      * 3 sorts and 768 failed allocations per execution of this code!
  246.      * Luckily, my experiments show that in general use in a typical 8-bit
  247.      * color environment only about 1 in every 10000 allocations fails to
  248.      * succeed in the fastest possible time. So virtually every time what
  249.      * actually happens is a single sort followed by a successful allocate.
  250.      * The very first allocation also costs a colormap read, but no further
  251.      * reads are usually necessary.
  252.      */
  253.  
  254. #define ITERATIONS 2            /* more than one is almost never
  255.                      * necessary */
  256.  
  257.     for (n = 0; n <= ITERATIONS; ++n) {
  258.     CloseColor *closenesses =
  259.         (CloseColor *) XpmCalloc(ncols, sizeof(CloseColor));
  260.     int i, c;
  261.  
  262.     for (i = 0; i < ncols; ++i) {    /* build & sort closenesses table */
  263. #define COLOR_FACTOR       3
  264. #define BRIGHTNESS_FACTOR  1
  265.  
  266.         closenesses[i].cols_index = i;
  267.         closenesses[i].closeness =
  268.         COLOR_FACTOR * (abs((long) col->red - (long) cols[i].red)
  269.                 + abs((long) col->green - (long) cols[i].green)
  270.                 + abs((long) col->blue - (long) cols[i].blue))
  271.         + BRIGHTNESS_FACTOR * abs(((long) col->red +
  272.                        (long) col->green +
  273.                        (long) col->blue)
  274.                        - ((long) cols[i].red +
  275.                           (long) cols[i].green +
  276.                           (long) cols[i].blue));
  277.     }
  278.     qsort(closenesses, ncols, sizeof(CloseColor), closeness_cmp);
  279.  
  280.     i = 0;
  281.     c = closenesses[i].cols_index;
  282.     while ((long) cols[c].red >= (long) col->red - red_closeness &&
  283.            (long) cols[c].red <= (long) col->red + red_closeness &&
  284.            (long) cols[c].green >= (long) col->green - green_closeness &&
  285.            (long) cols[c].green <= (long) col->green + green_closeness &&
  286.            (long) cols[c].blue >= (long) col->blue - blue_closeness &&
  287.            (long) cols[c].blue <= (long) col->blue + blue_closeness) {
  288.         if (XAllocColor(display, colormap, &cols[c])) {
  289.         if (n == ITERATIONS)
  290.             XUngrabServer(display);
  291.         XpmFree(closenesses);
  292.         *image_pixel = cols[c].pixel;
  293.         *mask_pixel = 1;
  294.         (*pixels)[*npixels] = cols[c].pixel;
  295.         (*npixels)++;
  296.         return (0);
  297.         } else {
  298.         ++i;
  299.         if (i == ncols)
  300.             break;
  301.         c = closenesses[i].cols_index;
  302.         }
  303.     }
  304.  
  305.     /* Couldn't allocate _any_ of the close colors! */
  306.  
  307.     if (n == ITERATIONS)
  308.         XUngrabServer(display);
  309.     XpmFree(closenesses);
  310.  
  311.     if (i == 0 || i == ncols)    /* no color close enough or cannot */
  312.         return (1);            /* alloc any color (full of r/w's) */
  313.  
  314.     if (XAllocColor(display, colormap, col)) {
  315.         *image_pixel = col->pixel;
  316.         *mask_pixel = 1;
  317.         (*pixels)[*npixels] = col->pixel;
  318.         (*npixels)++;
  319.         return (0);
  320.     } else {            /* colormap has probably changed, so
  321.                      * re-read... */
  322.         if (n == ITERATIONS - 1)
  323.         XGrabServer(display);
  324.  
  325. #if 0
  326.         if (visual->class == DirectColor) {
  327.         /* TODO */
  328.         } else
  329. #endif
  330.         XQueryColors(display, colormap, cols, ncols);
  331.     }
  332.     }
  333.     return (1);
  334. }
  335.  
  336. #define USE_CLOSECOLOR attributes && \
  337. (((attributes->valuemask & XpmCloseness) && attributes->closeness != 0) \
  338.  || ((attributes->valuemask & XpmRGBCloseness) && \
  339.      attributes->red_closeness != 0 \
  340.      && attributes->green_closeness != 0 \
  341.      && attributes->blue_closeness != 0))
  342.  
  343. #else
  344.     /* FOR_MSW part */
  345.     /* nothing to do here, the window system does it */
  346. #endif
  347.  
  348. /*
  349.  * set the color pixel related to the given colorname,
  350.  * return 0 if success, 1 otherwise.
  351.  */
  352.  
  353. static int
  354. SetColor(display, colormap, visual, colorname, color_index,
  355.      image_pixel, mask_pixel, mask_pixel_index,
  356.      pixels, npixels, attributes, cols, ncols)
  357.     Display *display;
  358.     Colormap colormap;
  359.     Visual *visual;
  360.     char *colorname;
  361.     unsigned int color_index;
  362.     Pixel *image_pixel, *mask_pixel;
  363.     unsigned int *mask_pixel_index;
  364.     Pixel **pixels;
  365.     unsigned int *npixels;
  366.     XpmAttributes *attributes;
  367.     XColor *cols;
  368.     int ncols;
  369. {
  370.     XColor xcolor;
  371.  
  372.     if (strcasecmp(colorname, TRANSPARENT_COLOR)) {
  373.     if (!XParseColor(display, colormap, colorname, &xcolor))
  374.         return (1);
  375.     if (!XAllocColor(display, colormap, &xcolor)) {
  376. #ifndef FOR_MSW
  377.         if (USE_CLOSECOLOR)
  378.         return (SetCloseColor(display, colormap, visual, &xcolor,
  379.                       image_pixel, mask_pixel, pixels, npixels,
  380.                       attributes, cols, ncols));
  381.         else
  382. #endif /* ndef FOR_MSW */
  383.         return (1);
  384.     }
  385.     *image_pixel = xcolor.pixel;
  386.     *mask_pixel = 1;
  387.     (*pixels)[*npixels] = xcolor.pixel;
  388.     (*npixels)++;
  389.     } else {
  390.     *image_pixel = 0;
  391.     *mask_pixel = 0;
  392.     *mask_pixel_index = color_index; /* store the color table index */
  393.     }
  394.     return (0);
  395. }
  396.  
  397.  
  398. static int
  399. CreateColors(display, attributes, ct, ncolors,
  400.          ip, mp, mask_pixel, pixels, npixels)
  401.     Display *display;
  402.     XpmAttributes *attributes;
  403.     XpmColor *ct;
  404.     unsigned int ncolors;
  405.     Pixel *ip;
  406.     Pixel *mp;
  407.     unsigned int *mask_pixel;        /* mask pixel index */
  408.     Pixel **pixels;            /* allocated pixels */
  409.     unsigned int *npixels;        /* number of allocated pixels */
  410. {
  411.     /* variables stored in the XpmAttributes structure */
  412.     Visual *visual;
  413.     Colormap colormap;
  414.     XpmColorSymbol *colorsymbols;
  415.     unsigned int numsymbols;
  416.  
  417.     char *colorname;
  418.     unsigned int a, b, l;
  419.     Bool pixel_defined;
  420.     unsigned int key;
  421.     XpmColorSymbol *symbol;
  422.     char **defaults;
  423.     int ErrorStatus = XpmSuccess;
  424.     char *s;
  425.     int default_index;
  426.  
  427.     XColor *cols = NULL;
  428.     unsigned int ncols = 0;
  429.  
  430.     /*
  431.      * retrieve information from the XpmAttributes
  432.      */
  433.     if (attributes && attributes->valuemask & XpmColorSymbols) {
  434.     colorsymbols = attributes->colorsymbols;
  435.     numsymbols = attributes->numsymbols;
  436.     } else
  437.     numsymbols = 0;
  438.  
  439.     if (attributes && attributes->valuemask & XpmVisual)
  440.     visual = attributes->visual;
  441.     else
  442.     visual = XDefaultVisual(display, XDefaultScreen(display));
  443.  
  444.     if (attributes && attributes->valuemask & XpmColormap)
  445.     colormap = attributes->colormap;
  446.     else
  447.     colormap = XDefaultColormap(display, XDefaultScreen(display));
  448.  
  449.     if (attributes && attributes->valuemask & XpmColorKey)
  450.     key = attributes->color_key;
  451.     else
  452.     key = xpmVisualType(visual);
  453.  
  454. #ifndef FOR_MSW
  455.     if (USE_CLOSECOLOR) {
  456.     /* originally from SetCloseColor */
  457. #if 0
  458.     if (visual->class == DirectColor) {
  459.  
  460.         /*
  461.          * TODO: Implement close colors for DirectColor visuals. This is
  462.          * difficult situation. Chances are that we will never get here,
  463.          * because any machine that supports DirectColor will probably
  464.          * also support TrueColor (and probably PseudoColor). Also,
  465.          * DirectColor colormaps can be very large, so looking for close
  466.          * colors may be too slow.
  467.          */
  468.     } else {
  469. #endif
  470.         int i;
  471.  
  472.         ncols = visual->map_entries;
  473.         cols = (XColor *) XpmCalloc(ncols, sizeof(XColor));
  474.         for (i = 0; i < ncols; ++i)
  475.         cols[i].pixel = i;
  476.         XQueryColors(display, colormap, cols, ncols);
  477. #if 0
  478.     }
  479. #endif
  480.     }
  481. #endif /* ndef FOR_MSW */
  482.  
  483.     switch (key) {
  484.     case XPM_MONO:
  485.     default_index = 2;
  486.     break;
  487.     case XPM_GRAY4:
  488.     default_index = 3;
  489.     break;
  490.     case XPM_GRAY:
  491.     default_index = 4;
  492.     break;
  493.     case XPM_COLOR:
  494.     default:
  495.     default_index = 5;
  496.     break;
  497.     }
  498.  
  499.     for (a = 0; a < ncolors; a++, ct++, ip++, mp++) {
  500.     colorname = NULL;
  501.     pixel_defined = False;
  502.     defaults = (char **) ct;
  503.  
  504.     /*
  505.      * look for a defined symbol
  506.      */
  507.     if (numsymbols) {
  508.         s = defaults[1];
  509.         for (l = 0, symbol = colorsymbols; l < numsymbols; l++, symbol++) {
  510.         if (symbol->name && s && !strcmp(symbol->name, s))
  511.             /* override name */
  512.             break;
  513.         if (!symbol->name && symbol->value) {    /* override value */
  514.             int def_index = default_index;
  515.  
  516.             while (defaults[def_index] == NULL)    /* find defined
  517.                              * colorname */
  518.             --def_index;
  519.             if (def_index < 2) {/* nothing towards mono, so try
  520.                      * towards color */
  521.             def_index = default_index + 1;
  522.             while (def_index <= 5 && defaults[def_index] == NULL)
  523.                 ++def_index;
  524.             }
  525.             if (def_index >= 2 && defaults[def_index] != NULL &&
  526.             !strcasecmp(symbol->value, defaults[def_index]))
  527.             break;
  528.         }
  529.         }
  530.         if (l != numsymbols) {
  531.         if (symbol->name && symbol->value)
  532.             colorname = symbol->value;
  533.         else
  534.             pixel_defined = True;
  535.         }
  536.     }
  537.     if (!pixel_defined) {        /* pixel not given as symbol value */
  538.         if (colorname) {        /* colorname given as symbol value */
  539.         if (!SetColor(display, colormap, visual, colorname, a, ip, mp,
  540.                   mask_pixel, pixels, npixels, attributes,
  541.                   cols, ncols))
  542.             pixel_defined = True;
  543.         else
  544.             ErrorStatus = XpmColorError;
  545.         }
  546.         b = key;
  547.         while (!pixel_defined && b > 1) {
  548.         if (defaults[b]) {
  549.             if (!SetColor(display, colormap, visual, defaults[b],
  550.                   a, ip, mp, mask_pixel, pixels, npixels,
  551.                   attributes, cols, ncols)) {
  552.             pixel_defined = True;
  553.             break;
  554.             } else
  555.             ErrorStatus = XpmColorError;
  556.         }
  557.         b--;
  558.         }
  559.         b = key + 1;
  560.         while (!pixel_defined && b < NKEYS + 1) {
  561.         if (defaults[b]) {
  562.             if (!SetColor(display, colormap, visual, defaults[b],
  563.                   a, ip, mp, mask_pixel, pixels, npixels,
  564.                   attributes, cols, ncols)) {
  565.             pixel_defined = True;
  566.             break;
  567.             } else
  568.             ErrorStatus = XpmColorError;
  569.         }
  570.         b++;
  571.         }
  572.         if (!pixel_defined) {
  573.         if (cols)
  574.             XpmFree(cols);
  575.         return (XpmColorFailed);
  576.         }
  577.     } else {
  578.         *ip = colorsymbols[l].pixel;
  579.         if (symbol->value
  580.         && !strcasecmp(symbol->value, TRANSPARENT_COLOR)) {
  581.         *mp = 0;
  582.         *mask_pixel = 0;
  583.         } else
  584.         *mp = 1;
  585.     }
  586.     }
  587.     if (cols)
  588.     XpmFree(cols);
  589.     return (ErrorStatus);
  590. }
  591.  
  592.  
  593. /* function call in case of error, frees only locally allocated variables */
  594. #undef RETURN
  595. #define RETURN(status) \
  596. { \
  597.     if (ximage) XDestroyImage(ximage); \
  598.     if (shapeimage) XDestroyImage(shapeimage); \
  599.     if (ximage_pixels) XpmFree(ximage_pixels); \
  600.     if (mask_pixels) XpmFree(mask_pixels); \
  601.     if (npixels) XFreeColors(display, colormap, pixels, npixels, 0); \
  602.     if (pixels) XpmFree(pixels); \
  603.     return (status); \
  604. }
  605.  
  606. int
  607. XpmCreateImageFromXpmImage(display, image,
  608.                image_return, shapeimage_return, attributes)
  609.     Display *display;
  610.     XpmImage *image;
  611.     XImage **image_return;
  612.     XImage **shapeimage_return;
  613.     XpmAttributes *attributes;
  614. {
  615.     /* variables stored in the XpmAttributes structure */
  616.     Visual *visual;
  617.     Colormap colormap;
  618.     unsigned int depth;
  619.  
  620.     /* variables to return */
  621.     XImage *ximage = NULL;
  622.     XImage *shapeimage = NULL;
  623.     unsigned int mask_pixel;
  624.     int ErrorStatus;
  625.  
  626.     /* calculation variables */
  627.     Pixel *ximage_pixels = NULL;
  628.     Pixel *mask_pixels = NULL;
  629.     Pixel *pixels = NULL;        /* allocated pixels */
  630.     unsigned int npixels = 0;        /* number of allocated pixels */
  631.  
  632.     /* initialize return values */
  633.     if (image_return)
  634.     *image_return = NULL;
  635.     if (shapeimage_return)
  636.     *shapeimage_return = NULL;
  637.  
  638.     /* retrieve information from the XpmAttributes */
  639.     if (attributes && (attributes->valuemask & XpmVisual))
  640.     visual = attributes->visual;
  641.     else
  642.     visual = XDefaultVisual(display, XDefaultScreen(display));
  643.  
  644.     if (attributes && (attributes->valuemask & XpmColormap))
  645.     colormap = attributes->colormap;
  646.     else
  647.     colormap = XDefaultColormap(display, XDefaultScreen(display));
  648.  
  649.     if (attributes && (attributes->valuemask & XpmDepth))
  650.     depth = attributes->depth;
  651.     else
  652.     depth = XDefaultDepth(display, XDefaultScreen(display));
  653.  
  654.     ErrorStatus = XpmSuccess;
  655.  
  656.     /* malloc pixels index tables */
  657.     ximage_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
  658.     if (!ximage_pixels)
  659.     return (XpmNoMemory);
  660.  
  661.     mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
  662.     if (!mask_pixels)
  663.     RETURN(XpmNoMemory);
  664.  
  665.     mask_pixel = XpmUndefPixel;
  666.  
  667.     /* maximum of allocated pixels will be the number of colors */
  668.     pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
  669.     if (!pixels)
  670.     RETURN(XpmNoMemory);
  671.  
  672.     /* get pixel colors, store them in index tables */
  673.     ErrorStatus = CreateColors(display, attributes, image->colorTable,
  674.                    image->ncolors, ximage_pixels, mask_pixels,
  675.                    &mask_pixel, &pixels, &npixels);
  676.  
  677.     if (ErrorStatus != XpmSuccess
  678.     && (ErrorStatus < 0 || (attributes
  679.                 && (attributes->valuemask & XpmExactColors)
  680.                 && attributes->exactColors)))
  681.     RETURN(ErrorStatus);
  682.  
  683.     /* create the ximage */
  684.     if (image_return) {
  685.     ErrorStatus = CreateXImage(display, visual, depth,
  686.                    image->width, image->height, &ximage);
  687.     if (ErrorStatus != XpmSuccess)
  688.         RETURN(ErrorStatus);
  689.  
  690. #ifndef FOR_MSW
  691.  
  692.     /*
  693.      * set the ximage data
  694.      * 
  695.      * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use
  696.      * optimized functions, otherwise use slower but sure general one.
  697.      * 
  698.      */
  699.  
  700.     if (ximage->depth == 1)
  701.         SetImagePixels1(ximage, image->width, image->height,
  702.                 image->data, ximage_pixels);
  703.     else if (ximage->bits_per_pixel == 8)
  704.         SetImagePixels8(ximage, image->width, image->height,
  705.                 image->data, ximage_pixels);
  706.     else if (ximage->bits_per_pixel == 16)
  707.         SetImagePixels16(ximage, image->width, image->height,
  708.                  image->data, ximage_pixels);
  709.     else if (ximage->bits_per_pixel == 32)
  710.         SetImagePixels32(ximage, image->width, image->height,
  711.                  image->data, ximage_pixels);
  712.     else
  713.         SetImagePixels(ximage, image->width, image->height,
  714.                image->data, ximage_pixels);
  715. #else  /* FOR_MSW */
  716.     MSWSetImagePixels(display, ximage, image->width, image->height,
  717.               image->data, ximage_pixels);
  718. #endif
  719.     }
  720.     /* create the shape mask image */
  721.     if (mask_pixel != XpmUndefPixel && shapeimage_return) {
  722.     ErrorStatus = CreateXImage(display, visual, 1, image->width,
  723.                    image->height, &shapeimage);
  724.     if (ErrorStatus != XpmSuccess)
  725.         RETURN(ErrorStatus);
  726.  
  727. #ifndef FOR_MSW
  728.     SetImagePixels1(shapeimage, image->width, image->height,
  729.             image->data, mask_pixels);
  730. #else
  731.     MSWSetImagePixels(display, shapeimage, image->width, image->height,
  732.               image->data, mask_pixels);
  733. #endif
  734.  
  735.     }
  736.     XpmFree(mask_pixels);
  737.     XpmFree(pixels);
  738.  
  739.     /* if requested store alloc'ed pixels in the XpmAttributes structure */
  740.     if (attributes) {
  741.     if (attributes->valuemask & XpmReturnPixels ||
  742. /* 3.2 backward compatibility code */
  743.         attributes->valuemask & XpmReturnInfos) {
  744. /* end 3.2 bc */
  745.         if (mask_pixel != XpmUndefPixel) {
  746.         Pixel *pixels, *p1, *p2;
  747.         unsigned int a;
  748.  
  749.         attributes->npixels = image->ncolors - 1;
  750.         pixels = (Pixel *) XpmMalloc(sizeof(Pixel)
  751.                          * attributes->npixels);
  752.         if (pixels) {
  753.             p1 = ximage_pixels;
  754.             p2 = pixels;
  755.             for (a = 0; a < image->ncolors; a++, p1++)
  756.             if (a != mask_pixel)
  757.                 *p2++ = *p1;
  758.             attributes->pixels = pixels;
  759.         } else {
  760.             /* if error just say we can't return requested data */
  761.             attributes->valuemask &= ~XpmReturnPixels;
  762. /* 3.2 backward compatibility code */
  763.             attributes->valuemask &= ~XpmReturnInfos;
  764. /* end 3.2 bc */
  765.             attributes->pixels = NULL;
  766.             attributes->npixels = 0;
  767.         }
  768.         XpmFree(ximage_pixels);
  769.         } else {
  770.         attributes->pixels = ximage_pixels;
  771.         attributes->npixels = image->ncolors;
  772.         }
  773.         attributes->mask_pixel = mask_pixel;
  774.     } else
  775.         XpmFree(ximage_pixels);
  776.     } else
  777.     XpmFree(ximage_pixels);
  778.  
  779.     /* return created images */
  780.     if (image_return)
  781.     *image_return = ximage;
  782.     if (shapeimage_return)
  783.     *shapeimage_return = shapeimage;
  784.  
  785.     return (ErrorStatus);
  786. }
  787.  
  788.  
  789. /*
  790.  * Create an XImage
  791.  */
  792. static int
  793. CreateXImage(display, visual, depth, width, height, image_return)
  794.     Display *display;
  795.     Visual *visual;
  796.     unsigned int depth;
  797.     unsigned int width;
  798.     unsigned int height;
  799.     XImage **image_return;
  800. {
  801.     int bitmap_pad;
  802.  
  803.     /* first get bitmap_pad */
  804.     if (depth > 16)
  805.     bitmap_pad = 32;
  806.     else if (depth > 8)
  807.     bitmap_pad = 16;
  808.     else
  809.     bitmap_pad = 8;
  810.  
  811.     /* then create the XImage with data = NULL and bytes_per_line = 0 */
  812.     *image_return = XCreateImage(display, visual, depth, ZPixmap, 0, 0,
  813.                  width, height, bitmap_pad, 0);
  814.     if (!*image_return)
  815.     return (XpmNoMemory);
  816.  
  817. #ifndef FOR_MSW
  818.     /* now that bytes_per_line must have been set properly alloc data */
  819.     (*image_return)->data =
  820.     (char *) XpmMalloc((*image_return)->bytes_per_line * height);
  821.  
  822.     if (!(*image_return)->data) {
  823.     XDestroyImage(*image_return);
  824.     *image_return = NULL;
  825.     return (XpmNoMemory);
  826.     }
  827. #else
  828.     /* under FOR_MSW XCreateImage has done it all */
  829. #endif
  830.     return (XpmSuccess);
  831. }
  832.  
  833. #ifndef FOR_MSW
  834. /*
  835.  * The functions below are written from X11R5 MIT's code (XImUtil.c)
  836.  *
  837.  * The idea is to have faster functions than the standard XPutPixel function
  838.  * to build the image data. Indeed we can speed up things by suppressing tests
  839.  * performed for each pixel. We do the same tests but at the image level.
  840.  * We also assume that we use only ZPixmap images with null offsets.
  841.  */
  842.  
  843. LFUNC(_putbits, void, (register char *src, int dstoffset,
  844.                register int numbits, register char *dst));
  845.  
  846. LFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register int nb));
  847.  
  848. static unsigned char Const _reverse_byte[0x100] = {
  849.     0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
  850.     0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
  851.     0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
  852.     0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
  853.     0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
  854.     0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
  855.     0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
  856.     0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
  857.     0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
  858.     0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
  859.     0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
  860.     0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
  861.     0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
  862.     0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
  863.     0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
  864.     0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
  865.     0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
  866.     0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
  867.     0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
  868.     0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
  869.     0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
  870.     0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
  871.     0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
  872.     0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
  873.     0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
  874.     0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
  875.     0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
  876.     0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
  877.     0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
  878.     0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
  879.     0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
  880.     0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
  881. };
  882.  
  883. static int
  884. _XReverse_Bytes(bpt, nb)
  885.     register unsigned char *bpt;
  886.     register int nb;
  887. {
  888.     do {
  889.     *bpt = _reverse_byte[*bpt];
  890.     bpt++;
  891.     } while (--nb > 0);
  892.     return 0;
  893. }
  894.  
  895.  
  896. void
  897. xpm_xynormalizeimagebits(bp, img)
  898.     register unsigned char *bp;
  899.     register XImage *img;
  900. {
  901.     register unsigned char c;
  902.  
  903.     if (img->byte_order != img->bitmap_bit_order) {
  904.     switch (img->bitmap_unit) {
  905.  
  906.     case 16:
  907.         c = *bp;
  908.         *bp = *(bp + 1);
  909.         *(bp + 1) = c;
  910.         break;
  911.  
  912.     case 32:
  913.         c = *(bp + 3);
  914.         *(bp + 3) = *bp;
  915.         *bp = c;
  916.         c = *(bp + 2);
  917.         *(bp + 2) = *(bp + 1);
  918.         *(bp + 1) = c;
  919.         break;
  920.     }
  921.     }
  922.     if (img->bitmap_bit_order == MSBFirst)
  923.     _XReverse_Bytes(bp, img->bitmap_unit >> 3);
  924. }
  925.  
  926. void
  927. xpm_znormalizeimagebits(bp, img)
  928.     register unsigned char *bp;
  929.     register XImage *img;
  930. {
  931.     register unsigned char c;
  932.  
  933.     switch (img->bits_per_pixel) {
  934.  
  935.     case 2:
  936.     _XReverse_Bytes(bp, 1);
  937.     break;
  938.  
  939.     case 4:
  940.     *bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF);
  941.     break;
  942.  
  943.     case 16:
  944.     c = *bp;
  945.     *bp = *(bp + 1);
  946.     *(bp + 1) = c;
  947.     break;
  948.  
  949.     case 24:
  950.     c = *(bp + 2);
  951.     *(bp + 2) = *bp;
  952.     *bp = c;
  953.     break;
  954.  
  955.     case 32:
  956.     c = *(bp + 3);
  957.     *(bp + 3) = *bp;
  958.     *bp = c;
  959.     c = *(bp + 2);
  960.     *(bp + 2) = *(bp + 1);
  961.     *(bp + 1) = c;
  962.     break;
  963.     }
  964. }
  965.  
  966. static unsigned char Const _lomask[0x09] = {
  967. 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  968. static unsigned char Const _himask[0x09] = {
  969. 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
  970.  
  971. static void
  972. _putbits(src, dstoffset, numbits, dst)
  973.     register char *src;            /* address of source bit string */
  974.     int dstoffset;            /* bit offset into destination;
  975.                      * range is 0-31 */
  976.     register int numbits;        /* number of bits to copy to
  977.                      * destination */
  978.     register char *dst;            /* address of destination bit string */
  979. {
  980.     register unsigned char chlo, chhi;
  981.     int hibits;
  982.  
  983.     dst = dst + (dstoffset >> 3);
  984.     dstoffset = dstoffset & 7;
  985.     hibits = 8 - dstoffset;
  986.     chlo = *dst & _lomask[dstoffset];
  987.     for (;;) {
  988.     chhi = (*src << dstoffset) & _himask[dstoffset];
  989.     if (numbits <= hibits) {
  990.         chhi = chhi & _lomask[dstoffset + numbits];
  991.         *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi;
  992.         break;
  993.     }
  994.     *dst = chhi | chlo;
  995.     dst++;
  996.     numbits = numbits - hibits;
  997.     chlo = (unsigned char) (*src & _himask[hibits]) >> hibits;
  998.     src++;
  999.     if (numbits <= dstoffset) {
  1000.         chlo = chlo & _lomask[numbits];
  1001.         *dst = (*dst & _himask[numbits]) | chlo;
  1002.         break;
  1003.     }
  1004.     numbits = numbits - dstoffset;
  1005.     }
  1006. }
  1007.  
  1008. /*
  1009.  * Default method to write pixels into a Z image data structure.
  1010.  * The algorithm used is:
  1011.  *
  1012.  *    copy the destination bitmap_unit or Zpixel to temp
  1013.  *    normalize temp if needed
  1014.  *    copy the pixel bits into the temp
  1015.  *    renormalize temp if needed
  1016.  *    copy the temp back into the destination image data
  1017.  */
  1018.  
  1019. static void
  1020. SetImagePixels(image, width, height, pixelindex, pixels)
  1021.     XImage *image;
  1022.     unsigned int width;
  1023.     unsigned int height;
  1024.     unsigned int *pixelindex;
  1025.     Pixel *pixels;
  1026. {
  1027.     register char *src;
  1028.     register char *dst;
  1029.     register unsigned int *iptr;
  1030.     register int x, y, i;
  1031.     register char *data;
  1032.     Pixel pixel, px;
  1033.     int nbytes, depth, ibu, ibpp;
  1034.  
  1035.     data = image->data;
  1036.     iptr = pixelindex;
  1037.     depth = image->depth;
  1038.     if (depth == 1) {
  1039.     ibu = image->bitmap_unit;
  1040.     for (y = 0; y < height; y++)
  1041.         for (x = 0; x < width; x++, iptr++) {
  1042.         pixel = pixels[*iptr];
  1043.         for (i = 0, px = pixel; i < sizeof(unsigned long);
  1044.              i++, px >>= 8)
  1045.             ((unsigned char *) &pixel)[i] = px;
  1046.         src = &data[XYINDEX(x, y, image)];
  1047.         dst = (char *) &px;
  1048.         px = 0;
  1049.         nbytes = ibu >> 3;
  1050.         for (i = nbytes; --i >= 0;)
  1051.             *dst++ = *src++;
  1052.         XYNORMALIZE(&px, image);
  1053.         _putbits((char *) &pixel, (x % ibu), 1, (char *) &px);
  1054.         XYNORMALIZE(&px, image);
  1055.         src = (char *) &px;
  1056.         dst = &data[XYINDEX(x, y, image)];
  1057.         for (i = nbytes; --i >= 0;)
  1058.             *dst++ = *src++;
  1059.         }
  1060.     } else {
  1061.     ibpp = image->bits_per_pixel;
  1062.     for (y = 0; y < height; y++)
  1063.         for (x = 0; x < width; x++, iptr++) {
  1064.         pixel = pixels[*iptr];
  1065.         if (depth == 4)
  1066.             pixel &= 0xf;
  1067.         for (i = 0, px = pixel; i < sizeof(unsigned long); i++,
  1068.              px >>= 8)
  1069.             ((unsigned char *) &pixel)[i] = px;
  1070.         src = &data[ZINDEX(x, y, image)];
  1071.         dst = (char *) &px;
  1072.         px = 0;
  1073.         nbytes = (ibpp + 7) >> 3;
  1074.         for (i = nbytes; --i >= 0;)
  1075.             *dst++ = *src++;
  1076.         ZNORMALIZE(&px, image);
  1077.         _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
  1078.         ZNORMALIZE(&px, image);
  1079.         src = (char *) &px;
  1080.         dst = &data[ZINDEX(x, y, image)];
  1081.         for (i = nbytes; --i >= 0;)
  1082.             *dst++ = *src++;
  1083.         }
  1084.     }
  1085. }
  1086.  
  1087. /*
  1088.  * write pixels into a 32-bits Z image data structure
  1089.  */
  1090.  
  1091. #ifndef WORD64
  1092. /* this item is static but deterministic so let it slide; doesn't
  1093.  * hurt re-entrancy of this library. Note if it is actually const then would
  1094.  * be OK under rules of ANSI-C but probably not C++ which may not
  1095.  * want to allocate space for it.
  1096.  */
  1097. static unsigned long /* constant */ RTXpm_byteorderpixel = MSBFirst << 24;
  1098.  
  1099. #endif
  1100.  
  1101. /*
  1102.    WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original
  1103.    3.2e code - by default you get the speeded-up version.
  1104. */
  1105.  
  1106. static void
  1107. SetImagePixels32(image, width, height, pixelindex, pixels)
  1108.     XImage *image;
  1109.     unsigned int width;
  1110.     unsigned int height;
  1111.     unsigned int *pixelindex;
  1112.     Pixel *pixels;
  1113. {
  1114.     unsigned char *data;
  1115.     unsigned int *iptr;
  1116.     int y;
  1117.     Pixel pixel;
  1118.  
  1119. #ifdef WITHOUT_SPEEDUPS
  1120.  
  1121.     int x;
  1122.     unsigned char *addr;
  1123.  
  1124.     data = (unsigned char *) image->data;
  1125.     iptr = pixelindex;
  1126. #ifndef WORD64
  1127.     if (*((char *) &RTXpm_byteorderpixel) == image->byte_order) {
  1128.     for (y = 0; y < height; y++)
  1129.         for (x = 0; x < width; x++, iptr++) {
  1130.         addr = &data[ZINDEX32(x, y, image)];
  1131.         *((unsigned long *) addr) = pixels[*iptr];
  1132.         }
  1133.     } else
  1134. #endif
  1135.     if (image->byte_order == MSBFirst)
  1136.     for (y = 0; y < height; y++)
  1137.         for (x = 0; x < width; x++, iptr++) {
  1138.         addr = &data[ZINDEX32(x, y, image)];
  1139.         pixel = pixels[*iptr];
  1140.         addr[0] = pixel >> 24;
  1141.         addr[1] = pixel >> 16;
  1142.         addr[2] = pixel >> 8;
  1143.         addr[3] = pixel;
  1144.         }
  1145.     else
  1146.     for (y = 0; y < height; y++)
  1147.         for (x = 0; x < width; x++, iptr++) {
  1148.         addr = &data[ZINDEX32(x, y, image)];
  1149.         pixel = pixels[*iptr];
  1150.         addr[0] = pixel;
  1151.         addr[1] = pixel >> 8;
  1152.         addr[2] = pixel >> 16;
  1153.         addr[3] = pixel >> 24;
  1154.         }
  1155.  
  1156. #else  /* WITHOUT_SPEEDUPS */
  1157.  
  1158.     int bpl = image->bytes_per_line;
  1159.     unsigned char *data_ptr, *max_data;
  1160.  
  1161.     data = (unsigned char *) image->data;
  1162.     iptr = pixelindex;
  1163. #ifndef WORD64
  1164.     if (*((char *) &RTXpm_byteorderpixel) == image->byte_order) {
  1165.     for (y = 0; y < height; y++) {
  1166.         data_ptr = data;
  1167.         max_data = data_ptr + (width << 2);
  1168.  
  1169.         while (data_ptr < max_data) {
  1170.         *((unsigned long *) data_ptr) = pixels[*(iptr++)];
  1171.         data_ptr += (1 << 2);
  1172.         }
  1173.         data += bpl;
  1174.     }
  1175.     } else
  1176. #endif
  1177.     if (image->byte_order == MSBFirst)
  1178.     for (y = 0; y < height; y++) {
  1179.         data_ptr = data;
  1180.         max_data = data_ptr + (width << 2);
  1181.  
  1182.         while (data_ptr < max_data) {
  1183.         pixel = pixels[*(iptr++)];
  1184.  
  1185.         *data_ptr++ = pixel >> 24;
  1186.         *data_ptr++ = pixel >> 16;
  1187.         *data_ptr++ = pixel >> 8;
  1188.         *data_ptr++ = pixel;
  1189.  
  1190.         }
  1191.         data += bpl;
  1192.     }
  1193.     else
  1194.     for (y = 0; y < height; y++) {
  1195.         data_ptr = data;
  1196.         max_data = data_ptr + (width << 2);
  1197.  
  1198.         while (data_ptr < max_data) {
  1199.         pixel = pixels[*(iptr++)];
  1200.  
  1201.         *data_ptr++ = pixel;
  1202.         *data_ptr++ = pixel >> 8;
  1203.         *data_ptr++ = pixel >> 16;
  1204.         *data_ptr++ = pixel >> 24;
  1205.         }
  1206.         data += bpl;
  1207.     }
  1208.  
  1209. #endif /* WITHOUT_SPEEDUPS */
  1210. }
  1211.  
  1212. /*
  1213.  * write pixels into a 16-bits Z image data structure
  1214.  */
  1215.  
  1216. static void
  1217. SetImagePixels16(image, width, height, pixelindex, pixels)
  1218.     XImage *image;
  1219.     unsigned int width;
  1220.     unsigned int height;
  1221.     unsigned int *pixelindex;
  1222.     Pixel *pixels;
  1223. {
  1224.     unsigned char *data;
  1225.     unsigned int *iptr;
  1226.     int y;
  1227.  
  1228. #ifdef WITHOUT_SPEEDUPS
  1229.  
  1230.     int x;
  1231.     unsigned char *addr;
  1232.  
  1233.     data = (unsigned char *) image->data;
  1234.     iptr = pixelindex;
  1235.     if (image->byte_order == MSBFirst)
  1236.     for (y = 0; y < height; y++)
  1237.         for (x = 0; x < width; x++, iptr++) {
  1238.         addr = &data[ZINDEX16(x, y, image)];
  1239.         addr[0] = pixels[*iptr] >> 8;
  1240.         addr[1] = pixels[*iptr];
  1241.         }
  1242.     else
  1243.     for (y = 0; y < height; y++)
  1244.         for (x = 0; x < width; x++, iptr++) {
  1245.         addr = &data[ZINDEX16(x, y, image)];
  1246.         addr[0] = pixels[*iptr];
  1247.         addr[1] = pixels[*iptr] >> 8;
  1248.         }
  1249.  
  1250. #else  /* WITHOUT_SPEEDUPS */
  1251.  
  1252.     Pixel pixel;
  1253.  
  1254.     int bpl = image->bytes_per_line;
  1255.     unsigned char *data_ptr, *max_data;
  1256.  
  1257.     data = (unsigned char *) image->data;
  1258.     iptr = pixelindex;
  1259.     if (image->byte_order == MSBFirst)
  1260.     for (y = 0; y < height; y++) {
  1261.         data_ptr = data;
  1262.         max_data = data_ptr + (width << 1);
  1263.  
  1264.         while (data_ptr < max_data) {
  1265.         pixel = pixels[*(iptr++)];
  1266.  
  1267.         data_ptr[0] = pixel >> 8;
  1268.         data_ptr[1] = pixel;
  1269.  
  1270.         data_ptr += (1 << 1);
  1271.         }
  1272.         data += bpl;
  1273.     }
  1274.     else
  1275.     for (y = 0; y < height; y++) {
  1276.         data_ptr = data;
  1277.         max_data = data_ptr + (width << 1);
  1278.  
  1279.         while (data_ptr < max_data) {
  1280.         pixel = pixels[*(iptr++)];
  1281.  
  1282.         data_ptr[0] = pixel;
  1283.         data_ptr[1] = pixel >> 8;
  1284.  
  1285.         data_ptr += (1 << 1);
  1286.         }
  1287.         data += bpl;
  1288.     }
  1289.  
  1290. #endif /* WITHOUT_SPEEDUPS */
  1291. }
  1292.  
  1293. /*
  1294.  * write pixels into a 8-bits Z image data structure
  1295.  */
  1296.  
  1297. static void
  1298. SetImagePixels8(image, width, height, pixelindex, pixels)
  1299.     XImage *image;
  1300.     unsigned int width;
  1301.     unsigned int height;
  1302.     unsigned int *pixelindex;
  1303.     Pixel *pixels;
  1304. {
  1305.     char *data;
  1306.     unsigned int *iptr;
  1307.     int y;
  1308.  
  1309. #ifdef WITHOUT_SPEEDUPS
  1310.  
  1311.     int x;
  1312.  
  1313.     data = image->data;
  1314.     iptr = pixelindex;
  1315.     for (y = 0; y < height; y++)
  1316.     for (x = 0; x < width; x++, iptr++)
  1317.         data[ZINDEX8(x, y, image)] = pixels[*iptr];
  1318.  
  1319. #else  /* WITHOUT_SPEEDUPS */
  1320.  
  1321.     int bpl = image->bytes_per_line;
  1322.     char *data_ptr, *max_data;
  1323.  
  1324.     data = image->data;
  1325.     iptr = pixelindex;
  1326.  
  1327.     for (y = 0; y < height; y++) {
  1328.     data_ptr = data;
  1329.     max_data = data_ptr + width;
  1330.  
  1331.     while (data_ptr < max_data)
  1332.         *(data_ptr++) = pixels[*(iptr++)];
  1333.  
  1334.     data += bpl;
  1335.     }
  1336.  
  1337. #endif /* WITHOUT_SPEEDUPS */
  1338. }
  1339.  
  1340. /*
  1341.  * write pixels into a 1-bit depth image data structure and **offset null**
  1342.  */
  1343.  
  1344. static void
  1345. SetImagePixels1(image, width, height, pixelindex, pixels)
  1346.     XImage *image;
  1347.     unsigned int width;
  1348.     unsigned int height;
  1349.     unsigned int *pixelindex;
  1350.     Pixel *pixels;
  1351. {
  1352.     if (image->byte_order != image->bitmap_bit_order)
  1353.     SetImagePixels(image, width, height, pixelindex, pixels);
  1354.     else {
  1355.     unsigned int *iptr;
  1356.     int y;
  1357.     char *data;
  1358.  
  1359. #ifdef WITHOUT_SPEEDUPS
  1360.  
  1361.     int x;
  1362.  
  1363.     data = image->data;
  1364.     iptr = pixelindex;
  1365.     if (image->bitmap_bit_order == MSBFirst)
  1366.         for (y = 0; y < height; y++)
  1367.         for (x = 0; x < width; x++, iptr++) {
  1368.             if (pixels[*iptr] & 1)
  1369.             data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7);
  1370.             else
  1371.             data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7));
  1372.         }
  1373.     else
  1374.         for (y = 0; y < height; y++)
  1375.         for (x = 0; x < width; x++, iptr++) {
  1376.             if (pixels[*iptr] & 1)
  1377.             data[ZINDEX1(x, y, image)] |= 1 << (x & 7);
  1378.             else
  1379.             data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7));
  1380.         }
  1381.  
  1382. #else  /* WITHOUT_SPEEDUPS */
  1383.  
  1384.     char value;
  1385.     char *data_ptr, *max_data;
  1386.     int bpl = image->bytes_per_line;
  1387.     int diff, count;
  1388.  
  1389.     data = image->data;
  1390.     iptr = pixelindex;
  1391.  
  1392.     diff = width & 7;
  1393.     width >>= 3;
  1394.  
  1395.     if (image->bitmap_bit_order == MSBFirst)
  1396.         for (y = 0; y < height; y++) {
  1397.         data_ptr = data;
  1398.         max_data = data_ptr + width;
  1399.         while (data_ptr < max_data) {
  1400.             value = 0;
  1401.  
  1402.             value = (value << 1) | (pixels[*(iptr++)] & 1);
  1403.             value = (value << 1) | (pixels[*(iptr++)] & 1);
  1404.             value = (value << 1) | (pixels[*(iptr++)] & 1);
  1405.             value = (value << 1) | (pixels[*(iptr++)] & 1);
  1406.             value = (value << 1) | (pixels[*(iptr++)] & 1);
  1407.             value = (value << 1) | (pixels[*(iptr++)] & 1);
  1408.             value = (value << 1) | (pixels[*(iptr++)] & 1);
  1409.             value = (value << 1) | (pixels[*(iptr++)] & 1);
  1410.  
  1411.             *(data_ptr++) = value;
  1412.         }
  1413.         if (diff) {
  1414.             value = 0;
  1415.             for (count = 0; count < diff; count++) {
  1416.             if (pixels[*(iptr++)] & 1)
  1417.                 value |= (0x80 >> count);
  1418.             }
  1419.             *(data_ptr) = value;
  1420.         }
  1421.         data += bpl;
  1422.         }
  1423.     else
  1424.         for (y = 0; y < height; y++) {
  1425.         data_ptr = data;
  1426.         max_data = data_ptr + width;
  1427.         while (data_ptr < max_data) {
  1428.             value = 0;
  1429.             iptr += 8;
  1430.  
  1431.             value = (value << 1) | (pixels[*(--iptr)] & 1);
  1432.             value = (value << 1) | (pixels[*(--iptr)] & 1);
  1433.             value = (value << 1) | (pixels[*(--iptr)] & 1);
  1434.             value = (value << 1) | (pixels[*(--iptr)] & 1);
  1435.             value = (value << 1) | (pixels[*(--iptr)] & 1);
  1436.             value = (value << 1) | (pixels[*(--iptr)] & 1);
  1437.             value = (value << 1) | (pixels[*(--iptr)] & 1);
  1438.             value = (value << 1) | (pixels[*(--iptr)] & 1);
  1439.  
  1440.             iptr += 8;
  1441.             *(data_ptr++) = value;
  1442.         }
  1443.         if (diff) {
  1444.             value = 0;
  1445.             for (count = 0; count < diff; count++) {
  1446.             if (pixels[*(iptr++)] & 1)
  1447.                 value |= (1 << count);
  1448.             }
  1449.             *(data_ptr) = value;
  1450.         }
  1451.         data += bpl;
  1452.         }
  1453.  
  1454. #endif /* WITHOUT_SPEEDUPS */
  1455.     }
  1456. }
  1457.  
  1458. int
  1459. XpmCreatePixmapFromXpmImage(display, d, image,
  1460.                 pixmap_return, shapemask_return, attributes)
  1461.     Display *display;
  1462.     Drawable d;
  1463.     XpmImage *image;
  1464.     Pixmap *pixmap_return;
  1465.     Pixmap *shapemask_return;
  1466.     XpmAttributes *attributes;
  1467. {
  1468.     XImage *ximage, *shapeimage;
  1469.     int ErrorStatus;
  1470.  
  1471.     /* initialize return values */
  1472.     if (pixmap_return)
  1473.     *pixmap_return = 0;
  1474.     if (shapemask_return)
  1475.     *shapemask_return = 0;
  1476.  
  1477.     /* create the ximages */
  1478.     ErrorStatus = XpmCreateImageFromXpmImage(display, image,
  1479.                          (pixmap_return ? &ximage : NULL),
  1480.                          (shapemask_return ?
  1481.                           &shapeimage : NULL),
  1482.                          attributes);
  1483.     if (ErrorStatus < 0)
  1484.     return (ErrorStatus);
  1485.  
  1486.     /* create the pixmaps and destroy images */
  1487.     if (pixmap_return && ximage) {
  1488.     xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
  1489.     XDestroyImage(ximage);
  1490.     }
  1491.     if (shapemask_return && shapeimage) {
  1492.     xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
  1493.     XDestroyImage(shapeimage);
  1494.     }
  1495.     return (ErrorStatus);
  1496. }
  1497.  
  1498. #else  /* FOR_MSW part follows */
  1499. static void
  1500. MSWSetImagePixels(dc, image, width, height, pixelindex, pixels)
  1501.     Display *dc;
  1502.     XImage *image;
  1503.     unsigned int width;
  1504.     unsigned int height;
  1505.     unsigned int *pixelindex;
  1506.     Pixel *pixels;
  1507. {
  1508.     unsigned int *data = pixelindex;
  1509.     unsigned int x, y;
  1510.  
  1511.     SelectObject(*dc, image->bitmap);
  1512.     for (y = 0; y < height; y++) {
  1513.     for (x = 0; x < width; x++) {
  1514.         SetPixel(*dc, x, y, pixels[*(data++)]); /* data is [x+y*width] */
  1515.     }
  1516.     }
  1517. }
  1518.  
  1519. #endif /* FOR_MSW */
  1520.