2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /************************************<+>*************************************
24 ****************************************************************************
28 ** Project: CDE Help System
30 ** Description: This code processes a graphic (X11 bitmap, X11 pixmap,
31 ** X11 XWD file, and TIFF). It will degrade graphics to
32 ** match the type of monitor the image is displayed upon.
34 ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
36 ** (c) Copyright 1993, 1994 Hewlett-Packard Company
37 ** (c) Copyright 1993, 1994 International Business Machines Corp.
38 ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
39 ** (c) Copyright 1993, 1994 Novell, Inc.
41 ****************************************************************************
42 ************************************<+>*************************************/
43 /******************************************************************************
44 ** The GreyScale and Perform_Dither routine were take and modified from
45 ** the g-job 'xgedit' created by Mark F. Cook. The following is the
46 ** disclaimer from the dither.c source code
47 ******************************************************************************
50 ** Description: X11-based graphics editor
52 ** File: dither.c, containing the following
53 ** subroutines/functions:
57 ** Copyright 1988 by Mark F. Cook and Hewlett-Packard, Corvallis
58 ** Workstation Operation. All rights reserved.
60 ** Permission to use, copy, and modify this software is granted, provided
61 ** that this copyright appears in all copies and that both this copyright
62 ** and permission notice appear in all supporting documentation, and that
63 ** the name of Mark F. Cook and/or Hewlett-Packard not be used in advertising
64 ** without specific, written prior permission. Neither Mark F. Cook or
65 ** Hewlett-Packard make any representations about the suitibility of this
66 ** software for any purpose. It is provided "as is" without express or
69 ******************************************************************************
72 ** 1.00.00 - 1/11/89 - Start of Rev. number.
74 ** @@@ 4.05.00 - 12/07/89 - Created Dither_Image() and Perform_Dither() to
75 ** @@@ allow conversion of color images into a dithered black &
76 ** @@@ white image suitable for output on a laser printer.
78 ******************************************************************************/
81 static char rcs_id[]="$XConsortium: Graphics.c /main/23 1996/12/06 11:12:54 cde-hp $";
91 #include <X11/XWDFile.h>
92 #include <X11/ImUtil.h>
100 #include <Xm/XmPrivate.h>
107 #include "GraphicsP.h"
108 #include "GraphicsI.h"
109 #include "StringFuncsI.h"
110 #include "GifUtilsI.h"
111 #include "XbmUtilsI.h"
112 #include "JpegUtilsI.h"
115 /*****************************************************************************/
117 /*****************************************************************************/
118 #define GR_SUCCESS 0 /* everything okay */
119 #define GR_DRAWABLE_ERR 1 /* couldn't get drawable attr/geom */
120 #define GR_FILE_ERR 2 /* file open/read/write problem */
121 #define GR_REQUEST_ERR 3 /* bad placement or size */
122 #define GR_ALLOC_ERR 4 /* memory allocation failure */
123 #define GR_HEADER_ERR 5 /* file header version/size problem */
125 #define MAX_GREY_COLORS 8
127 #define RES_TOLERANCE 25 /* resolution scaling tolerance */
129 static short GreyAllocated = False;
130 static Pixel GreyScalePixels[MAX_GREY_COLORS];
131 static char *GreyScaleColors[MAX_GREY_COLORS] =
143 #define Missing_bm_width 75
144 #define Missing_bm_height 47
145 static unsigned char Missing_bm_bits[] = {
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
149 0xff, 0xff, 0x7f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
150 0xff, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
151 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00,
152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x04, 0x01, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0xc0, 0x00, 0x18, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0xc0, 0x00, 0x18, 0x8c, 0x21, 0x00, 0x00, 0x20, 0x00, 0x00, 0xc0, 0x00,
156 0x18, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x24,
157 0x31, 0xf0, 0xf0, 0x30, 0xe8, 0xf0, 0xc1, 0x00, 0x18, 0x04, 0x21, 0x08,
158 0x08, 0x20, 0x18, 0x09, 0xc1, 0x00, 0x18, 0x04, 0x21, 0xf0, 0xf0, 0x20,
159 0x08, 0x09, 0xc1, 0x00, 0x18, 0x04, 0x21, 0x00, 0x01, 0x21, 0x08, 0x09,
160 0xc1, 0x00, 0x18, 0x04, 0x21, 0x08, 0x09, 0x21, 0x08, 0x09, 0xc1, 0x00,
161 0x18, 0x04, 0x71, 0xf0, 0xf0, 0x70, 0x08, 0xf1, 0xc1, 0x00, 0x18, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x18, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
164 0x00, 0xf0, 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
166 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0xf0,
167 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x08, 0x01, 0x00,
168 0x00, 0x08, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x08, 0x00, 0x00, 0x00, 0x08,
169 0x20, 0x00, 0xc0, 0x00, 0x18, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
170 0xc0, 0x00, 0x18, 0x08, 0xd8, 0xf0, 0xe8, 0xf8, 0x30, 0xf0, 0xc0, 0x00,
171 0x18, 0xc8, 0x31, 0x01, 0x19, 0x09, 0x21, 0x08, 0xc1, 0x00, 0x18, 0x08,
172 0x11, 0xf0, 0x09, 0x09, 0x21, 0x08, 0xc0, 0x00, 0x18, 0x08, 0x11, 0x08,
173 0x09, 0x09, 0x21, 0x08, 0xc0, 0x00, 0x18, 0x08, 0x11, 0x08, 0x09, 0x09,
174 0x21, 0x08, 0xc1, 0x00, 0x18, 0xf0, 0x10, 0xf0, 0xf9, 0x08, 0x71, 0xf0,
175 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xc0, 0x00,
176 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00,
177 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00,
178 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
179 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
181 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf8, 0xff,
182 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
183 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
184 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187 /* Used to hold image type converter registry info */
190 _DtGrLoadProc convert_proc;
191 _DtGrDestroyContextProc destroy_context_proc;
195 * This array maps image file name extensions to the corresponding
196 * CDE data type. It is used by the DetermineImageType function.
197 * The array must be NULL-terminated.
199 static char * img_extensions[] = {
214 /*****************************************************************************/
215 /* Private declarations */
216 /*****************************************************************************/
218 static int Do_Direct(
221 XWDFileHeader *header,
225 enum _DtGrColorModel force,
228 unsigned long **ret_colors,
230 static int Do_Pseudo(
236 enum _DtGrColorModel force,
239 unsigned long **ret_colors,
241 static int GreyScale (
249 enum _DtGrColorModel force,
256 static unsigned int Image_Size(
258 static void Perform_Dither(
263 static enum _DtGrLoadStatus processBitmap(
272 enum _DtGrColorModel color_model,
273 Boolean allow_reduced_colors,
274 Dimension *in_out_width,
275 Dimension *in_out_height,
276 unsigned short media_resolution,
281 _DtGrContext *context);
283 static enum _DtGrLoadStatus processTiff(
292 enum _DtGrColorModel color_model,
293 Boolean allow_reduced_colors,
294 Dimension *in_out_width,
295 Dimension *in_out_height,
296 unsigned short media_resolution,
301 _DtGrContext *context);
302 static void destroyTiffContext(
303 _DtGrContext *context);
305 static enum _DtGrLoadStatus processXwd(
314 enum _DtGrColorModel color_model,
315 Boolean allow_reduced_colors,
316 Dimension *in_out_width,
317 Dimension *in_out_height,
318 unsigned short media_resolution,
323 _DtGrContext *context);
324 static void _swaplong (
326 register unsigned n );
327 static void _swapshort (
329 register unsigned n );
330 static int XwdFileToPixmap (
338 enum _DtGrColorModel color_model,
346 unsigned long **ret_colors,
348 static enum _DtGrLoadStatus processXpm(
357 enum _DtGrColorModel color_model,
358 Boolean allow_reduced_colors,
359 Dimension *in_out_width,
360 Dimension *in_out_height,
361 unsigned short media_resolution,
366 _DtGrContext *context);
367 static enum _DtGrLoadStatus processGIF(
376 enum _DtGrColorModel color_model,
377 Boolean allow_reduced_colors,
378 Dimension *in_out_width,
379 Dimension *in_out_height,
380 unsigned short media_resolution,
385 _DtGrContext *context);
386 static enum _DtGrLoadStatus processJPEG(
395 enum _DtGrColorModel color_model,
396 Boolean allow_reduced_colors,
397 Dimension *in_out_width,
398 Dimension *in_out_height,
399 unsigned short media_resolution,
404 _DtGrContext *context);
405 static enum _DtGrLoadStatus DetermineImageType(
408 static enum _DtGrLoadStatus GetConverterAndDestructor(
410 _DtGrLoadProc *converter,
411 _DtGrDestroyContextProc *destructor);
412 static float ComputeRatio(int media_res, int image_res);
414 /*****************************************************************************
415 * Image type registry declarations
416 *****************************************************************************/
418 /* Registry of converters and destructors for default image types */
419 static _DtGrRegistryRec registry[] =
458 static int registry_count = XtNumber(registry);
460 /* Registry of converters and destructors for non-default image types */
461 static _DtGrRegistryRec *new_registry = NULL;
462 static int new_registry_count = 0;
464 /*****************************************************************************
466 *****************************************************************************/
467 /*****************************************************************************
468 * taken straight out of xwud and modified.
469 *****************************************************************************/
470 /* Copyright 1985, 1986, 1988 Massachusetts Institute of Technology */
475 register unsigned n )
478 register char *ep = bp + n;
491 register unsigned n )
494 register char *ep = bp + n;
511 ComputeRatio(int media_res, int image_res)
516 if (media_res >= image_res) {
517 ratio = (float)media_res / (float)image_res;
518 if (media_res % image_res == 0)
520 iratio = ratio + 0.5;
521 dx = media_res - image_res * iratio;
522 if (dx >= -RES_TOLERANCE && dx <= RES_TOLERANCE)
523 ratio = (float)iratio;
525 ratio = (float)image_res / (float)media_res;
526 if (image_res % media_res == 0)
528 iratio = ratio + 0.5;
529 dx = image_res - media_res * iratio;
530 if (dx >= -RES_TOLERANCE && dx <= RES_TOLERANCE)
531 ratio = (float)iratio;
537 /*****************************************************************************
538 * Function: GreyScale
540 * Turn a color image into a 8 grey color image
541 * If it can't create a grey scale image, GreyScale will call
542 * Perform_Dither to create a bi-tonal image.
544 *****************************************************************************
545 * The GreyScale code was ported from xgedit and changed to fit our needs
546 *****************************************************************************/
556 enum _DtGrColorModel force,
567 int width = in_image->width;
568 int height = in_image->height;
571 Pixel valueArray[256];
575 /*--- allocate an array big enough to map each pixel in the image ---*/
576 /*--- into a corresponding greyscale value (in the range [0-255]). ---*/
578 grey_scale = (int *) calloc(width*height, sizeof(int));
579 if (grey_scale == NULL) {
583 /*--- < ESTABLISH THE GREYSCALE IMAGE > ---*/
584 /*--- The NTSC formula for converting an RGB value into the ---*/
585 /*--- corresponding greyscale value is: ---*/
586 /*--- luminosity = .299 red + .587 green + .114 blue ---*/
589 * zero the flag array
591 for (i = 0; i < 256; i++)
594 for (j=0, x = 0; j<height; j++)
595 for (i=0; i<width; i++, x++) {
596 n = XGetPixel(in_image, i, j);
599 ret_color.red = (n >> rshift) & rmask;
600 ret_color.green = (n >> gshift) & gmask;
601 ret_color.blue = (n >> bshift) & bmask;
604 ret_color.red = colors[ret_color.red ].red;
605 ret_color.green = colors[ret_color.green].green;
606 ret_color.blue = colors[ret_color.blue ].blue;
610 ret_color.red = (((Pixel) ret_color.red ) * 65535) / rmask;
611 ret_color.green = (((Pixel) ret_color.green) * 65535) / gmask;
612 ret_color.blue = (((Pixel) ret_color.blue ) * 65535) / bmask;
615 value = (((int)(ret_color.red*299) + (int)(ret_color.green*587) +
616 (int)(ret_color.blue*114)) / 1000) >> 8;
619 value = (((int)(colors[n].red*299) + (int)(colors[n].green*587) +
620 (int)(colors[n].blue*114)) / 1000) >> 8;
621 grey_scale[x] = value;
626 * Find out if we can/have allocate the pre-defined grey colors.
628 _DtHelpProcessLock();
629 if (!GreyAllocated && force != _DtGrBITONAL)
631 for (i = 0; !GreyAllocated && i < MAX_GREY_COLORS; i++)
633 if (!XParseColor (dpy, cmap, GreyScaleColors[i], &ret_color) ||
634 !XAllocColor (dpy, cmap, &ret_color))
637 * Have a problem allocating one of the pre-defined
638 * grey colors. Free the already allocated pixels
642 XFreeColors (dpy, cmap, GreyScalePixels, i, 0);
646 GreyScalePixels[i] = ret_color.pixel;
649 GreyAllocated = True;
653 * Had a problem allocating the pre-defined grey colors.
654 * Try to dither into black and white.
656 if (force == _DtGrBITONAL || GreyAllocated == -1)
658 Perform_Dither (dpy, screen, out_image, grey_scale);
660 _DtHelpProcessUnlock();
663 _DtHelpProcessUnlock();
666 * Find out how many grey scale colors there are.
668 for (count = 0, i = 0; i < 256; i++)
673 * If we have less than maximum grey colors we want to spread the load
676 if (count < MAX_GREY_COLORS)
679 inc = MAX_GREY_COLORS;
682 * This is rather esoteric code.
684 * valueArray[n] = GreyScalePixels[i * MAX_GREY_COLORS / inc]
686 * causes the colors to be evenly distributed if the total number
687 * of calculated grey shades is less than the number of pre-defined
691 * if (j >= count / (MAX_GREY_COLORS - i))
693 * uniformly reduces the calculated grey shades into the pre-defined
694 * grey colors, if the total number of grey shades is greater than
695 * the number of pre-defined grey colors.
697 * If after reading the following code, the reader still doesn't
698 * understand it, pick a couple of numbers between 1-255 for 'count'
699 * and walk each of them thru the 'for' loop. Hopefully it will help.
700 * (Suggestion - pick a large number for one value and pick
701 * a number less than 8 for the other value).
703 for (i = 0, n = 0, j = 0; n < 256 && count && i < MAX_GREY_COLORS; n++)
707 _DtHelpProcessLock();
708 valueArray[n] = GreyScalePixels[i * MAX_GREY_COLORS / inc];
709 _DtHelpProcessUnlock();
711 if (j >= count / (MAX_GREY_COLORS - i))
721 * Now replace the image pixels with the grey pixels
723 for (j = 0, x = 0; j < height; j++)
724 for (i = 0; i < width; i++, x++) {
725 XPutPixel (out_image, i, j, valueArray[grey_scale[x]]);
733 /***************************************************************************
735 * Routine: Perform_Dither *
737 * Purpose: Given a color XImage and a greyscale representation of it, *
738 * for each pixel in the image, determine whether it should be *
739 * coverted to Black or White base on the weighted average of *
740 * the greyscale value of it and the pixels surrounding it. *
741 * Be sure to do bounds checking for pixels that are at the *
742 * edge of the image. *
744 * The dithering is done using the Floyd-Steinberg error *
745 * diffusion algorithm, which incorporates a Stucki error *
746 * filter (specifics can be found in Chapter 8, "Dithering *
747 * with Blue Noise", of the book "Digital Halftoning" by *
748 * Robert Ulichney (MIT Press, 1988). *
750 *X11***********************************************************************/
758 int i, j, width, height;
759 int result, error, max_lum;
760 Pixel blackPixel = XBlackPixel (dpy, screen);
761 Pixel whitePixel = XWhitePixel (dpy, screen);
763 width = image->width;
764 height = image->height;
767 for (j=0; j<height; j++) /* rows */
768 for (i=0; i<width; i++) { /* columns */
769 if (greyscale[(j*width)+i] < (max_lum/2))
772 result = max_lum - 1;
773 error = greyscale[(j*width)+i] - result;
774 if (i+1 < width) /*--- G [j] [i+1] ---*/
775 greyscale[(j*width)+i+1] += (error * 8)/42;
776 if (i+2 < width) /*--- G [j] [i+2] ---*/
777 greyscale[(j*width)+i+2] += (error * 4)/42;
780 if (i-2 >= 0) /*--- G [j+1] [i-2] ---*/
781 greyscale[((j+1)*width)+i-2] += (error * 2)/42;
782 if (i-1 >= 0) /*--- G [j+1] [i-1] ---*/
783 greyscale[((j+1)*width)+i-1] += (error * 4)/42;
784 /*--- G [j+1] [i] ---*/
785 greyscale[((j+1)*width)+i] += (error * 8)/42;
786 if (i+1 < width) /*--- G [j+1] [i+1] ---*/
787 greyscale[((j+1)*width)+i+1] += (error * 4)/42;
788 if (i+2 < width) /*--- G [j+1] [i+2] ---*/
789 greyscale[((j+1)*width)+i+2] += (error * 2)/42;
793 if (i-2 >= 0) /*--- G [j+2] [i-2] ---*/
794 greyscale[((j+2)*width)+i-2] += error/42;
795 if (i-1 >= 0) /*--- G [j+2] [i-1] ---*/
796 greyscale[((j+2)*width)+i-1] += (error * 2)/42;
797 /*--- G [j+2] [i] ---*/
798 greyscale[((j+2)*width)+i] += (error * 4)/42;
799 if (i+1 < width) /*--- G [j+2] [i+1] ---*/
800 greyscale[((j+2)*width)+i+1] += (error * 2)/42;
801 if (i+2 < width) /*--- G [j+2] [i+2] ---*/
802 greyscale[((j+2)*width)+i+2] += error/42;
806 XPutPixel(image, i, j, whitePixel);
808 XPutPixel(image, i, j, blackPixel);
820 enum _DtGrColorModel force,
823 unsigned long **ret_colors,
826 register int i, x, y, colorCount = 0;
827 register XColor *color;
831 for (i = 0; i < ncolors; i++)
839 * It is set to one upon entering this routine.
840 * The only way it can be modified is by the call to XAllocColor.
842 if (force == _DtGrCOLOR)
845 for (y = 0; result && y < in_image->height; y++)
847 for (x = 0; result && x < in_image->width; x++)
849 pixel = XGetPixel(in_image, x, y);
850 color = &colors[pixel];
853 color->flags = DoRed | DoGreen | DoBlue;
854 result = XAllocColor(dpy, colormap, color);
861 XPutPixel(out_image, x, y, color->pixel);
866 * If result == 0, a call to XAllocColor failed
867 * Try to grey scale the image.
873 for (i = 0; i < ncolors; i++)
877 XFreeColors (dpy, colormap, &(colors[i].pixel), 1, 0);
882 result = GreyScale (dpy, screen, colormap, in_image, out_image, colors,
883 ncolors, force, 0, 0, 0, 0, 0, 0);
888 *ret_colors = (unsigned long *) malloc (
889 sizeof (unsigned long) * colorCount);
890 if (*ret_colors == NULL)
893 result = GR_ALLOC_ERR;
896 for (i = 0, x = 0; i < ncolors && x < colorCount; i++)
898 (*ret_colors)[x++] = colors[i].pixel;
900 *ret_number = colorCount;
904 * result was set to a XHPIF value via the 'else' stmt or
905 * returned from GreyScale routine.
914 XWDFileHeader *header,
918 enum _DtGrColorModel force,
921 unsigned long **ret_colors,
926 unsigned long rmask, gmask, bmask;
927 int rshift = 0, gshift = 0, bshift = 0;
936 oldPixels = (Pixel *) malloc (sizeof (Pixel) * pixMax);
937 newPixels = (Pixel *) malloc (sizeof (Pixel) * pixMax);
939 if (oldPixels == NULL || newPixels == NULL)
949 rmask = header->red_mask;
950 while (!(rmask & 1)) {
954 gmask = header->green_mask;
955 while (!(gmask & 1)) {
959 bmask = header->blue_mask;
960 while (!(bmask & 1)) {
964 if (in_image->depth <= 12)
965 pix = 1 << in_image->depth;
967 if (force == _DtGrCOLOR)
968 color.flags = DoRed | DoGreen | DoBlue;
972 for (y = 0; color.flags && y < in_image->height; y++)
974 for (x = 0; color.flags && x < in_image->width; x++)
976 pix = XGetPixel(in_image, x, y);
979 while (i < pixI && oldPixels[i] != pix)
984 color.red = (pix >> rshift) & rmask;
985 color.green = (pix >> gshift) & gmask;
986 color.blue = (pix >> bshift) & bmask;
988 color.red = colors[color.red].red;
989 color.green = colors[color.green].green;
990 color.blue = colors[color.blue].blue;
992 color.red = ((unsigned long)color.red * 65535) / rmask;
993 color.green = ((unsigned long)color.green * 65535) / gmask;
994 color.blue = ((unsigned long)color.blue * 65535) / bmask;
996 if (!XAllocColor(dpy, colormap, &color))
1003 oldPixels = (Pixel *) realloc ((void *) oldPixels,
1004 (sizeof (Pixel) * pixMax));
1005 newPixels = (Pixel *) realloc ((void *) newPixels,
1006 (sizeof (Pixel) * pixMax));
1011 if (oldPixels == NULL || newPixels == NULL)
1018 XFreeColors(dpy, colormap, newPixels, pixI, 0);
1022 return GR_ALLOC_ERR;
1025 oldPixels[pixI] = pix;
1026 newPixels[pixI++] = color.pixel;
1030 XPutPixel(out_image, x, y, newPixels[i]);
1035 result = GR_SUCCESS;
1038 newPixels = (Pixel *) realloc ((void *) newPixels,
1039 (sizeof (Pixel) * pixI));
1040 if (newPixels == NULL)
1041 result = GR_ALLOC_ERR;
1046 *ret_colors = newPixels;
1052 XFreeColors (dpy, colormap, newPixels, pixI, 0);
1057 result = GreyScale(dpy, screen, colormap, in_image, out_image, colors,
1058 ncolors, force, rshift, gshift, bshift, rmask, gmask, bmask);
1068 if (image->format != ZPixmap)
1069 return(image->bytes_per_line * image->height * image->depth);
1071 return((unsigned)image->bytes_per_line * image->height);
1083 enum _DtGrColorModel color_model,
1090 _DtGrStream *stream,
1091 unsigned long **ret_colors,
1096 XImage in_image, *out_image;
1097 register char *buffer;
1098 unsigned long swaptest = 1;
1100 unsigned buffer_size;
1102 Bool rawbits = False;
1103 XColor *colors = NULL;
1105 /* Use a different structure for compatibility with 32-bit platform */
1107 #endif /* __alpha */
1108 XWDFileHeader header;
1110 /* Reset the pointer to the beginning of the stream */
1111 _DtGrSeek(stream, 0, SEEK_SET);
1114 * Read in header information.
1116 if(_DtGrRead((char *)&header, sizeof(header), 1, stream) != 1)
1118 return GR_HEADER_ERR;
1121 if (*(char *) &swaptest)
1122 _swaplong((char *) &header, sizeof(header));
1124 /* check to see if the dump file is in the proper format */
1125 if (header.file_version != XWD_FILE_VERSION)
1127 return GR_HEADER_ERR;
1130 if (header.header_size < sizeof(header))
1132 return GR_HEADER_ERR;
1136 * skip the window name
1138 if (_DtGrSeek(stream, (header.header_size - sizeof(header)), 1))
1144 * initialize the input image
1146 in_image.width = (int) header.pixmap_width;
1147 in_image.height = (int) header.pixmap_height;
1148 in_image.xoffset = (int) header.xoffset;
1149 in_image.format = (int) header.pixmap_format;
1150 in_image.byte_order = (int) header.byte_order;
1151 in_image.bitmap_unit = (int) header.bitmap_unit;
1152 in_image.bitmap_bit_order = (int) header.bitmap_bit_order;
1153 in_image.bitmap_pad = (int) header.bitmap_pad;
1154 in_image.depth = (int) header.pixmap_depth;
1155 in_image.bits_per_pixel = (int) header.bits_per_pixel;
1156 in_image.bytes_per_line = (int) header.bytes_per_line;
1157 in_image.red_mask = header.red_mask;
1158 in_image.green_mask = header.green_mask;
1159 in_image.blue_mask = header.blue_mask;
1160 in_image.obdata = NULL;
1161 _XInitImageFuncPtrs(&in_image);
1163 /* read in the color map buffer */
1164 ncolors = header.ncolors;
1166 colors = (XColor *)malloc((unsigned) ncolors * sizeof(XColor));
1169 return GR_ALLOC_ERR;
1173 /* Use XWDColor instead of XColor. Byte-swapping if it is necessary.
1174 * Move values back into Xcolor structure.
1176 for (i = 0; i < ncolors; i++) {
1177 if (_DtGrRead( (char *) &xwd_color, sizeof(XWDColor), 1 , stream) != 1 )
1179 XFree ((char *) colors);
1183 if (*(char *) &swaptest) {
1184 _swaplong((char *) &xwd_color.pixel, sizeof(xwd_color.pixel));
1185 _swapshort((char *) &xwd_color.red, 3 * sizeof(xwd_color.red));
1188 colors[i].pixel = xwd_color.pixel;
1189 colors[i].red = xwd_color.red;
1190 colors[i].green = xwd_color.green;
1191 colors[i].blue = xwd_color.blue;
1192 colors[i].flags = xwd_color.flags;
1195 if(_DtGrRead((char *) colors, sizeof(XColor), ncolors, stream) != ncolors)
1197 XFree ((char *) colors);
1201 if (*(char *) &swaptest) {
1202 for (i = 0; i < ncolors; i++) {
1203 _swaplong((char *) &colors[i].pixel, sizeof(long));
1204 _swapshort((char *) &colors[i].red, 3 * sizeof(short));
1207 #endif /* __alpha */
1211 * alloc the pixel buffer
1213 buffer_size = Image_Size(&in_image);
1214 buffer = (char *) malloc(buffer_size);
1218 XFree ((char *) colors);
1219 return GR_ALLOC_ERR;
1222 /* read in the image data */
1223 count = _DtGrRead(buffer, sizeof(char), (int)buffer_size, stream);
1225 if (count != buffer_size)
1228 XFree ((char *) colors);
1233 if (in_image.depth == 1) {
1234 in_image.format = XYBitmap;
1237 in_image.data = buffer;
1239 /* create the output image */
1240 result = GR_SUCCESS;
1243 out_image = &in_image;
1245 out_image = XCreateImage(dpy, visual, depth,
1246 (depth == 1) ? XYBitmap : in_image.format,
1247 in_image.xoffset, NULL,
1248 in_image.width, in_image.height,
1249 XBitmapPad(dpy), 0);
1251 out_image->data = (char *) malloc(Image_Size(out_image));
1253 if ((header.visual_class == TrueColor) ||
1254 (header.visual_class == DirectColor))
1255 result = Do_Direct(dpy, screen, &header, colormap, ncolors, colors,
1257 &in_image, out_image, ret_colors, ret_number);
1259 result = Do_Pseudo(dpy, screen, colormap, ncolors, colors, color_model,
1260 &in_image, out_image, ret_colors, ret_number);
1263 if (result != GR_ALLOC_ERR)
1265 _XmPutScaledImage(dpy, pixmap, gc, out_image,
1266 src_x, src_y, dst_x, dst_y,
1267 in_image.width, in_image.height,
1274 XFree ((char *) colors);
1277 XDestroyImage (out_image);
1282 /*****************************************************************************/
1283 /* General functions for changing a file into a pixmap */
1285 /*****************************************************************************/
1288 * Function processBitmap
1291 * Make a bitmap into the pixmap for the graphic.
1294 static enum _DtGrLoadStatus processBitmap(
1295 _DtGrStream *stream,
1303 enum _DtGrColorModel color_model,
1304 Boolean allow_reduced_colors,
1305 Dimension *in_out_width,
1306 Dimension *in_out_height,
1307 unsigned short media_resolution,
1311 int *ret_num_colors,
1312 _DtGrContext *context
1317 unsigned int width, height;
1318 unsigned char *data;
1319 Pixmap scaled_pixmap = 0;
1320 Display *dpy = DisplayOfScreen(screen);
1321 Drawable drawable = RootWindowOfScreen(screen);
1325 if (media_resolution == 0)
1326 return(_DtGrCONVERT_FAILURE);
1328 if (*in_out_width == 0 && *in_out_height == 0)
1329 ratio = ComputeRatio(media_resolution, 100);
1331 if (stream->type == _DtGrNONE)
1332 return(_DtGrCONVERT_FAILURE);
1334 result = _DtGrReadBitmapStreamData (stream,
1335 &width, &height, &data, &junk, &junk);
1337 /* Be sure to implement XvpCopyPlane later */
1338 if (result == BitmapSuccess)
1340 ximage.height = height;
1341 ximage.width = width;
1343 ximage.bits_per_pixel = 1;
1345 ximage.format = XYBitmap;
1346 ximage.data = (char *)data;
1347 ximage.byte_order = LSBFirst;
1348 ximage.bitmap_unit = 8;
1349 ximage.bitmap_bit_order = LSBFirst;
1350 ximage.bitmap_pad = 8;
1351 ximage.bytes_per_line = (width+7)/8;
1352 XInitImage(&ximage);
1354 *in_out_width = (Dimension) width * ratio + 0.5;
1355 *in_out_height = (Dimension) height * ratio + 0.5;
1356 if (*in_out_width == 0)
1358 if (*in_out_height == 0)
1361 scaled_pixmap = XCreatePixmap (dpy, drawable, (*in_out_width),
1362 (*in_out_height), depth);
1363 _XmPutScaledImage(dpy, scaled_pixmap, gc, &ximage,0, 0, 0, 0,
1364 width,height,(*in_out_width),(*in_out_height));
1365 XFree((char *)data);
1366 *ret_pixmap = scaled_pixmap;
1369 if (result == BitmapSuccess)
1370 return(_DtGrSUCCESS);
1371 else if (result == BitmapOpenFailed)
1372 return(_DtGrOPEN_FAILED);
1373 else if (result == BitmapFileInvalid)
1374 return(_DtGrFILE_INVALID);
1375 else if (result == BitmapNoMemory)
1376 return(_DtGrNO_MEMORY);
1378 return(_DtGrCONVERT_FAILURE);
1384 * Function processTiff
1387 * Make a tiff into the pixmap for the graphic.
1390 static enum _DtGrLoadStatus processTiff(
1391 _DtGrStream *stream,
1399 enum _DtGrColorModel color_model,
1400 Boolean allow_reduced_colors,
1401 Dimension *in_out_width,
1402 Dimension *in_out_height,
1403 unsigned short media_resolution,
1407 int *ret_num_colors,
1408 _DtGrContext *context
1415 ilFileImage inImage;
1416 const ilImageDes *inDes;
1417 static ilContext IlContext = NULL;
1418 Display *dpy = DisplayOfScreen(screen);
1419 Drawable drawable = RootWindowOfScreen(screen);
1423 _DtHelpProcessLock();
1424 if ((context == NULL) || (stream->type == _DtGrNONE))
1426 _DtHelpProcessUnlock();
1427 return (_DtGrCONVERT_FAILURE);
1430 if (media_resolution == 0)
1432 _DtHelpProcessUnlock();
1433 return(_DtGrCONVERT_FAILURE);
1436 tiff_xwc = (ilXWC *) &(context->context);
1437 if (IlContext == NULL)
1439 if (IL_CREATE_CONTEXT (&IlContext, 0))
1442 _DtHelpProcessUnlock();
1443 return (_DtGrCONVERT_FAILURE);
1447 if (*tiff_xwc == NULL)
1449 /* Fill in the context record fields */
1450 *tiff_xwc = ilCreateXWC (IlContext, dpy, visual, colormap, gc, 0, 0);
1451 if (*tiff_xwc == NULL)
1453 _DtHelpProcessUnlock();
1454 return(_DtGrCONVERT_FAILURE);
1456 context->image_type = XtNewString("TIFF");
1459 inFile = ilConnectFile (IlContext, stream, 0, 0);
1462 inImage = ilListFileImages (inFile, 0);
1465 int image_resolution = 100 ; /* assume that if not in file */
1468 if (inImage->xRes != 0) {
1469 image_resolution = inImage->xRes ; /* dpi from the file */
1472 if (*in_out_width == 0 && *in_out_height == 0)
1473 ratio = ComputeRatio(media_resolution, image_resolution);
1475 *in_out_width = inImage->width * ratio + 0.5;
1476 *in_out_height = inImage->height * ratio + 0.5;
1477 if (*in_out_width == 0)
1479 if (*in_out_height == 0)
1482 pixmap = XCreatePixmap (dpy, drawable, (*in_out_width),
1483 (*in_out_height), depth);
1486 inPipe = ilCreatePipe (IlContext, 0);
1489 if (color_model == _DtGrGRAY_SCALE)
1490 inDes = IL_DES_GRAY;
1491 else if (color_model == _DtGrBITONAL)
1492 inDes = IL_DES_BITONAL;
1495 if (!ilReadFileImage (inPipe, inImage, (ilRect *) NULL, 0))
1498 if (result == 0 && color_model != _DtGrCOLOR &&
1499 ilConvert (inPipe, inDes, ((ilImageFormat *) NULL), 0, NULL) != True)
1503 ilWriteXDrawable (inPipe, pixmap, *tiff_xwc,
1504 (ilRect *) NULL, 0, 0, 0))
1506 ilExecutePipe (inPipe, 0, ratio);
1507 if (IlContext->error != 0)
1510 ilDestroyObject (inPipe);
1514 XFreePixmap (dpy, pixmap);
1519 ilDestroyObject (inFile);
1522 *ret_pixmap = pixmap;
1525 if ((IlContext->error == IL_ERROR_FILE_IO) ||
1526 (IlContext->error == IL_ERROR_FILE_NOT_TIFF))
1528 _DtHelpProcessUnlock();
1529 return(_DtGrFILE_INVALID);
1531 else if (IlContext->error == IL_ERROR_MALLOC)
1533 _DtHelpProcessUnlock();
1534 return(_DtGrNO_MEMORY);
1538 _DtHelpProcessUnlock();
1539 return(_DtGrCONVERT_FAILURE);
1544 _DtHelpProcessUnlock();
1545 return(_DtGrSUCCESS);
1552 * Function processXwd
1555 * Make an XWD file into the pixmap for the graphic.
1558 static enum _DtGrLoadStatus processXwd(
1559 _DtGrStream *stream,
1567 enum _DtGrColorModel color_model,
1568 Boolean allow_reduced_colors,
1569 Dimension *in_out_width,
1570 Dimension *in_out_height,
1571 unsigned short media_resolution,
1575 int *ret_num_colors,
1576 _DtGrContext *context
1580 XWDFileHeader header;
1582 unsigned long swaptest = TRUE;
1583 Display *dpy = DisplayOfScreen(screen);
1584 Drawable drawable = RootWindowOfScreen(screen);
1585 int screen_num = XScreenNumberOfScreen(screen);
1588 if (media_resolution == 0)
1589 return(_DtGrCONVERT_FAILURE);
1591 if (stream->type == _DtGrNONE)
1592 return(_DtGrCONVERT_FAILURE);
1594 /* Read in XWDFileHeader structure */
1595 result = _DtGrRead((char *)&header, sizeof(header), 1, stream);
1597 if (result == 1 && *(char *) &swaptest)
1598 _swaplong((char *) &header, sizeof(header));
1600 if (result != 1 || header.file_version != XWD_FILE_VERSION)
1601 return (_DtGrFILE_INVALID);
1603 if (*in_out_width == 0 && *in_out_height == 0)
1604 ratio = ComputeRatio(media_resolution, 100);
1606 *in_out_width = header.pixmap_width * ratio + 0.5;
1607 *in_out_height = header.pixmap_height * ratio + 0.5;
1609 if (*in_out_width == 0)
1611 if (*in_out_height == 0)
1614 pixmap = XCreatePixmap (dpy, drawable, (*in_out_width),
1615 (*in_out_height),depth);
1618 if ((result=XwdFileToPixmap (dpy, screen_num, depth, pixmap, colormap,
1619 visual, gc, color_model, 0, 0, 0, 0,
1620 (*in_out_width), (*in_out_height), stream,
1621 ret_colors, ret_num_colors))
1623 *ret_pixmap = pixmap;
1624 return (_DtGrSUCCESS);
1626 else if (result == GR_HEADER_ERR)
1627 return (_DtGrFILE_INVALID);
1628 else if (result == GR_FILE_ERR)
1629 return (_DtGrFILE_INVALID);
1630 else if (result == GR_ALLOC_ERR)
1631 return (_DtGrNO_MEMORY);
1633 return (_DtGrCONVERT_FAILURE);
1636 return (_DtGrNO_MEMORY);
1639 /************************************
1640 * myXpmReadFileToPixmap
1641 ***********************************/
1643 myXpmReadFileToPixmap(
1647 _DtGrStream *stream,
1648 Pixmap *pixmap_return,
1649 Pixmap *shapemask_return,
1650 XpmAttributes *attributes,
1658 XImage *image = NULL;
1659 XImage **imageptr = 0;
1660 XImage *shapeimage, **shapeimageptr = NULL;
1663 int scaledWidth, scaledHeight;
1665 * initialize return values
1668 if (pixmap_return) {
1672 if (shapemask_return) {
1673 *shapemask_return = 0;
1674 shapeimageptr = &shapeimage;
1681 if (stream->type == _DtGrFILE)
1683 if (stream->source.file.uncompressed_filename != NULL)
1684 ErrorStatus = _DtXpmReadFileToImage(display,
1685 stream->source.file.uncompressed_filename,
1686 imageptr, shapeimageptr, attributes);
1688 ErrorStatus = _DtXpmReadFileToImage(display,
1689 stream->source.file.filename,
1690 imageptr, shapeimageptr, attributes);
1692 else if (stream->type == _DtGrBUFFER)
1694 ErrorStatus = XpmCreateImageFromBuffer(display,
1695 (char *) stream->source.buffer.base,
1696 imageptr, shapeimageptr, attributes);
1699 ErrorStatus = XpmFileInvalid; /* stream type of _DtGrNONE */
1701 if (ErrorStatus < 0)
1702 return (ErrorStatus);
1705 * Check to see if we will need to switch the foreground and
1706 * background colors. When forced to a depth of 1, the Xpm call
1707 * returns a ZPixmap ready to place in pixmap of depth 1.
1708 * Unfortunately, usually the pixmap is of a different depth. This
1709 * causes a depth mismatch for the XPutImage. Therefore, we change
1710 * the format type to XYBitmap and XPutImage is happy. But on
1711 * servers where BlackPixel is not at pixel 1 in the colormap, this
1712 * causes the image to be inverted. So by switching the foreground
1713 * and background in the gc, the image is corrected for these
1716 * The other way of doing this, is to create a pixmap of depth 1 and
1717 * do an XPutImage to it. Then do a XCopyPlane to a pixmap of the
1718 * correct depth. But this is a major performance hit compared to
1719 * switching the colors.
1721 * The downside of switching colors is that it works only when
1722 * BlackPixel and WhitePixel fill colormap entries 0 and 1. But
1723 * since this is the 99.9% case, we'll go with it.
1725 if (image->depth == 1 && BlackPixelOfScreen(screen) != 1L)
1729 * create the pixmaps
1731 if (imageptr && image) {
1732 scaledWidth = image->width * ratio + 0.5;
1733 scaledHeight = image->height * ratio + 0.5;
1735 if (scaledWidth == 0)
1737 if (scaledHeight == 0)
1740 *pixmap_return = XCreatePixmap(display, d, scaledWidth,
1741 scaledHeight, depth);
1742 if (image->depth == 1)
1743 image->format = XYBitmap;
1747 XSetBackground (display, gc, fg);
1748 XSetForeground (display, gc, bg);
1750 _XmPutScaledImage(display, *pixmap_return, gc, image,
1752 image->width, image->height,
1753 scaledWidth, scaledHeight);
1756 XSetBackground (display, gc, bg);
1757 XSetForeground (display, gc, fg);
1760 XDestroyImage(image);
1763 if (shapeimageptr && shapeimage)
1764 XDestroyImage(shapeimage);
1766 return (ErrorStatus);
1769 static XpmColorSymbol colorSymbol = {"none", NULL, 0};
1773 * Function processXpm
1776 * Make an XPM file into the pixmap for the graphic.
1780 static enum _DtGrLoadStatus processXpm(
1781 _DtGrStream *stream,
1789 enum _DtGrColorModel color_model,
1790 Boolean allow_reduced_colors,
1791 Dimension *in_out_width,
1792 Dimension *in_out_height,
1793 unsigned short media_resolution,
1797 int *ret_num_colors,
1798 _DtGrContext *context
1804 XpmAttributes xpmAttr;
1808 enum _DtGrLoadStatus status = _DtGrSUCCESS;
1810 if (media_resolution == 0)
1811 return(_DtGrCONVERT_FAILURE);
1813 if (stream->type == _DtGrNONE)
1814 return(_DtGrCONVERT_FAILURE); /* stream type of _DtGrNONE */
1817 _DtHelpProcessLock();
1820 colorSymbol.pixel = background;
1822 xpmAttr.valuemask = XpmVisual | XpmReturnPixels |
1823 XpmColorSymbols | XpmColormap | XpmDepth;
1824 xpmAttr.visual = visual;
1825 xpmAttr.colorsymbols = &colorSymbol;
1826 xpmAttr.colormap = colormap;
1827 xpmAttr.numsymbols = 1;
1828 xpmAttr.depth = depth;
1829 xpmAttr.pixels = NULL;
1832 * If not color, force to black and white.
1834 if (color_model != _DtGrCOLOR)
1836 memcpy (&vis2, xpmAttr.visual, sizeof(Visual));
1838 vis2.class = StaticGray;
1839 vis2.map_entries = 2;
1842 xpmAttr.visual = &vis2;
1844 if (*in_out_width == 0 && *in_out_height == 0)
1845 ratio = ComputeRatio(media_resolution, 100);
1847 result = myXpmReadFileToPixmap (DisplayOfScreen(screen),
1849 RootWindowOfScreen(screen),
1851 ret_mask, &xpmAttr, gc,
1852 background, foreground, depth,
1856 * if we did not successfully get our icon, force the color
1857 * to black and white.
1859 if (result == XpmColorFailed && color_model != _DtGrBITONAL)
1861 if (allow_reduced_colors)
1863 color_model = _DtGrBITONAL;
1864 status = _DtGrCOLOR_REDUCE;
1868 status = _DtGrCOLOR_FAILED;
1871 } while (done == False);
1873 if (result == XpmSuccess || result == XpmColorError)
1875 *in_out_width = xpmAttr.width * ratio + 0.5;
1876 *in_out_height = xpmAttr.height * ratio + 0.5;
1877 if (*in_out_width == 0)
1879 if (*in_out_height == 0)
1881 *ret_colors = xpmAttr.pixels;
1882 *ret_num_colors = xpmAttr.npixels;
1885 * squeeze out the pixel used for the transparent color since we
1886 * don't want to free it when we free the other colors
1889 while (i < xpmAttr.npixels && xpmAttr.pixels[i] != colorSymbol.pixel)
1892 if (i < xpmAttr.npixels)
1894 for (j = i, i = i + 1; i < xpmAttr.npixels; i++, j++)
1895 xpmAttr.pixels[j] = xpmAttr.pixels[i];
1897 *ret_num_colors = j;
1900 _DtHelpProcessUnlock();
1902 if (result == XpmOpenFailed)
1903 status = _DtGrOPEN_FAILED;
1904 else if (result == XpmFileInvalid)
1905 status = _DtGrFILE_INVALID;
1906 else if (result == XpmNoMemory)
1907 status = _DtGrNO_MEMORY;
1908 else if (result == XpmColorFailed)
1909 status = _DtGrCOLOR_FAILED;
1914 /******************************************************************************
1916 * Function processGIF
1918 * Default gif converter, creates a pixmap from a file-associated or
1919 * buffer-associated stream of gif data.
1921 *****************************************************************************/
1922 static enum _DtGrLoadStatus processGIF(
1923 _DtGrStream *stream,
1931 enum _DtGrColorModel color_model,
1932 Boolean allow_reduced_colors,
1933 Dimension *in_out_width,
1934 Dimension *in_out_height,
1935 unsigned short media_resolution,
1939 int *ret_num_colors,
1940 _DtGrContext *context
1946 enum _DtGrLoadStatus status;
1947 Display *display = DisplayOfScreen(screen);
1948 Drawable drawable = RootWindowOfScreen(screen);
1952 if (media_resolution == 0)
1953 return(_DtGrCONVERT_FAILURE);
1955 if (stream->type == _DtGrNONE)
1956 return(_DtGrCONVERT_FAILURE); /* stream type of _DtGrNONE */
1958 *ret_pixmap = 0; /* Initialize the return pixmap to zero */
1961 ** The gif-to-pixmap utilities operate only on in-memory buffers,
1962 ** so if this is a buffer-based stream, simply pass the buffer, and
1963 ** if this is a file-based stream, read the file contents into a buffer
1967 if (stream->type == _DtGrBUFFER)
1969 buffer = (char *) stream->source.buffer.base;
1970 size = stream->source.buffer.size;
1974 if (stream->source.file.uncompressed_filename != NULL)
1975 stat (stream->source.file.uncompressed_filename, &stbuf);
1977 stat (stream->source.file.filename, &stbuf);
1978 size = stbuf.st_size;
1979 buffer = XtMalloc(size);
1980 fread (buffer, 1, size, stream->source.file.fileptr);
1983 /* Initialize the gif object */
1984 status = InitGifObject (&g, display, drawable, screen, depth, colormap,
1985 visual, gc, color_model, allow_reduced_colors);
1987 if (*in_out_width == 0 && *in_out_height == 0)
1988 ratio = ComputeRatio(media_resolution, 100);
1990 /* Create an X pixmap from the gif object */
1991 if ((status == _DtGrSUCCESS) || (status == _DtGrCOLOR_REDUCE))
1992 *ret_pixmap = gif_to_pixmap (&g, (unsigned char *) buffer, size,
1993 in_out_width, in_out_height,
1994 g.f_black, g.f_white, ratio);
1996 /* Set the returned colors parameters */
1997 if (*ret_pixmap != 0)
1999 if (g.f_do_visual == DO_COLOR)
2001 *ret_num_colors = g.total_colors;
2002 *ret_colors = (Pixel *) malloc(*ret_num_colors * sizeof(Pixel));
2003 for (i=0; i<*ret_num_colors; i++)
2004 (*ret_colors)[i] = g.GifCMap[i].pixel;
2008 *ret_num_colors = g.f_total_greys;
2009 *ret_colors = (Pixel *) malloc(*ret_num_colors * sizeof(Pixel));
2010 for (i=0; i<*ret_num_colors; i++)
2011 (*ret_colors)[i] = g.GifGMap[i];
2015 /* Free up any resources associated with the gif object */
2016 DeleteGifObjectResources (&g);
2018 /* If we allocated a buffer, free it */
2019 if (stream->type == _DtGrFILE)
2022 /* Return the status */
2026 /******************************************************************************
2028 * Function processJPEG
2030 * Default jpeg converter, creates a pixmap from a file-associated or
2031 * buffer-associated stream of jpeg data.
2033 * The function first converts the jpeg stream to an XImage with a virtual
2034 * colormap using the jpeg_to_ximage call, then generates a new XImage that
2035 * uses the X colormap by calling the Do_Pseudo routine. The Do_Pseudo
2036 * routine, which is also used by the XWD converter, automatically handles X
2037 * color allocation and color model degradation where necessary. Finally,
2038 * a pixmap is generated from the XImage returned by Do_Pseudo.
2040 *****************************************************************************/
2041 static enum _DtGrLoadStatus processJPEG(
2042 _DtGrStream *stream,
2050 enum _DtGrColorModel color_model,
2051 Boolean allow_reduced_colors,
2052 Dimension *in_out_width,
2053 Dimension *in_out_height,
2054 unsigned short media_resolution,
2058 int *ret_num_colors,
2059 _DtGrContext *context
2062 enum _DtGrLoadStatus status;
2063 XImage *in_image, *out_image;
2067 int result = GR_SUCCESS;
2068 Display *dpy = DisplayOfScreen(screen);
2069 int screen_num = XScreenNumberOfScreen(screen);
2070 Drawable drawable = RootWindowOfScreen(screen);
2072 unsigned int scaledWidth,scaledHeight;
2074 if (media_resolution == 0)
2075 return(_DtGrCONVERT_FAILURE);
2077 if (*in_out_width == 0 && *in_out_height == 0)
2080 if (stream->type == _DtGrNONE)
2081 return(_DtGrCONVERT_FAILURE); /* stream type of _DtGrNONE */
2084 ** Convert the stream to an XImage with a virtual colormap
2086 status = jpeg_to_ximage (stream, screen, visual, in_out_width,
2087 in_out_height, &in_image, &colors, &ncolors,
2093 ratio = ComputeRatio(media_resolution, xres);
2096 if (status == _DtGrSUCCESS)
2098 if (in_image->depth == 1)
2101 ** Bitmap, no further image transformation necessary
2103 out_image = in_image;
2104 result = GR_SUCCESS;
2109 ** Create an output image and have Do_Pseudo allocate the needed
2110 ** pixels and store image data that uses these pixels into
2111 ** the output image.
2113 out_image = XCreateImage(dpy, visual, depth,
2114 (depth == 1) ? XYBitmap : in_image->format,
2115 in_image->xoffset, NULL,
2116 in_image->width, in_image->height,
2117 XBitmapPad(dpy), 0);
2119 out_image->data = (char *) malloc(Image_Size(out_image));
2121 result = Do_Pseudo(dpy, screen_num, colormap, ncolors, colors,
2122 color_model, in_image, out_image,
2123 ret_colors, ret_num_colors);
2127 ** If we've got a good XImage, go ahead and make a pixmap out of it
2129 if (result != GR_ALLOC_ERR)
2132 ** Create a pixmap the same size as the XImage
2135 scaledWidth = out_image->width * ratio + 0.5;
2136 scaledHeight = out_image->height * ratio + 0.5;
2138 if (scaledWidth == 0)
2140 if (scaledHeight == 0)
2143 *ret_pixmap = XCreatePixmap (dpy, drawable, scaledWidth,
2144 scaledHeight, depth);
2148 ** Copy the XImage into the pixmap and set the other
2149 ** return parameters.
2151 _XmPutScaledImage(dpy, *ret_pixmap, gc, out_image, 0, 0, 0, 0,
2152 out_image->width, out_image->height,
2153 scaledWidth, scaledHeight);
2155 *in_out_width = scaledWidth;
2156 *in_out_height = scaledHeight;
2157 status = _DtGrSUCCESS;
2160 status = _DtGrNO_MEMORY;
2162 if (out_image != in_image)
2163 XDestroyImage (out_image);
2166 status = _DtGrNO_MEMORY;
2169 ** Free the colors array and the initial XImage
2171 XFree ((char *) colors);
2172 XDestroyImage (in_image);
2178 /******************************************************************************
2180 * Function destroyTiffContext
2182 * Default tiff context destructor, destroys the ilXWC object pointed to
2183 * by context->context and frees the context->image_type string.
2185 *****************************************************************************/
2186 static void destroyTiffContext(
2187 _DtGrContext *context)
2189 if (context != NULL)
2191 if (context->context != NULL)
2193 _DtHelpProcessLock();
2194 ilDestroyObject ((ilObject) context->context);
2195 _DtHelpProcessUnlock();
2197 if (context->image_type != NULL)
2198 XtFree(context->image_type);
2202 /******************************************************************************
2204 * Function DetermineImageType
2206 * Determines the image type of the specified stream and copies the
2207 * string representing that image type into the image_type buffer.
2209 * If the stream is a buffer, the buffer is passed to DtDtsBufferToData
2210 * in hopes that the file might be identified through content criteria.
2212 * If the stream is a file, the following checks are made:
2214 * 1. The file name extension is checked against a list of known image file
2216 * 2. The filename is passed to DtDtsFileToDataType in hopes that the file
2217 * type might be identified through filename extension or content
2219 * 3. If the file was uncompressed into a temporary file, the temporary
2220 * filename is passed to DtDtsFileToDataType in hopes that the file
2221 * type might be identified through content criteria.
2223 * If none of these checks are successful, _DtCONVERT_FAILURE is returned.
2224 * Otherwise, _DtGrSUCCESS is returned.
2226 *****************************************************************************/
2227 static enum _DtGrLoadStatus DetermineImageType(
2228 _DtGrStream *stream,
2234 if (stream->type == _DtGrFILE)
2236 /* First try to match the file name extension to a known mapping */
2237 if (stream->source.file.filename != NULL)
2239 /* Get the filename extension */
2240 if (_DtHelpCeStrrchr(stream->source.file.filename, ".",
2241 MB_CUR_MAX, &ext) == 0)
2243 ext++; /* Increment past the dot */
2244 while (img_extensions[i] != NULL)
2246 if (strcmp(ext, img_extensions[i]) == 0)
2249 strcpy (image_type,img_extensions[++i]);
2250 return (_DtGrSUCCESS);
2252 /* Skip two ahead to the next file extension name */
2259 * Didn't work, see if CDE datatyping can determine the image type.
2260 * First try the filename, then try the uncompressed temporary
2261 * filename, if it exists.
2263 if ((ext = DtDtsFileToDataType(stream->source.file.filename)) == NULL)
2264 if (stream->source.file.uncompressed_filename != NULL)
2265 ext = DtDtsFileToDataType(
2266 stream->source.file.uncompressed_filename);
2268 /* If successful, save the image type and return */
2271 strcpy (image_type, ext);
2272 DtDtsFreeDataType(ext);
2273 return (_DtGrSUCCESS);
2276 else if (stream->type == _DtGrBUFFER)
2278 /* See if the CDE datatyping mechanism can determine the image type */
2279 ext = DtDtsBufferToDataType (stream->source.buffer.base,
2280 stream->source.buffer.size,
2283 /* If successful, save the image type and return */
2286 strcpy (image_type, ext);
2287 DtDtsFreeDataType(ext);
2288 return (_DtGrSUCCESS);
2292 /* Couldn't figure out the type, return failure */
2293 return (_DtGrCONVERT_FAILURE);
2296 /******************************************************************************
2298 * Function GetConverterAndDestructor
2300 * This function returns the converter and context destructor functions for
2301 * the specified image type. The registry of default image types is searched
2302 * first, followed by the registry of new image types, until a match is made.
2303 * The function returns _DtGrSUCCESS if the image_type has been registered
2304 * and _DtGrCONVERT_FAILURE if it has not.
2306 *****************************************************************************/
2307 static enum _DtGrLoadStatus GetConverterAndDestructor(
2309 _DtGrLoadProc *converter,
2310 _DtGrDestroyContextProc *destructor)
2314 /* No image_type string, return failure */
2315 if (image_type == NULL)
2316 return (_DtGrCONVERT_FAILURE);
2318 /* Search the default image type registry for the specified image type */
2319 _DtHelpProcessLock();
2320 for (i=0; i<registry_count; i++)
2322 if (strcmp (registry[i].image_type, image_type) == 0)
2324 /* Found it, return the converter and destructor */
2325 *converter = registry[i].convert_proc;
2326 *destructor = registry[i].destroy_context_proc;
2327 _DtHelpProcessUnlock();
2328 return (_DtGrSUCCESS);
2332 /* Search the new image type registry for the specified image type */
2333 for (i=0; i<new_registry_count; i++)
2335 if (strcmp (new_registry[i].image_type, image_type) == 0)
2337 /* Found it, return the converter */
2338 *converter = new_registry[i].convert_proc;
2339 *destructor = registry[i].destroy_context_proc;
2340 _DtHelpProcessUnlock();
2341 return (_DtGrSUCCESS);
2344 _DtHelpProcessUnlock();
2346 /* Image type wasn't registered, return failure */
2347 return (_DtGrCONVERT_FAILURE);
2350 /******************************************************************************
2354 *****************************************************************************/
2355 /******************************************************************************
2357 * Function _DtHelpProcessGraphic
2360 * Get the pixmap for the graphic.
2362 *****************************************************************************/
2364 _DtHelpProcessGraphic(
2371 Dimension *def_pix_width,
2372 Dimension *def_pix_height,
2373 _DtGrContext *context,
2379 unsigned short media_resolution,
2387 unsigned int pixWidth = 0;
2388 unsigned int pixHeight = 0;
2389 Dimension pWidth, pHeight;
2390 Pixmap pix = 0, mask = 0;
2392 Screen *scrptr = ScreenOfDisplay (dpy, screen);
2393 static enum _DtGrColorModel ForceColor = _DtGrCOLOR;
2394 static Boolean first_time = TRUE;
2397 * initialize the return values
2404 * Initialize the Force Variable if this is the first time
2406 _DtHelpProcessLock();
2411 char *xrmName = NULL;
2412 char *xrmClass = NULL;
2416 ForceColor = _DtGrCOLOR;
2418 XtGetApplicationNameAndClass (dpy, &ptr, &ptr2);
2419 xrmName = malloc (strlen (ptr) + 14);
2420 xrmClass = malloc (strlen (ptr2) + 14);
2421 if (xrmName && xrmClass)
2423 strcpy (xrmName , ptr);
2424 strcat (xrmName , ".helpColorUse");
2426 strcpy (xrmClass, ptr2);
2427 strcat (xrmClass, ".HelpColorUse");
2429 if (XrmGetResource (XtDatabase (dpy), xrmName, xrmClass,
2430 &retStrType, &retValue) == True)
2432 ptr = (char *) retValue.addr;
2434 * check for GreyScale
2436 if (*ptr == 'G' || *ptr == 'g')
2437 ForceColor = _DtGrGRAY_SCALE;
2439 * check for BlackWhite
2441 else if (*ptr == 'B' || *ptr == 'b')
2442 ForceColor = _DtGrBITONAL;
2450 * choose the correct visual type to use
2452 if (ForceColor == _DtGrCOLOR &&
2453 (visual->class == GrayScale || visual->class == StaticGray))
2454 ForceColor = _DtGrGRAY_SCALE;
2456 if (ForceColor != _DtGrBITONAL && depth == 1)
2457 ForceColor = _DtGrBITONAL;
2461 _DtHelpProcessUnlock();
2463 if (filename != NULL)
2467 /* Open the file and associate with a stream */
2468 result = _DtGrOpenFile(&stream, filename);
2474 /* Create a pixmap from the image data stream */
2475 _DtGrLoad(&stream, NULL, scrptr, depth, colormap, visual,
2476 fore_ground, back_ground, gc, ForceColor, TRUE, &pWidth,
2477 &pHeight, media_resolution, &pix, &mask, ret_colors,
2478 ret_number, context);
2480 pixHeight = pHeight;
2481 /* Close the stream and the file associated with it */
2482 _DtGrCloseStream( &stream );
2490 * Try to get a localized pixmap
2492 * This is a cached pixmap.....
2493 * Make sure XFreePixmaps does not free this one.
2497 *def_pix = XmGetPixmap(scrptr, "Dthgraphic", fore_ground, back_ground);
2498 if (*def_pix != XmUNSPECIFIED_PIXMAP)
2502 unsigned int border;
2505 if (XGetGeometry(dpy, *def_pix, &root_id, &x, &y,
2506 &pixWidth, &pixHeight, &border, &depth) == 0)
2508 XmDestroyPixmap(scrptr, *def_pix);
2516 * couldn't get a localized pixmap, go with a build in default
2520 pixWidth = Missing_bm_width;
2521 pixHeight = Missing_bm_height;
2522 *def_pix = XCreatePixmapFromBitmapData ( dpy, drawable,
2523 (char *) Missing_bm_bits,
2524 pixWidth, pixHeight,
2525 fore_ground, back_ground, depth);
2528 *def_pix_width = (Dimension) pixWidth;
2529 *def_pix_height = (Dimension) pixHeight;
2533 pixWidth = *def_pix_width;
2534 pixHeight = *def_pix_height;
2537 *width = (Dimension) pixWidth;
2538 *height = (Dimension) pixHeight;
2544 /******************************************************************************
2546 * Function _DtGrLoad
2548 * Determines the image type of the specified stream and calls the appropriate
2549 * imagetype-to-pixmap converter function. If the conversion is successful
2550 * and the caller passed the address of a pointer to NULL in the image_type
2551 * parameter, a copy of the image type string is allocated and stored at this
2552 * address. The caller is responsible for freeing this string. The caller
2553 * is also responsible for freeing the values passed back in the ret_pixmap,
2554 * ret_mask, ret_colors, and context parameters. The _DtGrLoad function
2555 * returns _DtGrCONVERT_FAILURE if the appropriate converter could not be
2556 * determined, otherwise it returns the value returned by the converter.
2558 *****************************************************************************/
2559 enum _DtGrLoadStatus _DtGrLoad(
2560 _DtGrStream *stream,
2569 enum _DtGrColorModel color_model,
2570 Boolean allow_reduced_colors,
2571 Dimension *in_out_width,
2572 Dimension *in_out_height,
2573 unsigned short media_resolution,
2577 int *ret_num_colors,
2578 _DtGrContext *context
2581 enum _DtGrLoadStatus status;
2582 _DtGrLoadProc converter;
2583 _DtGrDestroyContextProc destructor;
2584 char buf[20],*itype;
2586 /* Determine the image type */
2587 if ((image_type != NULL) && (*image_type != NULL))
2588 itype = *image_type; /* Caller specified image type */
2591 /* Image type not specified by caller, try to figure it out */
2592 if ((status = DetermineImageType(stream, buf)) != _DtGrSUCCESS)
2593 return (status); /* Return failure if image type is unknown */
2597 /* Look up the proper converter for this image type */
2598 if ((status=GetConverterAndDestructor(itype, &converter, &destructor)) ==
2601 /* Call the converter */
2602 if (converter != NULL)
2604 status = (*converter)(stream, screen, depth, colormap, visual,
2605 foreground, background, gc, color_model,
2606 allow_reduced_colors, in_out_width,
2607 in_out_height, media_resolution, ret_pixmap,
2608 ret_mask, ret_colors, ret_num_colors,
2612 status = _DtGrCONVERT_FAILURE;
2615 /* Return a copy of the image type string if successful */
2616 if (status == _DtGrSUCCESS || status == _DtGrCOLOR_REDUCE)
2617 if ((image_type != NULL) && (*image_type == NULL) && (itype != NULL))
2618 *image_type = XtNewString(itype);
2620 /* Return the conversion status */
2624 /******************************************************************************
2626 * Function _DtGrDestroyContext
2628 * Obtains and calls the context destructor function for the image type
2629 * indicated by the context parameter.
2631 *****************************************************************************/
2632 void _DtGrDestroyContext(
2633 _DtGrContext *context)
2635 _DtGrLoadProc converter;
2636 _DtGrDestroyContextProc destructor;
2638 if (GetConverterAndDestructor(context->image_type, &converter,
2639 &destructor) == _DtGrSUCCESS)
2641 if (destructor != NULL)
2642 (*destructor)(context);
2646 /******************************************************************************
2648 * Function _DtGrRegisterConverter
2650 * Registers a converter and context destructor function for the specified
2651 * image type. If the image_type has not been registered, a new record for
2652 * it is created in the new image type registry. If the image_type has been
2653 * registered, the current converter and context destructor functions are
2654 * replaced by those specified by the caller. If the caller passes valid
2655 * addresses in the current_convert_proc and current_destroy_proc parameters,
2656 * the current converter and context destructor functions will be saved there
2657 * first so that the caller may restore them at a later time.
2659 *****************************************************************************/
2660 void _DtGrRegisterConverter(
2662 _DtGrLoadProc convert_proc,
2663 _DtGrDestroyContextProc destroy_context_proc,
2664 _DtGrLoadProc *current_convert_proc,
2665 _DtGrDestroyContextProc *current_destroy_proc)
2669 if (image_type == NULL)
2672 /* Search the default converter registry for the specified image type */
2673 _DtHelpProcessLock();
2674 for (i=0; i<registry_count; i++)
2676 if (strcmp (registry[i].image_type, image_type) == 0)
2678 /* Found it, save the current procs, then replace them */
2679 /* with the new ones and return */
2680 if (current_convert_proc != NULL)
2681 *current_convert_proc = registry[i].convert_proc;
2682 if (current_destroy_proc != NULL)
2683 *current_destroy_proc = registry[i].destroy_context_proc;
2684 registry[i].convert_proc = convert_proc;
2685 registry[i].destroy_context_proc = destroy_context_proc;
2686 _DtHelpProcessUnlock();
2691 /* Search the new converter registry for the specified image type */
2692 for (i=0; i<new_registry_count; i++)
2694 if (strcmp (new_registry[i].image_type, image_type) == 0)
2696 /* Found it, save the current procs, then replace them */
2697 /* with the new ones and return */
2698 if (current_convert_proc != NULL)
2699 *current_convert_proc = new_registry[i].convert_proc;
2700 if (current_destroy_proc != NULL)
2701 *current_destroy_proc = new_registry[i].destroy_context_proc;
2702 new_registry[i].convert_proc = convert_proc;
2703 new_registry[i].destroy_context_proc = destroy_context_proc;
2704 _DtHelpProcessUnlock();
2709 /* If we make it here, we've got a new image type to register */
2710 new_registry = (_DtGrRegistryRec *) XtRealloc ((char *) new_registry,
2711 sizeof(_DtGrRegistryRec) * (new_registry_count + 1));
2712 new_registry[new_registry_count].image_type = XtNewString (image_type);
2713 new_registry[new_registry_count].convert_proc = convert_proc;
2714 new_registry[new_registry_count].destroy_context_proc =
2715 destroy_context_proc;
2716 new_registry_count++;
2717 _DtHelpProcessUnlock();
2719 /* Newly registered type, so return NULL for current function params */
2720 if (current_convert_proc != NULL)
2721 *current_convert_proc = NULL;
2722 if (current_destroy_proc != NULL)
2723 *current_destroy_proc = NULL;
2728 /******************************************************************************
2730 * Input stream functions
2732 * These functions allow the creation and manipulation of a stream that
2733 * can be associated with either a file or a buffer. They are intended to
2734 * be used by image data to pixmap converter functions that need to handle
2735 * both image files and in-memory buffers containing file data.
2737 *****************************************************************************/
2739 /******************************************************************************
2741 * Function _DtGrOpenFile
2743 * Opens a file for reading and associates it with the specified stream. If
2744 * the file is compressed, the function uncompresses it prior to opening.
2745 * Returns 0 for success, -1 or the value of errno as set by fopen for
2748 *****************************************************************************/
2750 _DtGrStream *stream,
2756 return (-1); /* Failure */
2758 /* Uncompress the file if necessary and obtain the new filename */
2759 if (_DtHelpCeGetUncompressedFileName(path, &fname) == -1)
2761 stream->type = _DtGrNONE;
2762 return (-1); /* Failure */
2766 stream->source.file.fileptr = fopen(fname,"r");
2767 if (stream->source.file.fileptr == NULL)
2769 /* Failure, couldn't open the file */
2770 stream->type = _DtGrNONE;
2771 if ((fname != path) && (fname != NULL))
2779 /* Set the stream type and copy the filename */
2780 stream->type = _DtGrFILE;
2781 stream->source.file.filename = XtNewString(path);
2783 /* If the file was uncompressed and renamed, save the new name */
2785 stream->source.file.uncompressed_filename = NULL;
2787 stream->source.file.uncompressed_filename = fname;
2789 return(0); /* Success */
2792 /******************************************************************************
2794 * Function _DtGrOpenBuffer
2796 * Associates the specified in-memory buffer with the specified stream.
2797 * The function returns 0 for success and the EINVAL error code for failure.
2799 *****************************************************************************/
2800 int _DtGrOpenBuffer(
2801 _DtGrStream *stream,
2805 if ((stream == NULL) || (buffer == NULL) || (buffer_size < 0))
2808 stream->type = _DtGrNONE;
2809 return(EINVAL); /* Failure */
2812 /* Set the appropriate stream fields */
2813 stream->type = _DtGrBUFFER;
2814 stream->source.buffer.base = buffer;
2815 stream->source.buffer.size = buffer_size;
2816 stream->source.buffer.current = (char *)buffer;
2817 stream->source.buffer.end = (char *)(buffer + buffer_size - 1);
2818 return(0); /* Success */
2821 /******************************************************************************
2823 * Function _DtGrCloseStream
2825 * The function closes the specified stream by setting the stream type to
2826 * _DtGrNONE. If the stream is associated with a file, then the file is
2827 * closed and the filename in the stream structure is freed. If the file
2828 * required decompression, then the uncompressed file is unlinked and the
2829 * uncompressed filename is freed.
2831 *****************************************************************************/
2832 int _DtGrCloseStream(
2833 _DtGrStream *stream)
2837 if ((stream == NULL) || (stream->type == _DtGrNONE))
2838 return(EOF); /* Failure */
2840 if (stream->type == _DtGrFILE)
2842 /* Close the file and free the filename */
2843 status = fclose(stream->source.file.fileptr);
2844 if (stream->source.file.filename != NULL)
2845 XtFree(stream->source.file.filename);
2846 if (stream->source.file.uncompressed_filename != NULL)
2848 /* Unlink the uncompressed file and free the filename */
2849 unlink(stream->source.file.uncompressed_filename);
2850 free(stream->source.file.uncompressed_filename);
2853 else if (stream->type == _DtGrBUFFER)
2855 status = 0; /* Success */
2858 stream->type = _DtGrNONE;
2863 /******************************************************************************
2865 * Function _DtGrRead
2867 * Stream version of fread, reads data from a stream into a buffer. If the
2868 * stream is file-associated, a call to fread is made. If the stream is
2869 * buffer-associated, an analogous operation is performed on the stream
2870 * buffer. The number of items read from the stream is returned to the caller.
2872 *****************************************************************************/
2877 _DtGrStream *stream)
2882 if ((stream == NULL) || (stream->type == _DtGrNONE))
2885 if (stream->type == _DtGrFILE)
2887 return (fread(buffer, size, num_items, stream->source.file.fileptr));
2889 else if (stream->type == _DtGrBUFFER)
2891 /* This code mirrors that of fread in libc */
2893 if (size <= 0 || num_items <= 0)
2896 for (nleft = num_items * size; ; )
2898 if (stream->source.buffer.current > stream->source.buffer.end)
2900 /* past end of stream */
2901 if (stream->source.buffer.current ==
2902 stream->source.buffer.end + 1)
2903 return (num_items - (nleft + size - 1)/size);
2904 stream->source.buffer.current--;
2906 n = (nleft < stream->source.buffer.end -
2907 stream->source.buffer.current + 1 ? nleft :
2908 stream->source.buffer.end -
2909 stream->source.buffer.current + 1);
2910 /* Copy the items into the caller-supplied buffer */
2911 buffer = (char *)memcpy(buffer,
2912 (void *) stream->source.buffer.current,
2914 stream->source.buffer.current += n;
2915 if ((nleft -= n) == 0)
2921 /******************************************************************************
2923 * Function _DtGrSeek
2925 * Stream version of fseek, repositions the file or buffer pointer of a
2926 * stream. If the stream is file-associated, the return value is the value
2927 * returned by fseek. If the stream is buffer-associated, 0 is returned if
2928 * the requested position is inside the buffer, -1 if it is not.
2930 *****************************************************************************/
2932 _DtGrStream *stream,
2938 if ((stream == NULL) || (stream->type == _DtGrNONE))
2939 return(-1); /* Failure */
2941 if (stream->type == _DtGrFILE)
2943 return (fseek(stream->source.file.fileptr,offset,whence));
2945 else if (stream->type == _DtGrBUFFER)
2950 newpos = (long)stream->source.buffer.base + offset;
2953 newpos = (long)stream->source.buffer.current + offset;
2956 newpos = (long)stream->source.buffer.end + 1 + offset;
2962 if ((newpos >= (long)stream->source.buffer.base) &&
2963 (newpos <= (long)stream->source.buffer.end))
2965 /* New position is within buffer, reposition pointer */
2966 stream->source.buffer.current = (char *)newpos;
2967 return(0); /* Success */
2970 return(-1); /* Failure */
2974 /******************************************************************************
2976 * Function _DtGrGetChar
2978 * Stream version of fgetc, reads a character from a stream and advances the
2979 * stream position. The next byte in the stream is returned, or EOF if an
2980 * error occurs or the end of the stream is reached.
2982 *****************************************************************************/
2984 _DtGrStream *stream)
2986 if ((stream == NULL) || (stream->type == _DtGrNONE))
2989 if (stream->type == _DtGrFILE)
2991 return (fgetc(stream->source.file.fileptr));
2993 else if (stream->type == _DtGrBUFFER)
2995 if (stream->source.buffer.current > stream->source.buffer.end)
2998 return ((unsigned char) *(stream->source.buffer.current++));
3002 /******************************************************************************
3004 * Function _DtGrGetString
3006 * Stream version of fgets, reads a string from a stream and advances the
3007 * stream position. If an error occurs or the end of the stream is
3008 * encountered and no characters have been read, no characters are transferred
3009 * to the buffer and a NULL pointer is returned. Otherwise, the buffer is
3012 *****************************************************************************/
3013 char *_DtGrGetString(
3016 _DtGrStream *stream)
3018 char *p, *save = buffer;
3021 if ((stream == NULL) || (stream->type == _DtGrNONE))
3022 return(NULL); /* Failure */
3024 if (stream->type == _DtGrFILE)
3026 return (fgets(buffer,num_bytes,stream->source.file.fileptr));
3028 else if (stream->type == _DtGrBUFFER)
3030 /* This code mirrors that of fgets in libc */
3031 for (num_bytes--; num_bytes > 0; num_bytes -= i)
3033 if (stream->source.buffer.current > stream->source.buffer.end)
3035 if (stream->source.buffer.current ==
3036 stream->source.buffer.end + 1)
3040 break; /* no more data */
3042 stream->source.buffer.current--;
3044 i = (num_bytes < stream->source.buffer.end -
3045 stream->source.buffer.current + 1 ? num_bytes :
3046 stream->source.buffer.end -
3047 stream->source.buffer.current + 1);
3048 /* Copy the data into the buffer */
3049 if ((p = memccpy((void *)buffer,
3050 (void *)stream->source.buffer.current,
3051 (int)'\n',(size_t)i)) != NULL)
3054 stream->source.buffer.current += i;
3056 break; /* found '\n' in buffer */