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 $";
92 #include <X11/XWDFile.h>
103 #include "GraphicsP.h"
104 #include "GraphicsI.h"
105 #include "StringFuncsI.h"
106 #include "GifUtilsI.h"
107 #include "XbmUtilsI.h"
108 #include "JpegUtilsI.h"
111 /*****************************************************************************/
113 /*****************************************************************************/
114 #define GR_SUCCESS 0 /* everything okay */
115 #define GR_DRAWABLE_ERR 1 /* couldn't get drawable attr/geom */
116 #define GR_FILE_ERR 2 /* file open/read/write problem */
117 #define GR_REQUEST_ERR 3 /* bad placement or size */
118 #define GR_ALLOC_ERR 4 /* memory allocation failure */
119 #define GR_HEADER_ERR 5 /* file header version/size problem */
121 #define MAX_GREY_COLORS 8
123 #define RES_TOLERANCE 25 /* resolution scaling tolerance */
125 static short GreyAllocated = False;
126 static Pixel GreyScalePixels[MAX_GREY_COLORS];
127 static char *GreyScaleColors[MAX_GREY_COLORS] =
139 #define Missing_bm_width 75
140 #define Missing_bm_height 47
141 static unsigned char Missing_bm_bits[] = {
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
145 0xff, 0xff, 0x7f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
146 0xff, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
147 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x04, 0x01, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0xc0, 0x00, 0x18, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0xc0, 0x00, 0x18, 0x8c, 0x21, 0x00, 0x00, 0x20, 0x00, 0x00, 0xc0, 0x00,
152 0x18, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x24,
153 0x31, 0xf0, 0xf0, 0x30, 0xe8, 0xf0, 0xc1, 0x00, 0x18, 0x04, 0x21, 0x08,
154 0x08, 0x20, 0x18, 0x09, 0xc1, 0x00, 0x18, 0x04, 0x21, 0xf0, 0xf0, 0x20,
155 0x08, 0x09, 0xc1, 0x00, 0x18, 0x04, 0x21, 0x00, 0x01, 0x21, 0x08, 0x09,
156 0xc1, 0x00, 0x18, 0x04, 0x21, 0x08, 0x09, 0x21, 0x08, 0x09, 0xc1, 0x00,
157 0x18, 0x04, 0x71, 0xf0, 0xf0, 0x70, 0x08, 0xf1, 0xc1, 0x00, 0x18, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x18, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
160 0x00, 0xf0, 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
162 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0xf0,
163 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x08, 0x01, 0x00,
164 0x00, 0x08, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x08, 0x00, 0x00, 0x00, 0x08,
165 0x20, 0x00, 0xc0, 0x00, 0x18, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
166 0xc0, 0x00, 0x18, 0x08, 0xd8, 0xf0, 0xe8, 0xf8, 0x30, 0xf0, 0xc0, 0x00,
167 0x18, 0xc8, 0x31, 0x01, 0x19, 0x09, 0x21, 0x08, 0xc1, 0x00, 0x18, 0x08,
168 0x11, 0xf0, 0x09, 0x09, 0x21, 0x08, 0xc0, 0x00, 0x18, 0x08, 0x11, 0x08,
169 0x09, 0x09, 0x21, 0x08, 0xc0, 0x00, 0x18, 0x08, 0x11, 0x08, 0x09, 0x09,
170 0x21, 0x08, 0xc1, 0x00, 0x18, 0xf0, 0x10, 0xf0, 0xf9, 0x08, 0x71, 0xf0,
171 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xc0, 0x00,
172 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00,
173 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00,
174 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
175 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176 0xc0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
177 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf8, 0xff,
178 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 /* Used to hold image type converter registry info */
186 _DtGrLoadProc convert_proc;
187 _DtGrDestroyContextProc destroy_context_proc;
191 * This array maps image file name extensions to the corresponding
192 * CDE data type. It is used by the DetermineImageType function.
193 * The array must be NULL-terminated.
195 static char * img_extensions[] = {
210 /*****************************************************************************/
211 /* Private declarations */
212 /*****************************************************************************/
214 static int Do_Direct(
217 XWDFileHeader *header,
221 enum _DtGrColorModel force,
224 unsigned long **ret_colors,
226 static int Do_Pseudo(
232 enum _DtGrColorModel force,
235 unsigned long **ret_colors,
237 static int GreyScale (
245 enum _DtGrColorModel force,
252 static unsigned int Image_Size(
254 static void Perform_Dither(
259 static enum _DtGrLoadStatus processBitmap(
268 enum _DtGrColorModel color_model,
269 Boolean allow_reduced_colors,
270 Dimension *in_out_width,
271 Dimension *in_out_height,
272 unsigned short media_resolution,
277 _DtGrContext *context);
279 static enum _DtGrLoadStatus processTiff(
288 enum _DtGrColorModel color_model,
289 Boolean allow_reduced_colors,
290 Dimension *in_out_width,
291 Dimension *in_out_height,
292 unsigned short media_resolution,
297 _DtGrContext *context);
298 static void destroyTiffContext(
299 _DtGrContext *context);
301 static enum _DtGrLoadStatus processXwd(
310 enum _DtGrColorModel color_model,
311 Boolean allow_reduced_colors,
312 Dimension *in_out_width,
313 Dimension *in_out_height,
314 unsigned short media_resolution,
319 _DtGrContext *context);
320 static void _swaplong (
322 register unsigned n );
323 static void _swapshort (
325 register unsigned n );
326 static int XwdFileToPixmap (
334 enum _DtGrColorModel color_model,
342 unsigned long **ret_colors,
344 static enum _DtGrLoadStatus processXpm(
353 enum _DtGrColorModel color_model,
354 Boolean allow_reduced_colors,
355 Dimension *in_out_width,
356 Dimension *in_out_height,
357 unsigned short media_resolution,
362 _DtGrContext *context);
363 static enum _DtGrLoadStatus processGIF(
372 enum _DtGrColorModel color_model,
373 Boolean allow_reduced_colors,
374 Dimension *in_out_width,
375 Dimension *in_out_height,
376 unsigned short media_resolution,
381 _DtGrContext *context);
382 static enum _DtGrLoadStatus processJPEG(
391 enum _DtGrColorModel color_model,
392 Boolean allow_reduced_colors,
393 Dimension *in_out_width,
394 Dimension *in_out_height,
395 unsigned short media_resolution,
400 _DtGrContext *context);
401 static enum _DtGrLoadStatus DetermineImageType(
404 static enum _DtGrLoadStatus GetConverterAndDestructor(
406 _DtGrLoadProc *converter,
407 _DtGrDestroyContextProc *destructor);
408 static float ComputeRatio(int media_res, int image_res);
410 /*****************************************************************************
411 * Image type registry declarations
412 *****************************************************************************/
414 /* Registry of converters and destructors for default image types */
415 static _DtGrRegistryRec registry[] =
454 static int registry_count = XtNumber(registry);
456 /* Registry of converters and destructors for non-default image types */
457 static _DtGrRegistryRec *new_registry = NULL;
458 static new_registry_count = 0;
460 /*****************************************************************************
462 *****************************************************************************/
463 /*****************************************************************************
464 * taken straight out of xwud and modified.
465 *****************************************************************************/
466 /* Copyright 1985, 1986, 1988 Massachusetts Institute of Technology */
471 register unsigned n )
474 register char *ep = bp + n;
487 register unsigned n )
490 register char *ep = bp + n;
507 ComputeRatio(int media_res, int image_res)
512 if (media_res >= image_res) {
513 ratio = (float)media_res / (float)image_res;
514 if (media_res % image_res == 0)
516 iratio = ratio + 0.5;
517 dx = media_res - image_res * iratio;
518 if (dx >= -RES_TOLERANCE && dx <= RES_TOLERANCE)
519 ratio = (float)iratio;
521 ratio = (float)image_res / (float)media_res;
522 if (image_res % media_res == 0)
524 iratio = ratio + 0.5;
525 dx = image_res - media_res * iratio;
526 if (dx >= -RES_TOLERANCE && dx <= RES_TOLERANCE)
527 ratio = (float)iratio;
533 /*****************************************************************************
534 * Function: GreyScale
536 * Turn a color image into a 8 grey color image
537 * If it can't create a grey scale image, GreyScale will call
538 * Perform_Dither to create a bi-tonal image.
540 *****************************************************************************
541 * The GreyScale code was ported from xgedit and changed to fit our needs
542 *****************************************************************************/
552 enum _DtGrColorModel force,
563 int width = in_image->width;
564 int height = in_image->height;
567 Pixel valueArray[256];
571 /*--- allocate an array big enough to map each pixel in the image ---*/
572 /*--- into a corresponding greyscale value (in the range [0-255]). ---*/
574 grey_scale = (int *) calloc(width*height, sizeof(int));
575 if (grey_scale == NULL) {
579 /*--- < ESTABLISH THE GREYSCALE IMAGE > ---*/
580 /*--- The NTSC formula for converting an RGB value into the ---*/
581 /*--- corresponding greyscale value is: ---*/
582 /*--- luminosity = .299 red + .587 green + .114 blue ---*/
585 * zero the flag array
587 for (i = 0; i < 256; i++)
590 for (j=0, x = 0; j<height; j++)
591 for (i=0; i<width; i++, x++) {
592 n = XGetPixel(in_image, i, j);
595 ret_color.red = (n >> rshift) & rmask;
596 ret_color.green = (n >> gshift) & gmask;
597 ret_color.blue = (n >> bshift) & bmask;
600 ret_color.red = colors[ret_color.red ].red;
601 ret_color.green = colors[ret_color.green].green;
602 ret_color.blue = colors[ret_color.blue ].blue;
606 ret_color.red = (((Pixel) ret_color.red ) * 65535) / rmask;
607 ret_color.green = (((Pixel) ret_color.green) * 65535) / gmask;
608 ret_color.blue = (((Pixel) ret_color.blue ) * 65535) / bmask;
611 value = (((int)(ret_color.red*299) + (int)(ret_color.green*587) +
612 (int)(ret_color.blue*114)) / 1000) >> 8;
615 value = (((int)(colors[n].red*299) + (int)(colors[n].green*587) +
616 (int)(colors[n].blue*114)) / 1000) >> 8;
617 grey_scale[x] = value;
622 * Find out if we can/have allocate the pre-defined grey colors.
624 _DtHelpProcessLock();
625 if (!GreyAllocated && force != _DtGrBITONAL)
627 for (i = 0; !GreyAllocated && i < MAX_GREY_COLORS; i++)
629 if (!XParseColor (dpy, cmap, GreyScaleColors[i], &ret_color) ||
630 !XAllocColor (dpy, cmap, &ret_color))
633 * Have a problem allocating one of the pre-defined
634 * grey colors. Free the already allocated pixels
638 XFreeColors (dpy, cmap, GreyScalePixels, i, 0);
642 GreyScalePixels[i] = ret_color.pixel;
645 GreyAllocated = True;
649 * Had a problem allocating the pre-defined grey colors.
650 * Try to dither into black and white.
652 if (force == _DtGrBITONAL || GreyAllocated == -1)
654 Perform_Dither (dpy, screen, out_image, grey_scale);
656 _DtHelpProcessUnlock();
659 _DtHelpProcessUnlock();
662 * Find out how many grey scale colors there are.
664 for (count = 0, i = 0; i < 256; i++)
669 * If we have less than maximum grey colors we want to spread the load
672 if (count < MAX_GREY_COLORS)
675 inc = MAX_GREY_COLORS;
678 * This is rather esoteric code.
680 * valueArray[n] = GreyScalePixels[i * MAX_GREY_COLORS / inc]
682 * causes the colors to be evenly distributed if the total number
683 * of calculated grey shades is less than the number of pre-defined
687 * if (j >= count / (MAX_GREY_COLORS - i))
689 * uniformly reduces the calculated grey shades into the pre-defined
690 * grey colors, if the total number of grey shades is greater than
691 * the number of pre-defined grey colors.
693 * If after reading the following code, the reader still doesn't
694 * understand it, pick a couple of numbers between 1-255 for 'count'
695 * and walk each of them thru the 'for' loop. Hopefully it will help.
696 * (Suggestion - pick a large number for one value and pick
697 * a number less than 8 for the other value).
699 for (i = 0, n = 0, j = 0; n < 256 && count && i < MAX_GREY_COLORS; n++)
703 _DtHelpProcessLock();
704 valueArray[n] = GreyScalePixels[i * MAX_GREY_COLORS / inc];
705 _DtHelpProcessUnlock();
707 if (j >= count / (MAX_GREY_COLORS - i))
717 * Now replace the image pixels with the grey pixels
719 for (j = 0, x = 0; j < height; j++)
720 for (i = 0; i < width; i++, x++) {
721 XPutPixel (out_image, i, j, valueArray[grey_scale[x]]);
729 /***************************************************************************
731 * Routine: Perform_Dither *
733 * Purpose: Given a color XImage and a greyscale representation of it, *
734 * for each pixel in the image, determine whether it should be *
735 * coverted to Black or White base on the weighted average of *
736 * the greyscale value of it and the pixels surrounding it. *
737 * Be sure to do bounds checking for pixels that are at the *
738 * edge of the image. *
740 * The dithering is done using the Floyd-Steinberg error *
741 * diffusion algorithm, which incorporates a Stucki error *
742 * filter (specifics can be found in Chapter 8, "Dithering *
743 * with Blue Noise", of the book "Digital Halftoning" by *
744 * Robert Ulichney (MIT Press, 1988). *
746 *X11***********************************************************************/
754 int i, j, width, height;
755 int result, error, max_lum;
756 Pixel blackPixel = XBlackPixel (dpy, screen);
757 Pixel whitePixel = XWhitePixel (dpy, screen);
759 width = image->width;
760 height = image->height;
763 for (j=0; j<height; j++) /* rows */
764 for (i=0; i<width; i++) { /* columns */
765 if (greyscale[(j*width)+i] < (max_lum/2))
768 result = max_lum - 1;
769 error = greyscale[(j*width)+i] - result;
770 if (i+1 < width) /*--- G [j] [i+1] ---*/
771 greyscale[(j*width)+i+1] += (error * 8)/42;
772 if (i+2 < width) /*--- G [j] [i+2] ---*/
773 greyscale[(j*width)+i+2] += (error * 4)/42;
776 if (i-2 >= 0) /*--- G [j+1] [i-2] ---*/
777 greyscale[((j+1)*width)+i-2] += (error * 2)/42;
778 if (i-1 >= 0) /*--- G [j+1] [i-1] ---*/
779 greyscale[((j+1)*width)+i-1] += (error * 4)/42;
780 /*--- G [j+1] [i] ---*/
781 greyscale[((j+1)*width)+i] += (error * 8)/42;
782 if (i+1 < width) /*--- G [j+1] [i+1] ---*/
783 greyscale[((j+1)*width)+i+1] += (error * 4)/42;
784 if (i+2 < width) /*--- G [j+1] [i+2] ---*/
785 greyscale[((j+1)*width)+i+2] += (error * 2)/42;
789 if (i-2 >= 0) /*--- G [j+2] [i-2] ---*/
790 greyscale[((j+2)*width)+i-2] += error/42;
791 if (i-1 >= 0) /*--- G [j+2] [i-1] ---*/
792 greyscale[((j+2)*width)+i-1] += (error * 2)/42;
793 /*--- G [j+2] [i] ---*/
794 greyscale[((j+2)*width)+i] += (error * 4)/42;
795 if (i+1 < width) /*--- G [j+2] [i+1] ---*/
796 greyscale[((j+2)*width)+i+1] += (error * 2)/42;
797 if (i+2 < width) /*--- G [j+2] [i+2] ---*/
798 greyscale[((j+2)*width)+i+2] += error/42;
802 XPutPixel(image, i, j, whitePixel);
804 XPutPixel(image, i, j, blackPixel);
816 enum _DtGrColorModel force,
819 unsigned long **ret_colors,
822 register int i, x, y, colorCount = 0;
823 register XColor *color;
827 for (i = 0; i < ncolors; i++)
835 * It is set to one upon entering this routine.
836 * The only way it can be modified is by the call to XAllocColor.
838 if (force == _DtGrCOLOR)
841 for (y = 0; result && y < in_image->height; y++)
843 for (x = 0; result && x < in_image->width; x++)
845 pixel = XGetPixel(in_image, x, y);
846 color = &colors[pixel];
849 color->flags = DoRed | DoGreen | DoBlue;
850 result = XAllocColor(dpy, colormap, color);
857 XPutPixel(out_image, x, y, color->pixel);
862 * If result == 0, a call to XAllocColor failed
863 * Try to grey scale the image.
869 for (i = 0; i < ncolors; i++)
873 XFreeColors (dpy, colormap, &(colors[i].pixel), 1, 0);
878 result = GreyScale (dpy, screen, colormap, in_image, out_image, colors,
879 ncolors, force, 0, 0, 0, 0, 0, 0);
884 *ret_colors = (unsigned long *) malloc (
885 sizeof (unsigned long) * colorCount);
886 if (*ret_colors == NULL)
889 result = GR_ALLOC_ERR;
892 for (i = 0, x = 0; i < ncolors && x < colorCount; i++)
894 (*ret_colors)[x++] = colors[i].pixel;
896 *ret_number = colorCount;
900 * result was set to a XHPIF value via the 'else' stmt or
901 * returned from GreyScale routine.
910 XWDFileHeader *header,
914 enum _DtGrColorModel force,
917 unsigned long **ret_colors,
922 unsigned long rmask, gmask, bmask;
923 int rshift = 0, gshift = 0, bshift = 0;
932 oldPixels = (Pixel *) malloc (sizeof (Pixel) * pixMax);
933 newPixels = (Pixel *) malloc (sizeof (Pixel) * pixMax);
935 if (oldPixels == NULL || newPixels == NULL)
945 rmask = header->red_mask;
946 while (!(rmask & 1)) {
950 gmask = header->green_mask;
951 while (!(gmask & 1)) {
955 bmask = header->blue_mask;
956 while (!(bmask & 1)) {
960 if (in_image->depth <= 12)
961 pix = 1 << in_image->depth;
963 if (force == _DtGrCOLOR)
964 color.flags = DoRed | DoGreen | DoBlue;
968 for (y = 0; color.flags && y < in_image->height; y++)
970 for (x = 0; color.flags && x < in_image->width; x++)
972 pix = XGetPixel(in_image, x, y);
975 while (i < pixI && oldPixels[i] != pix)
980 color.red = (pix >> rshift) & rmask;
981 color.green = (pix >> gshift) & gmask;
982 color.blue = (pix >> bshift) & bmask;
984 color.red = colors[color.red].red;
985 color.green = colors[color.green].green;
986 color.blue = colors[color.blue].blue;
988 color.red = ((unsigned long)color.red * 65535) / rmask;
989 color.green = ((unsigned long)color.green * 65535) / gmask;
990 color.blue = ((unsigned long)color.blue * 65535) / bmask;
992 if (!XAllocColor(dpy, colormap, &color))
999 oldPixels = (Pixel *) realloc ((void *) oldPixels,
1000 (sizeof (Pixel) * pixMax));
1001 newPixels = (Pixel *) realloc ((void *) newPixels,
1002 (sizeof (Pixel) * pixMax));
1007 if (oldPixels == NULL || newPixels == NULL)
1014 XFreeColors(dpy, colormap, newPixels, pixI, 0);
1018 return GR_ALLOC_ERR;
1021 oldPixels[pixI] = pix;
1022 newPixels[pixI++] = color.pixel;
1026 XPutPixel(out_image, x, y, newPixels[i]);
1031 result = GR_SUCCESS;
1034 newPixels = (Pixel *) realloc ((void *) newPixels,
1035 (sizeof (Pixel) * pixI));
1036 if (newPixels == NULL)
1037 result = GR_ALLOC_ERR;
1042 *ret_colors = newPixels;
1048 XFreeColors (dpy, colormap, newPixels, pixI, 0);
1053 result = GreyScale(dpy, screen, colormap, in_image, out_image, colors,
1054 ncolors, force, rshift, gshift, bshift, rmask, gmask, bmask);
1064 if (image->format != ZPixmap)
1065 return(image->bytes_per_line * image->height * image->depth);
1067 return((unsigned)image->bytes_per_line * image->height);
1079 enum _DtGrColorModel color_model,
1086 _DtGrStream *stream,
1087 unsigned long **ret_colors,
1092 XImage in_image, *out_image;
1093 register char *buffer;
1094 unsigned long swaptest = 1;
1096 unsigned buffer_size;
1098 Bool rawbits = False;
1099 XColor *colors = NULL;
1101 /* Use a different structure for compatibility with 32-bit platform */
1103 #endif /* __alpha */
1104 XWDFileHeader header;
1106 /* Reset the pointer to the beginning of the stream */
1107 _DtGrSeek(stream, 0, SEEK_SET);
1110 * Read in header information.
1112 if(_DtGrRead((char *)&header, sizeof(header), 1, stream) != 1)
1114 return GR_HEADER_ERR;
1117 if (*(char *) &swaptest)
1118 _swaplong((char *) &header, sizeof(header));
1120 /* check to see if the dump file is in the proper format */
1121 if (header.file_version != XWD_FILE_VERSION)
1123 return GR_HEADER_ERR;
1126 if (header.header_size < sizeof(header))
1128 return GR_HEADER_ERR;
1132 * skip the window name
1134 if (_DtGrSeek(stream, (header.header_size - sizeof(header)), 1))
1140 * initialize the input image
1142 in_image.width = (int) header.pixmap_width;
1143 in_image.height = (int) header.pixmap_height;
1144 in_image.xoffset = (int) header.xoffset;
1145 in_image.format = (int) header.pixmap_format;
1146 in_image.byte_order = (int) header.byte_order;
1147 in_image.bitmap_unit = (int) header.bitmap_unit;
1148 in_image.bitmap_bit_order = (int) header.bitmap_bit_order;
1149 in_image.bitmap_pad = (int) header.bitmap_pad;
1150 in_image.depth = (int) header.pixmap_depth;
1151 in_image.bits_per_pixel = (int) header.bits_per_pixel;
1152 in_image.bytes_per_line = (int) header.bytes_per_line;
1153 in_image.red_mask = header.red_mask;
1154 in_image.green_mask = header.green_mask;
1155 in_image.blue_mask = header.blue_mask;
1156 in_image.obdata = NULL;
1157 _XInitImageFuncPtrs(&in_image);
1159 /* read in the color map buffer */
1160 ncolors = header.ncolors;
1162 colors = (XColor *)malloc((unsigned) ncolors * sizeof(XColor));
1165 return GR_ALLOC_ERR;
1169 /* Use XWDColor instead of XColor. Byte-swapping if it is necessary.
1170 * Move values back into Xcolor structure.
1172 for (i = 0; i < ncolors; i++) {
1173 if (_DtGrRead( (char *) &xwd_color, sizeof(XWDColor), 1 , stream) != 1 )
1175 XFree ((char *) colors);
1179 if (*(char *) &swaptest) {
1180 _swaplong((char *) &xwd_color.pixel, sizeof(xwd_color.pixel));
1181 _swapshort((char *) &xwd_color.red, 3 * sizeof(xwd_color.red));
1184 colors[i].pixel = xwd_color.pixel;
1185 colors[i].red = xwd_color.red;
1186 colors[i].green = xwd_color.green;
1187 colors[i].blue = xwd_color.blue;
1188 colors[i].flags = xwd_color.flags;
1191 if(_DtGrRead((char *) colors, sizeof(XColor), ncolors, stream) != ncolors)
1193 XFree ((char *) colors);
1197 if (*(char *) &swaptest) {
1198 for (i = 0; i < ncolors; i++) {
1199 _swaplong((char *) &colors[i].pixel, sizeof(long));
1200 _swapshort((char *) &colors[i].red, 3 * sizeof(short));
1203 #endif /* __alpha */
1207 * alloc the pixel buffer
1209 buffer_size = Image_Size(&in_image);
1210 buffer = (char *) malloc(buffer_size);
1214 XFree ((char *) colors);
1215 return GR_ALLOC_ERR;
1218 /* read in the image data */
1219 count = _DtGrRead(buffer, sizeof(char), (int)buffer_size, stream);
1221 if (count != buffer_size)
1224 XFree ((char *) colors);
1229 if (in_image.depth == 1) {
1230 in_image.format = XYBitmap;
1233 in_image.data = buffer;
1235 /* create the output image */
1236 result = GR_SUCCESS;
1239 out_image = &in_image;
1241 out_image = XCreateImage(dpy, visual, depth,
1242 (depth == 1) ? XYBitmap : in_image.format,
1243 in_image.xoffset, NULL,
1244 in_image.width, in_image.height,
1245 XBitmapPad(dpy), 0);
1247 out_image->data = (char *) malloc(Image_Size(out_image));
1249 if ((header.visual_class == TrueColor) ||
1250 (header.visual_class == DirectColor))
1251 result = Do_Direct(dpy, screen, &header, colormap, ncolors, colors,
1253 &in_image, out_image, ret_colors, ret_number);
1255 result = Do_Pseudo(dpy, screen, colormap, ncolors, colors, color_model,
1256 &in_image, out_image, ret_colors, ret_number);
1259 if (result != GR_ALLOC_ERR)
1261 _XmPutScaledImage(dpy, pixmap, gc, out_image,
1262 src_x, src_y, dst_x, dst_y,
1263 in_image.width, in_image.height,
1270 XFree ((char *) colors);
1273 XDestroyImage (out_image);
1278 /*****************************************************************************/
1279 /* General functions for changing a file into a pixmap */
1281 /*****************************************************************************/
1284 * Function processBitmap
1287 * Make a bitmap into the pixmap for the graphic.
1290 static enum _DtGrLoadStatus processBitmap(
1291 _DtGrStream *stream,
1299 enum _DtGrColorModel color_model,
1300 Boolean allow_reduced_colors,
1301 Dimension *in_out_width,
1302 Dimension *in_out_height,
1303 unsigned short media_resolution,
1307 int *ret_num_colors,
1308 _DtGrContext *context
1313 unsigned int width, height;
1314 unsigned char *data;
1315 Pixmap scaled_pixmap=NULL;
1316 Display *dpy = DisplayOfScreen(screen);
1317 Drawable drawable = RootWindowOfScreen(screen);
1321 if (media_resolution == 0)
1322 return(_DtGrCONVERT_FAILURE);
1324 if (*in_out_width == 0 && *in_out_height == 0)
1325 ratio = ComputeRatio(media_resolution, 100);
1327 if (stream->type == _DtGrNONE)
1328 return(_DtGrCONVERT_FAILURE);
1330 result = _DtGrReadBitmapStreamData (stream,
1331 &width, &height, &data, &junk, &junk);
1333 /* Be sure to implement XvpCopyPlane later */
1334 if (result == BitmapSuccess)
1336 ximage.height = height;
1337 ximage.width = width;
1339 ximage.bits_per_pixel = 1;
1341 ximage.format = XYBitmap;
1342 ximage.data = (char *)data;
1343 ximage.byte_order = LSBFirst;
1344 ximage.bitmap_unit = 8;
1345 ximage.bitmap_bit_order = LSBFirst;
1346 ximage.bitmap_pad = 8;
1347 ximage.bytes_per_line = (width+7)/8;
1348 XInitImage(&ximage);
1350 *in_out_width = (Dimension) width * ratio + 0.5;
1351 *in_out_height = (Dimension) height * ratio + 0.5;
1352 if (*in_out_width == 0)
1354 if (*in_out_height == 0)
1357 scaled_pixmap = XCreatePixmap (dpy, drawable, (*in_out_width),
1358 (*in_out_height), depth);
1359 _XmPutScaledImage(dpy, scaled_pixmap, gc, &ximage,0, 0, 0, 0,
1360 width,height,(*in_out_width),(*in_out_height));
1361 XFree((char *)data);
1362 *ret_pixmap = scaled_pixmap;
1365 if (result == BitmapSuccess)
1366 return(_DtGrSUCCESS);
1367 else if (result == BitmapOpenFailed)
1368 return(_DtGrOPEN_FAILED);
1369 else if (result == BitmapFileInvalid)
1370 return(_DtGrFILE_INVALID);
1371 else if (result == BitmapNoMemory)
1372 return(_DtGrNO_MEMORY);
1374 return(_DtGrCONVERT_FAILURE);
1380 * Function processTiff
1383 * Make a tiff into the pixmap for the graphic.
1386 static enum _DtGrLoadStatus processTiff(
1387 _DtGrStream *stream,
1395 enum _DtGrColorModel color_model,
1396 Boolean allow_reduced_colors,
1397 Dimension *in_out_width,
1398 Dimension *in_out_height,
1399 unsigned short media_resolution,
1403 int *ret_num_colors,
1404 _DtGrContext *context
1408 Pixmap pixmap = NULL;
1411 ilFileImage inImage;
1412 const ilImageDes *inDes;
1413 static ilContext IlContext = NULL;
1414 Display *dpy = DisplayOfScreen(screen);
1415 Drawable drawable = RootWindowOfScreen(screen);
1419 _DtHelpProcessLock();
1420 if ((context == NULL) || (stream->type == _DtGrNONE))
1422 _DtHelpProcessUnlock();
1423 return (_DtGrCONVERT_FAILURE);
1426 if (media_resolution == 0)
1428 _DtHelpProcessUnlock();
1429 return(_DtGrCONVERT_FAILURE);
1432 tiff_xwc = (ilXWC *) &(context->context);
1433 if (IlContext == NULL)
1435 if (IL_CREATE_CONTEXT (&IlContext, 0))
1438 _DtHelpProcessUnlock();
1439 return (_DtGrCONVERT_FAILURE);
1443 if (*tiff_xwc == NULL)
1445 /* Fill in the context record fields */
1446 *tiff_xwc = ilCreateXWC (IlContext, dpy, visual, colormap, gc, 0, 0);
1447 if (*tiff_xwc == NULL)
1449 _DtHelpProcessUnlock();
1450 return(_DtGrCONVERT_FAILURE);
1452 context->image_type = XtNewString("TIFF");
1455 inFile = ilConnectFile (IlContext, stream, 0, 0);
1458 inImage = ilListFileImages (inFile, 0);
1461 int image_resolution = 100 ; /* assume that if not in file */
1464 if (inImage->xRes != 0) {
1465 image_resolution = inImage->xRes ; /* dpi from the file */
1468 if (*in_out_width == 0 && *in_out_height == 0)
1469 ratio = ComputeRatio(media_resolution, image_resolution);
1471 *in_out_width = inImage->width * ratio + 0.5;
1472 *in_out_height = inImage->height * ratio + 0.5;
1473 if (*in_out_width == 0)
1475 if (*in_out_height == 0)
1478 pixmap = XCreatePixmap (dpy, drawable, (*in_out_width),
1479 (*in_out_height), depth);
1482 inPipe = ilCreatePipe (IlContext, 0);
1485 if (color_model == _DtGrGRAY_SCALE)
1486 inDes = IL_DES_GRAY;
1487 else if (color_model == _DtGrBITONAL)
1488 inDes = IL_DES_BITONAL;
1491 if (!ilReadFileImage (inPipe, inImage, (ilRect *) NULL, 0))
1494 if (result == 0 && color_model != _DtGrCOLOR &&
1495 ilConvert (inPipe, inDes, ((ilImageFormat *) NULL), 0, NULL) != True)
1499 ilWriteXDrawable (inPipe, pixmap, *tiff_xwc,
1500 (ilRect *) NULL, 0, 0, 0))
1502 ilExecutePipe (inPipe, 0, ratio);
1503 if (IlContext->error != 0)
1506 ilDestroyObject (inPipe);
1510 XFreePixmap (dpy, pixmap);
1515 ilDestroyObject (inFile);
1518 *ret_pixmap = pixmap;
1521 if ((IlContext->error == IL_ERROR_FILE_IO) ||
1522 (IlContext->error == IL_ERROR_FILE_NOT_TIFF))
1524 _DtHelpProcessUnlock();
1525 return(_DtGrFILE_INVALID);
1527 else if (IlContext->error == IL_ERROR_MALLOC)
1529 _DtHelpProcessUnlock();
1530 return(_DtGrNO_MEMORY);
1534 _DtHelpProcessUnlock();
1535 return(_DtGrCONVERT_FAILURE);
1540 _DtHelpProcessUnlock();
1541 return(_DtGrSUCCESS);
1548 * Function processXwd
1551 * Make an XWD file into the pixmap for the graphic.
1554 static enum _DtGrLoadStatus processXwd(
1555 _DtGrStream *stream,
1563 enum _DtGrColorModel color_model,
1564 Boolean allow_reduced_colors,
1565 Dimension *in_out_width,
1566 Dimension *in_out_height,
1567 unsigned short media_resolution,
1571 int *ret_num_colors,
1572 _DtGrContext *context
1576 XWDFileHeader header;
1578 unsigned long swaptest = TRUE;
1579 Display *dpy = DisplayOfScreen(screen);
1580 Drawable drawable = RootWindowOfScreen(screen);
1581 int screen_num = XScreenNumberOfScreen(screen);
1584 if (media_resolution == 0)
1585 return(_DtGrCONVERT_FAILURE);
1587 if (stream->type == _DtGrNONE)
1588 return(_DtGrCONVERT_FAILURE);
1590 /* Read in XWDFileHeader structure */
1591 result = _DtGrRead((char *)&header, sizeof(header), 1, stream);
1593 if (result == 1 && *(char *) &swaptest)
1594 _swaplong((char *) &header, sizeof(header));
1596 if (result != 1 || header.file_version != XWD_FILE_VERSION)
1597 return (_DtGrFILE_INVALID);
1599 if (*in_out_width == 0 && *in_out_height == 0)
1600 ratio = ComputeRatio(media_resolution, 100);
1602 *in_out_width = header.pixmap_width * ratio + 0.5;
1603 *in_out_height = header.pixmap_height * ratio + 0.5;
1605 if (*in_out_width == 0)
1607 if (*in_out_height == 0)
1610 pixmap = XCreatePixmap (dpy, drawable, (*in_out_width),
1611 (*in_out_height),depth);
1614 if ((result=XwdFileToPixmap (dpy, screen_num, depth, pixmap, colormap,
1615 visual, gc, color_model, 0, 0, 0, 0,
1616 (*in_out_width), (*in_out_height), stream,
1617 ret_colors, ret_num_colors))
1619 *ret_pixmap = pixmap;
1620 return (_DtGrSUCCESS);
1622 else if (result == GR_HEADER_ERR)
1623 return (_DtGrFILE_INVALID);
1624 else if (result == GR_FILE_ERR)
1625 return (_DtGrFILE_INVALID);
1626 else if (result == GR_ALLOC_ERR)
1627 return (_DtGrNO_MEMORY);
1629 return (_DtGrCONVERT_FAILURE);
1632 return (_DtGrNO_MEMORY);
1635 /************************************
1636 * myXpmReadFileToPixmap
1637 ***********************************/
1639 myXpmReadFileToPixmap(
1643 _DtGrStream *stream,
1644 Pixmap *pixmap_return,
1645 Pixmap *shapemask_return,
1646 XpmAttributes *attributes,
1654 XImage *image, **imageptr = NULL;
1655 XImage *shapeimage, **shapeimageptr = NULL;
1658 int scaledWidth, scaledHeight;
1660 * initialize return values
1663 if (pixmap_return) {
1664 *pixmap_return = NULL;
1667 if (shapemask_return) {
1668 *shapemask_return = NULL;
1669 shapeimageptr = &shapeimage;
1676 if (stream->type == _DtGrFILE)
1678 if (stream->source.file.uncompressed_filename != NULL)
1679 ErrorStatus = _DtXpmReadFileToImage(display,
1680 stream->source.file.uncompressed_filename,
1681 imageptr, shapeimageptr, attributes);
1683 ErrorStatus = _DtXpmReadFileToImage(display,
1684 stream->source.file.filename,
1685 imageptr, shapeimageptr, attributes);
1687 else if (stream->type == _DtGrBUFFER)
1689 ErrorStatus = XpmCreateImageFromBuffer(display,
1690 (char *) stream->source.buffer.base,
1691 imageptr, shapeimageptr, attributes);
1694 ErrorStatus = XpmFileInvalid; /* stream type of _DtGrNONE */
1696 if (ErrorStatus < 0)
1697 return (ErrorStatus);
1700 * Check to see if we will need to switch the foreground and
1701 * background colors. When forced to a depth of 1, the Xpm call
1702 * returns a ZPixmap ready to place in pixmap of depth 1.
1703 * Unfortunately, usually the pixmap is of a different depth. This
1704 * causes a depth mismatch for the XPutImage. Therefore, we change
1705 * the format type to XYBitmap and XPutImage is happy. But on
1706 * servers where BlackPixel is not at pixel 1 in the colormap, this
1707 * causes the image to be inverted. So by switching the foreground
1708 * and background in the gc, the image is corrected for these
1711 * The other way of doing this, is to create a pixmap of depth 1 and
1712 * do an XPutImage to it. Then do a XCopyPlane to a pixmap of the
1713 * correct depth. But this is a major performance hit compared to
1714 * switching the colors.
1716 * The downside of switching colors is that it works only when
1717 * BlackPixel and WhitePixel fill colormap entries 0 and 1. But
1718 * since this is the 99.9% case, we'll go with it.
1720 if (image->depth == 1 && BlackPixelOfScreen(screen) != 1L)
1724 * create the pixmaps
1726 if (imageptr && image) {
1727 scaledWidth = image->width * ratio + 0.5;
1728 scaledHeight = image->height * ratio + 0.5;
1730 if (scaledWidth == 0)
1732 if (scaledHeight == 0)
1735 *pixmap_return = XCreatePixmap(display, d, scaledWidth,
1736 scaledHeight, depth);
1737 if (image->depth == 1)
1738 image->format = XYBitmap;
1742 XSetBackground (display, gc, fg);
1743 XSetForeground (display, gc, bg);
1745 _XmPutScaledImage(display, *pixmap_return, gc, image,
1747 image->width, image->height,
1748 scaledWidth, scaledHeight);
1751 XSetBackground (display, gc, bg);
1752 XSetForeground (display, gc, fg);
1755 XDestroyImage(image);
1758 if (shapeimageptr && shapeimage)
1759 XDestroyImage(shapeimage);
1761 return (ErrorStatus);
1764 static XpmColorSymbol colorSymbol = {"none", NULL, 0};
1768 * Function processXpm
1771 * Make an XPM file into the pixmap for the graphic.
1775 static enum _DtGrLoadStatus processXpm(
1776 _DtGrStream *stream,
1784 enum _DtGrColorModel color_model,
1785 Boolean allow_reduced_colors,
1786 Dimension *in_out_width,
1787 Dimension *in_out_height,
1788 unsigned short media_resolution,
1792 int *ret_num_colors,
1793 _DtGrContext *context
1799 Pixmap pixmap = NULL;
1800 XpmAttributes xpmAttr;
1805 enum _DtGrLoadStatus status = _DtGrSUCCESS;
1807 if (media_resolution == 0)
1808 return(_DtGrCONVERT_FAILURE);
1810 if (stream->type == _DtGrNONE)
1811 return(_DtGrCONVERT_FAILURE); /* stream type of _DtGrNONE */
1814 _DtHelpProcessLock();
1817 colorSymbol.pixel = background;
1819 xpmAttr.valuemask = XpmVisual | XpmReturnPixels |
1820 XpmColorSymbols | XpmColormap | XpmDepth;
1821 xpmAttr.visual = visual;
1822 xpmAttr.colorsymbols = &colorSymbol;
1823 xpmAttr.colormap = colormap;
1824 xpmAttr.numsymbols = 1;
1825 xpmAttr.depth = depth;
1826 xpmAttr.pixels = NULL;
1829 * If not color, force to black and white.
1831 if (color_model != _DtGrCOLOR)
1833 memcpy (&vis2, xpmAttr.visual, sizeof(Visual));
1835 vis2.class = StaticGray;
1836 vis2.map_entries = 2;
1839 xpmAttr.visual = &vis2;
1841 if (*in_out_width == 0 && *in_out_height == 0)
1842 ratio = ComputeRatio(media_resolution, 100);
1844 result = myXpmReadFileToPixmap (DisplayOfScreen(screen),
1846 RootWindowOfScreen(screen),
1848 ret_mask, &xpmAttr, gc,
1849 background, foreground, depth,
1853 * if we did not successfully get our icon, force the color
1854 * to black and white.
1856 if (result == XpmColorFailed && color_model != _DtGrBITONAL)
1858 if (allow_reduced_colors)
1860 color_model = _DtGrBITONAL;
1861 status = _DtGrCOLOR_REDUCE;
1865 status = _DtGrCOLOR_FAILED;
1868 } while (done == False);
1870 if (result == XpmSuccess || result == XpmColorError)
1872 *in_out_width = xpmAttr.width * ratio + 0.5;
1873 *in_out_height = xpmAttr.height * ratio + 0.5;
1874 if (*in_out_width == 0)
1876 if (*in_out_height == 0)
1878 *ret_colors = xpmAttr.pixels;
1879 *ret_num_colors = xpmAttr.npixels;
1882 * squeeze out the pixel used for the transparent color since we
1883 * don't want to free it when we free the other colors
1886 while (i < xpmAttr.npixels && xpmAttr.pixels[i] != colorSymbol.pixel)
1889 if (i < xpmAttr.npixels)
1891 for (j = i, i = i + 1; i < xpmAttr.npixels; i++, j++)
1892 xpmAttr.pixels[j] = xpmAttr.pixels[i];
1894 *ret_num_colors = j;
1897 _DtHelpProcessUnlock();
1899 if (result == XpmOpenFailed)
1900 status = _DtGrOPEN_FAILED;
1901 else if (result == XpmFileInvalid)
1902 status = _DtGrFILE_INVALID;
1903 else if (result == XpmNoMemory)
1904 status = _DtGrNO_MEMORY;
1905 else if (result == XpmColorFailed)
1906 status = _DtGrCOLOR_FAILED;
1911 /******************************************************************************
1913 * Function processGIF
1915 * Default gif converter, creates a pixmap from a file-associated or
1916 * buffer-associated stream of gif data.
1918 *****************************************************************************/
1919 static enum _DtGrLoadStatus processGIF(
1920 _DtGrStream *stream,
1928 enum _DtGrColorModel color_model,
1929 Boolean allow_reduced_colors,
1930 Dimension *in_out_width,
1931 Dimension *in_out_height,
1932 unsigned short media_resolution,
1936 int *ret_num_colors,
1937 _DtGrContext *context
1943 enum _DtGrLoadStatus status;
1944 Display *display = DisplayOfScreen(screen);
1945 Drawable drawable = RootWindowOfScreen(screen);
1949 if (media_resolution == 0)
1950 return(_DtGrCONVERT_FAILURE);
1952 if (stream->type == _DtGrNONE)
1953 return(_DtGrCONVERT_FAILURE); /* stream type of _DtGrNONE */
1955 *ret_pixmap = 0; /* Initialize the return pixmap to zero */
1958 ** The gif-to-pixmap utilities operate only on in-memory buffers,
1959 ** so if this is a buffer-based stream, simply pass the buffer, and
1960 ** if this is a file-based stream, read the file contents into a buffer
1964 if (stream->type == _DtGrBUFFER)
1966 buffer = (char *) stream->source.buffer.base;
1967 size = stream->source.buffer.size;
1971 if (stream->source.file.uncompressed_filename != NULL)
1972 stat (stream->source.file.uncompressed_filename, &stbuf);
1974 stat (stream->source.file.filename, &stbuf);
1975 size = stbuf.st_size;
1976 buffer = XtMalloc(size);
1977 fread (buffer, 1, size, stream->source.file.fileptr);
1980 /* Initialize the gif object */
1981 status = InitGifObject (&g, display, drawable, screen, depth, colormap,
1982 visual, gc, color_model, allow_reduced_colors);
1984 if (*in_out_width == 0 && *in_out_height == 0)
1985 ratio = ComputeRatio(media_resolution, 100);
1987 /* Create an X pixmap from the gif object */
1988 if ((status == _DtGrSUCCESS) || (status == _DtGrCOLOR_REDUCE))
1989 *ret_pixmap = gif_to_pixmap (&g, (unsigned char *) buffer, size,
1990 in_out_width, in_out_height,
1991 g.f_black, g.f_white, ratio);
1993 /* Set the returned colors parameters */
1994 if (*ret_pixmap != NULL)
1996 if (g.f_do_visual == DO_COLOR)
1998 *ret_num_colors = g.total_colors;
1999 *ret_colors = (Pixel *) malloc(*ret_num_colors * sizeof(Pixel));
2000 for (i=0; i<*ret_num_colors; i++)
2001 (*ret_colors)[i] = g.GifCMap[i].pixel;
2005 *ret_num_colors = g.f_total_greys;
2006 *ret_colors = (Pixel *) malloc(*ret_num_colors * sizeof(Pixel));
2007 for (i=0; i<*ret_num_colors; i++)
2008 (*ret_colors)[i] = g.GifGMap[i];
2012 /* Free up any resources associated with the gif object */
2013 DeleteGifObjectResources (&g);
2015 /* If we allocated a buffer, free it */
2016 if (stream->type == _DtGrFILE)
2019 /* Return the status */
2023 /******************************************************************************
2025 * Function processJPEG
2027 * Default jpeg converter, creates a pixmap from a file-associated or
2028 * buffer-associated stream of jpeg data.
2030 * The function first converts the jpeg stream to an XImage with a virtual
2031 * colormap using the jpeg_to_ximage call, then generates a new XImage that
2032 * uses the X colormap by calling the Do_Pseudo routine. The Do_Pseudo
2033 * routine, which is also used by the XWD converter, automatically handles X
2034 * color allocation and color model degradation where necessary. Finally,
2035 * a pixmap is generated from the XImage returned by Do_Pseudo.
2037 *****************************************************************************/
2038 static enum _DtGrLoadStatus processJPEG(
2039 _DtGrStream *stream,
2047 enum _DtGrColorModel color_model,
2048 Boolean allow_reduced_colors,
2049 Dimension *in_out_width,
2050 Dimension *in_out_height,
2051 unsigned short media_resolution,
2055 int *ret_num_colors,
2056 _DtGrContext *context
2059 enum _DtGrLoadStatus status;
2060 XImage *in_image, *out_image;
2064 int result = GR_SUCCESS;
2065 Display *dpy = DisplayOfScreen(screen);
2066 int screen_num = XScreenNumberOfScreen(screen);
2067 Drawable drawable = RootWindowOfScreen(screen);
2069 unsigned int scaledWidth,scaledHeight;
2071 if (media_resolution == 0)
2072 return(_DtGrCONVERT_FAILURE);
2074 if (*in_out_width == 0 && *in_out_height == 0)
2077 if (stream->type == _DtGrNONE)
2078 return(_DtGrCONVERT_FAILURE); /* stream type of _DtGrNONE */
2081 ** Convert the stream to an XImage with a virtual colormap
2083 status = jpeg_to_ximage (stream, screen, visual, in_out_width,
2084 in_out_height, &in_image, &colors, &ncolors,
2090 ratio = ComputeRatio(media_resolution, xres);
2093 if (status == _DtGrSUCCESS)
2095 if (in_image->depth == 1)
2098 ** Bitmap, no further image transformation necessary
2100 out_image = in_image;
2101 result = GR_SUCCESS;
2106 ** Create an output image and have Do_Pseudo allocate the needed
2107 ** pixels and store image data that uses these pixels into
2108 ** the output image.
2110 out_image = XCreateImage(dpy, visual, depth,
2111 (depth == 1) ? XYBitmap : in_image->format,
2112 in_image->xoffset, NULL,
2113 in_image->width, in_image->height,
2114 XBitmapPad(dpy), 0);
2116 out_image->data = (char *) malloc(Image_Size(out_image));
2118 result = Do_Pseudo(dpy, screen_num, colormap, ncolors, colors,
2119 color_model, in_image, out_image,
2120 ret_colors, ret_num_colors);
2124 ** If we've got a good XImage, go ahead and make a pixmap out of it
2126 if (result != GR_ALLOC_ERR)
2129 ** Create a pixmap the same size as the XImage
2132 scaledWidth = out_image->width * ratio + 0.5;
2133 scaledHeight = out_image->height * ratio + 0.5;
2135 if (scaledWidth == 0)
2137 if (scaledHeight == 0)
2140 *ret_pixmap = XCreatePixmap (dpy, drawable, scaledWidth,
2141 scaledHeight, depth);
2145 ** Copy the XImage into the pixmap and set the other
2146 ** return parameters.
2148 _XmPutScaledImage(dpy, *ret_pixmap, gc, out_image, 0, 0, 0, 0,
2149 out_image->width, out_image->height,
2150 scaledWidth, scaledHeight);
2152 *in_out_width = scaledWidth;
2153 *in_out_height = scaledHeight;
2154 status = _DtGrSUCCESS;
2157 status = _DtGrNO_MEMORY;
2159 if (out_image != in_image)
2160 XDestroyImage (out_image);
2163 status = _DtGrNO_MEMORY;
2166 ** Free the colors array and the initial XImage
2168 XFree ((char *) colors);
2169 XDestroyImage (in_image);
2175 /******************************************************************************
2177 * Function destroyTiffContext
2179 * Default tiff context destructor, destroys the ilXWC object pointed to
2180 * by context->context and frees the context->image_type string.
2182 *****************************************************************************/
2183 static void destroyTiffContext(
2184 _DtGrContext *context)
2186 if (context != NULL)
2188 if (context->context != NULL)
2190 _DtHelpProcessLock();
2191 ilDestroyObject ((ilObject) context->context);
2192 _DtHelpProcessUnlock();
2194 if (context->image_type != NULL)
2195 XtFree(context->image_type);
2199 /******************************************************************************
2201 * Function DetermineImageType
2203 * Determines the image type of the specified stream and copies the
2204 * string representing that image type into the image_type buffer.
2206 * If the stream is a buffer, the buffer is passed to DtDtsBufferToData
2207 * in hopes that the file might be identified through content criteria.
2209 * If the stream is a file, the following checks are made:
2211 * 1. The file name extension is checked against a list of known image file
2213 * 2. The filename is passed to DtDtsFileToDataType in hopes that the file
2214 * type might be identified through filename extension or content
2216 * 3. If the file was uncompressed into a temporary file, the temporary
2217 * filename is passed to DtDtsFileToDataType in hopes that the file
2218 * type might be identified through content criteria.
2220 * If none of these checks are successful, _DtCONVERT_FAILURE is returned.
2221 * Otherwise, _DtGrSUCCESS is returned.
2223 *****************************************************************************/
2224 static enum _DtGrLoadStatus DetermineImageType(
2225 _DtGrStream *stream,
2231 if (stream->type == _DtGrFILE)
2233 /* First try to match the file name extension to a known mapping */
2234 if (stream->source.file.filename != NULL)
2236 /* Get the filename extension */
2237 if (_DtHelpCeStrrchr(stream->source.file.filename, ".",
2238 MB_CUR_MAX, &ext) == 0)
2240 ext++; /* Increment past the dot */
2241 while (img_extensions[i] != NULL)
2243 if (strcmp(ext, img_extensions[i]) == 0)
2246 strcpy (image_type,img_extensions[++i]);
2247 return (_DtGrSUCCESS);
2249 /* Skip two ahead to the next file extension name */
2256 * Didn't work, see if CDE datatyping can determine the image type.
2257 * First try the filename, then try the uncompressed temporary
2258 * filename, if it exists.
2260 if ((ext = DtDtsFileToDataType(stream->source.file.filename)) == NULL)
2261 if (stream->source.file.uncompressed_filename != NULL)
2262 ext = DtDtsFileToDataType(
2263 stream->source.file.uncompressed_filename);
2265 /* If successful, save the image type and return */
2268 strcpy (image_type, ext);
2269 DtDtsFreeDataType(ext);
2270 return (_DtGrSUCCESS);
2273 else if (stream->type == _DtGrBUFFER)
2275 /* See if the CDE datatyping mechanism can determine the image type */
2276 ext = DtDtsBufferToDataType (stream->source.buffer.base,
2277 stream->source.buffer.size,
2280 /* If successful, save the image type and return */
2283 strcpy (image_type, ext);
2284 DtDtsFreeDataType(ext);
2285 return (_DtGrSUCCESS);
2289 /* Couldn't figure out the type, return failure */
2290 return (_DtGrCONVERT_FAILURE);
2293 /******************************************************************************
2295 * Function GetConverterAndDestructor
2297 * This function returns the converter and context destructor functions for
2298 * the specified image type. The registry of default image types is searched
2299 * first, followed by the registry of new image types, until a match is made.
2300 * The function returns _DtGrSUCCESS if the image_type has been registered
2301 * and _DtGrCONVERT_FAILURE if it has not.
2303 *****************************************************************************/
2304 static enum _DtGrLoadStatus GetConverterAndDestructor(
2306 _DtGrLoadProc *converter,
2307 _DtGrDestroyContextProc *destructor)
2311 /* No image_type string, return failure */
2312 if (image_type == NULL)
2313 return (_DtGrCONVERT_FAILURE);
2315 /* Search the default image type registry for the specified image type */
2316 _DtHelpProcessLock();
2317 for (i=0; i<registry_count; i++)
2319 if (strcmp (registry[i].image_type, image_type) == 0)
2321 /* Found it, return the converter and destructor */
2322 *converter = registry[i].convert_proc;
2323 *destructor = registry[i].destroy_context_proc;
2324 _DtHelpProcessUnlock();
2325 return (_DtGrSUCCESS);
2329 /* Search the new image type registry for the specified image type */
2330 for (i=0; i<new_registry_count; i++)
2332 if (strcmp (new_registry[i].image_type, image_type) == 0)
2334 /* Found it, return the converter */
2335 *converter = new_registry[i].convert_proc;
2336 *destructor = registry[i].destroy_context_proc;
2337 _DtHelpProcessUnlock();
2338 return (_DtGrSUCCESS);
2341 _DtHelpProcessUnlock();
2343 /* Image type wasn't registered, return failure */
2344 return (_DtGrCONVERT_FAILURE);
2347 /******************************************************************************
2351 *****************************************************************************/
2352 /******************************************************************************
2354 * Function _DtHelpProcessGraphic
2357 * Get the pixmap for the graphic.
2359 *****************************************************************************/
2361 _DtHelpProcessGraphic(
2368 Dimension *def_pix_width,
2369 Dimension *def_pix_height,
2370 _DtGrContext *context,
2376 unsigned short media_resolution,
2384 unsigned int pixWidth = 0;
2385 unsigned int pixHeight = 0;
2386 Dimension pWidth, pHeight;
2388 Pixmap pix = NULL, mask = NULL;
2390 Screen *scrptr = ScreenOfDisplay (dpy, screen);
2391 static enum _DtGrColorModel ForceColor = _DtGrCOLOR;
2392 static Boolean first_time = TRUE;
2395 * initialize the return values
2402 * Initialize the Force Variable if this is the first time
2404 _DtHelpProcessLock();
2409 char *xrmName = NULL;
2410 char *xrmClass = NULL;
2414 ForceColor = _DtGrCOLOR;
2416 XtGetApplicationNameAndClass (dpy, &ptr, &ptr2);
2417 xrmName = malloc (strlen (ptr) + 14);
2418 xrmClass = malloc (strlen (ptr2) + 14);
2419 if (xrmName && xrmClass)
2421 strcpy (xrmName , ptr);
2422 strcat (xrmName , ".helpColorUse");
2424 strcpy (xrmClass, ptr2);
2425 strcat (xrmClass, ".HelpColorUse");
2427 if (XrmGetResource (XtDatabase (dpy), xrmName, xrmClass,
2428 &retStrType, &retValue) == True)
2430 ptr = (char *) retValue.addr;
2432 * check for GreyScale
2434 if (*ptr == 'G' || *ptr == 'g')
2435 ForceColor = _DtGrGRAY_SCALE;
2437 * check for BlackWhite
2439 else if (*ptr == 'B' || *ptr == 'b')
2440 ForceColor = _DtGrBITONAL;
2448 * choose the correct visual type to use
2450 if (ForceColor == _DtGrCOLOR &&
2451 (visual->class == GrayScale || visual->class == StaticGray))
2452 ForceColor = _DtGrGRAY_SCALE;
2454 if (ForceColor != _DtGrBITONAL && depth == 1)
2455 ForceColor = _DtGrBITONAL;
2459 _DtHelpProcessUnlock();
2461 if (filename != NULL)
2465 /* Open the file and associate with a stream */
2466 result = _DtGrOpenFile(&stream, filename);
2472 /* Create a pixmap from the image data stream */
2473 _DtGrLoad(&stream, NULL, scrptr, depth, colormap, visual,
2474 fore_ground, back_ground, gc, ForceColor, TRUE, &pWidth,
2475 &pHeight, media_resolution, &pix, &mask, ret_colors,
2476 ret_number, context);
2478 pixHeight = pHeight;
2479 /* Close the stream and the file associated with it */
2480 _DtGrCloseStream( &stream );
2488 * Try to get a localized pixmap
2490 * This is a cached pixmap.....
2491 * Make sure XFreePixmaps does not free this one.
2493 if (*def_pix == NULL)
2495 *def_pix = XmGetPixmap(scrptr, "Dthgraphic", fore_ground, back_ground);
2496 if (*def_pix != XmUNSPECIFIED_PIXMAP)
2500 unsigned int border;
2503 if (XGetGeometry(dpy, *def_pix, &root_id, &x, &y,
2504 &pixWidth, &pixHeight, &border, &depth) == 0)
2506 XmDestroyPixmap(scrptr, *def_pix);
2514 * couldn't get a localized pixmap, go with a build in default
2516 if (*def_pix == NULL)
2518 pixWidth = Missing_bm_width;
2519 pixHeight = Missing_bm_height;
2520 *def_pix = XCreatePixmapFromBitmapData ( dpy, drawable,
2521 (char *) Missing_bm_bits,
2522 pixWidth, pixHeight,
2523 fore_ground, back_ground, depth);
2526 *def_pix_width = (Dimension) pixWidth;
2527 *def_pix_height = (Dimension) pixHeight;
2531 pixWidth = *def_pix_width;
2532 pixHeight = *def_pix_height;
2535 *width = (Dimension) pixWidth;
2536 *height = (Dimension) pixHeight;
2542 /******************************************************************************
2544 * Function _DtGrLoad
2546 * Determines the image type of the specified stream and calls the appropriate
2547 * imagetype-to-pixmap converter function. If the conversion is successful
2548 * and the caller passed the address of a pointer to NULL in the image_type
2549 * parameter, a copy of the image type string is allocated and stored at this
2550 * address. The caller is responsible for freeing this string. The caller
2551 * is also responsible for freeing the values passed back in the ret_pixmap,
2552 * ret_mask, ret_colors, and context parameters. The _DtGrLoad function
2553 * returns _DtGrCONVERT_FAILURE if the appropriate converter could not be
2554 * determined, otherwise it returns the value returned by the converter.
2556 *****************************************************************************/
2557 enum _DtGrLoadStatus _DtGrLoad(
2558 _DtGrStream *stream,
2567 enum _DtGrColorModel color_model,
2568 Boolean allow_reduced_colors,
2569 Dimension *in_out_width,
2570 Dimension *in_out_height,
2571 unsigned short media_resolution,
2575 int *ret_num_colors,
2576 _DtGrContext *context
2579 enum _DtGrLoadStatus status;
2580 _DtGrLoadProc converter;
2581 _DtGrDestroyContextProc destructor;
2582 char buf[20],*itype;
2584 /* Determine the image type */
2585 if ((image_type != NULL) && (*image_type != NULL))
2586 itype = *image_type; /* Caller specified image type */
2589 /* Image type not specified by caller, try to figure it out */
2590 if ((status = DetermineImageType(stream, buf)) != _DtGrSUCCESS)
2591 return (status); /* Return failure if image type is unknown */
2595 /* Look up the proper converter for this image type */
2596 if ((status=GetConverterAndDestructor(itype, &converter, &destructor)) ==
2599 /* Call the converter */
2600 if (converter != NULL)
2602 status = (*converter)(stream, screen, depth, colormap, visual,
2603 foreground, background, gc, color_model,
2604 allow_reduced_colors, in_out_width,
2605 in_out_height, media_resolution, ret_pixmap,
2606 ret_mask, ret_colors, ret_num_colors,
2610 status = _DtGrCONVERT_FAILURE;
2613 /* Return a copy of the image type string if successful */
2614 if (status == _DtGrSUCCESS || status == _DtGrCOLOR_REDUCE)
2615 if ((image_type != NULL) && (*image_type == NULL) && (itype != NULL))
2616 *image_type = XtNewString(itype);
2618 /* Return the conversion status */
2622 /******************************************************************************
2624 * Function _DtGrDestroyContext
2626 * Obtains and calls the context destructor function for the image type
2627 * indicated by the context parameter.
2629 *****************************************************************************/
2630 void _DtGrDestroyContext(
2631 _DtGrContext *context)
2633 _DtGrLoadProc converter;
2634 _DtGrDestroyContextProc destructor;
2636 if (GetConverterAndDestructor(context->image_type, &converter,
2637 &destructor) == _DtGrSUCCESS)
2639 if (destructor != NULL)
2640 (*destructor)(context);
2644 /******************************************************************************
2646 * Function _DtGrRegisterConverter
2648 * Registers a converter and context destructor function for the specified
2649 * image type. If the image_type has not been registered, a new record for
2650 * it is created in the new image type registry. If the image_type has been
2651 * registered, the current converter and context destructor functions are
2652 * replaced by those specified by the caller. If the caller passes valid
2653 * addresses in the current_convert_proc and current_destroy_proc parameters,
2654 * the current converter and context destructor functions will be saved there
2655 * first so that the caller may restore them at a later time.
2657 *****************************************************************************/
2658 void _DtGrRegisterConverter(
2660 _DtGrLoadProc convert_proc,
2661 _DtGrDestroyContextProc destroy_context_proc,
2662 _DtGrLoadProc *current_convert_proc,
2663 _DtGrDestroyContextProc *current_destroy_proc)
2667 if (image_type == NULL)
2670 /* Search the default converter registry for the specified image type */
2671 _DtHelpProcessLock();
2672 for (i=0; i<registry_count; i++)
2674 if (strcmp (registry[i].image_type, image_type) == 0)
2676 /* Found it, save the current procs, then replace them */
2677 /* with the new ones and return */
2678 if (current_convert_proc != NULL)
2679 *current_convert_proc = registry[i].convert_proc;
2680 if (current_destroy_proc != NULL)
2681 *current_destroy_proc = registry[i].destroy_context_proc;
2682 registry[i].convert_proc = convert_proc;
2683 registry[i].destroy_context_proc = destroy_context_proc;
2684 _DtHelpProcessUnlock();
2689 /* Search the new converter registry for the specified image type */
2690 for (i=0; i<new_registry_count; i++)
2692 if (strcmp (new_registry[i].image_type, image_type) == 0)
2694 /* Found it, save the current procs, then replace them */
2695 /* with the new ones and return */
2696 if (current_convert_proc != NULL)
2697 *current_convert_proc = new_registry[i].convert_proc;
2698 if (current_destroy_proc != NULL)
2699 *current_destroy_proc = new_registry[i].destroy_context_proc;
2700 new_registry[i].convert_proc = convert_proc;
2701 new_registry[i].destroy_context_proc = destroy_context_proc;
2702 _DtHelpProcessUnlock();
2707 /* If we make it here, we've got a new image type to register */
2708 new_registry = (_DtGrRegistryRec *) XtRealloc ((char *) new_registry,
2709 sizeof(_DtGrRegistryRec) * (new_registry_count + 1));
2710 new_registry[new_registry_count].image_type = XtNewString (image_type);
2711 new_registry[new_registry_count].convert_proc = convert_proc;
2712 new_registry[new_registry_count].destroy_context_proc =
2713 destroy_context_proc;
2714 new_registry_count++;
2715 _DtHelpProcessUnlock();
2717 /* Newly registered type, so return NULL for current function params */
2718 if (current_convert_proc != NULL)
2719 *current_convert_proc = NULL;
2720 if (current_destroy_proc != NULL)
2721 *current_destroy_proc = NULL;
2726 /******************************************************************************
2728 * Input stream functions
2730 * These functions allow the creation and manipulation of a stream that
2731 * can be associated with either a file or a buffer. They are intended to
2732 * be used by image data to pixmap converter functions that need to handle
2733 * both image files and in-memory buffers containing file data.
2735 *****************************************************************************/
2737 /******************************************************************************
2739 * Function _DtGrOpenFile
2741 * Opens a file for reading and associates it with the specified stream. If
2742 * the file is compressed, the function uncompresses it prior to opening.
2743 * Returns 0 for success, -1 or the value of errno as set by fopen for
2746 *****************************************************************************/
2748 _DtGrStream *stream,
2754 return (-1); /* Failure */
2756 /* Uncompress the file if necessary and obtain the new filename */
2757 if (_DtHelpCeGetUncompressedFileName(path, &fname) == -1)
2759 stream->type = _DtGrNONE;
2760 return (-1); /* Failure */
2764 stream->source.file.fileptr = fopen(fname,"r");
2765 if (stream->source.file.fileptr == NULL)
2767 /* Failure, couldn't open the file */
2768 stream->type = _DtGrNONE;
2769 if ((fname != path) && (fname != NULL))
2777 /* Set the stream type and copy the filename */
2778 stream->type = _DtGrFILE;
2779 stream->source.file.filename = XtNewString(path);
2781 /* If the file was uncompressed and renamed, save the new name */
2783 stream->source.file.uncompressed_filename = NULL;
2785 stream->source.file.uncompressed_filename = fname;
2787 return(0); /* Success */
2790 /******************************************************************************
2792 * Function _DtGrOpenBuffer
2794 * Associates the specified in-memory buffer with the specified stream.
2795 * The function returns 0 for success and the EINVAL error code for failure.
2797 *****************************************************************************/
2798 int _DtGrOpenBuffer(
2799 _DtGrStream *stream,
2803 if ((stream == NULL) || (buffer == NULL) || (buffer_size < 0))
2806 stream->type = _DtGrNONE;
2807 return(EINVAL); /* Failure */
2810 /* Set the appropriate stream fields */
2811 stream->type = _DtGrBUFFER;
2812 stream->source.buffer.base = buffer;
2813 stream->source.buffer.size = buffer_size;
2814 stream->source.buffer.current = (char *)buffer;
2815 stream->source.buffer.end = (char *)(buffer + buffer_size - 1);
2816 return(0); /* Success */
2819 /******************************************************************************
2821 * Function _DtGrCloseStream
2823 * The function closes the specified stream by setting the stream type to
2824 * _DtGrNONE. If the stream is associated with a file, then the file is
2825 * closed and the filename in the stream structure is freed. If the file
2826 * required decompression, then the uncompressed file is unlinked and the
2827 * uncompressed filename is freed.
2829 *****************************************************************************/
2830 int _DtGrCloseStream(
2831 _DtGrStream *stream)
2835 if ((stream == NULL) || (stream->type == _DtGrNONE))
2836 return(EOF); /* Failure */
2838 if (stream->type == _DtGrFILE)
2840 /* Close the file and free the filename */
2841 status = fclose(stream->source.file.fileptr);
2842 if (stream->source.file.filename != NULL)
2843 XtFree(stream->source.file.filename);
2844 if (stream->source.file.uncompressed_filename != NULL)
2846 /* Unlink the uncompressed file and free the filename */
2847 unlink(stream->source.file.uncompressed_filename);
2848 free(stream->source.file.uncompressed_filename);
2851 else if (stream->type == _DtGrBUFFER)
2853 status = 0; /* Success */
2856 stream->type = _DtGrNONE;
2861 /******************************************************************************
2863 * Function _DtGrRead
2865 * Stream version of fread, reads data from a stream into a buffer. If the
2866 * stream is file-associated, a call to fread is made. If the stream is
2867 * buffer-associated, an analogous operation is performed on the stream
2868 * buffer. The number of items read from the stream is returned to the caller.
2870 *****************************************************************************/
2875 _DtGrStream *stream)
2877 size_t num_items_read;
2881 if ((stream == NULL) || (stream->type == _DtGrNONE))
2884 if (stream->type == _DtGrFILE)
2886 return (fread(buffer, size, num_items, stream->source.file.fileptr));
2888 else if (stream->type == _DtGrBUFFER)
2890 /* This code mirrors that of fread in libc */
2892 if (size <= 0 || num_items <= 0)
2895 for (nleft = num_items * size; ; )
2897 if (stream->source.buffer.current > stream->source.buffer.end)
2899 /* past end of stream */
2900 if (stream->source.buffer.current ==
2901 stream->source.buffer.end + 1)
2902 return (num_items - (nleft + size - 1)/size);
2903 stream->source.buffer.current--;
2905 n = (nleft < stream->source.buffer.end -
2906 stream->source.buffer.current + 1 ? nleft :
2907 stream->source.buffer.end -
2908 stream->source.buffer.current + 1);
2909 /* Copy the items into the caller-supplied buffer */
2910 buffer = (char *)memcpy(buffer,
2911 (void *) stream->source.buffer.current,
2913 stream->source.buffer.current += n;
2914 if ((nleft -= n) == 0)
2920 /******************************************************************************
2922 * Function _DtGrSeek
2924 * Stream version of fseek, repositions the file or buffer pointer of a
2925 * stream. If the stream is file-associated, the return value is the value
2926 * returned by fseek. If the stream is buffer-associated, 0 is returned if
2927 * the requested position is inside the buffer, -1 if it is not.
2929 *****************************************************************************/
2931 _DtGrStream *stream,
2937 if ((stream == NULL) || (stream->type == _DtGrNONE))
2938 return(-1); /* Failure */
2940 if (stream->type == _DtGrFILE)
2942 return (fseek(stream->source.file.fileptr,offset,whence));
2944 else if (stream->type == _DtGrBUFFER)
2949 newpos = (long)stream->source.buffer.base + offset;
2952 newpos = (long)stream->source.buffer.current + offset;
2955 newpos = (long)stream->source.buffer.end + 1 + offset;
2961 if ((newpos >= (long)stream->source.buffer.base) &&
2962 (newpos <= (long)stream->source.buffer.end))
2964 /* New position is within buffer, reposition pointer */
2965 stream->source.buffer.current = (char *)newpos;
2966 return(0); /* Success */
2969 return(-1); /* Failure */
2973 /******************************************************************************
2975 * Function _DtGrGetChar
2977 * Stream version of fgetc, reads a character from a stream and advances the
2978 * stream position. The next byte in the stream is returned, or EOF if an
2979 * error occurs or the end of the stream is reached.
2981 *****************************************************************************/
2983 _DtGrStream *stream)
2985 if ((stream == NULL) || (stream->type == _DtGrNONE))
2988 if (stream->type == _DtGrFILE)
2990 return (fgetc(stream->source.file.fileptr));
2992 else if (stream->type == _DtGrBUFFER)
2994 if (stream->source.buffer.current > stream->source.buffer.end)
2997 return ((unsigned char) *(stream->source.buffer.current++));
3001 /******************************************************************************
3003 * Function _DtGrGetString
3005 * Stream version of fgets, reads a string from a stream and advances the
3006 * stream position. If an error occurs or the end of the stream is
3007 * encountered and no characters have been read, no characters are transferred
3008 * to the buffer and a NULL pointer is returned. Otherwise, the buffer is
3011 *****************************************************************************/
3012 char *_DtGrGetString(
3015 _DtGrStream *stream)
3017 char *p, *save = buffer;
3020 if ((stream == NULL) || (stream->type == _DtGrNONE))
3021 return(NULL); /* Failure */
3023 if (stream->type == _DtGrFILE)
3025 return (fgets(buffer,num_bytes,stream->source.file.fileptr));
3027 else if (stream->type == _DtGrBUFFER)
3029 /* This code mirrors that of fgets in libc */
3030 for (num_bytes--; num_bytes > 0; num_bytes -= i)
3032 if (stream->source.buffer.current > stream->source.buffer.end)
3034 if (stream->source.buffer.current ==
3035 stream->source.buffer.end + 1)
3039 break; /* no more data */
3041 stream->source.buffer.current--;
3043 i = (num_bytes < stream->source.buffer.end -
3044 stream->source.buffer.current + 1 ? num_bytes :
3045 stream->source.buffer.end -
3046 stream->source.buffer.current + 1);
3047 /* Copy the data into the buffer */
3048 if ((p = memccpy((void *)buffer,
3049 (void *)stream->source.buffer.current,
3050 (int)'\n',(size_t)i)) != NULL)
3053 stream->source.buffer.current += i;
3055 break; /* found '\n' in buffer */