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 libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: ilX.c /main/11 1996/11/12 05:02:17 pascale $ */
24 /**---------------------------------------------------------------------
26 *** (c)Copyright 1991 Hewlett-Packard Co.
28 *** RESTRICTED RIGHTS LEGEND
29 *** Use, duplication, or disclosure by the U.S. Government is subject to
30 *** restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
31 *** Technical Data and Computer Software clause in DFARS 252.227-7013.
32 *** Hewlett-Packard Company
33 *** 3000 Hanover Street
34 *** Palo Alto, CA 94304 U.S.A.
35 *** Rights for non-DOD U.S. Government Departments and Agencies are as set
36 *** forth in FAR 52.227-19(c)(1,2).
38 ***-------------------------------------------------------------------*/
41 #include "ilcontext.h"
45 #include <X11/Xutil.h>
46 #include "ilpipelem.h"
49 #include <Xm/XmPrivate.h>
51 #define X_COLOR_MAX 65535 /* max value for X colormap RGB
54 /* Buffer allocation checks. Buffers are allocated for example when
55 writing to a 24 bit drawable: the pipe image pixels are converted
56 from 3 bytes to 4 bytes (CARD32).
58 #define MAX_IMAGE_BUFFER_SIZE 100000 /* force strips if larger than
60 #define BEST_IMAGE_BUFFER_SIZE 50000 /* to strips of this size */
62 /* Masks for ilFreeColorData(); see below.
64 #define IL_FREE_XCOLORS (1<<0)
65 #define IL_FREE_XGRAYS (1<<1)
67 /* Codes for view of X , in "ilXWCRec.i.visualType". When the visual is
68 unsupported or an insufficient # of colors can be allocated from the
69 colormap, the drawable defaults to IL_XWC_BITONAL. Images rendered
70 to such an XWC are converted to bitonal, then XPutImage() of an
71 XYBitmap is done - the XWC GC's foreground/background colors are used
74 #define IL_X_MAX_VISUAL_TYPE 3 /* max value of IL_XWC_BITONAL
77 /* Default # of grays or dither colors to allocate for pseudo-color. */
78 #define IL_DEFAULT_X_GRAYS 32
83 /* Internals of an XWC (X Write Context), an IL object created by
85 An XWC is associated with the visual "visual" and "colormap".
86 "i" contains basic information returned by ilQueryXWC().
87 If pColors is non-null, it points to a list of length "nColors",
88 of colors allocated from "colormap". "pad" in each colorcell is
90 == 0 if color not allocated, else color was sucessfully allocated.
91 If non-null, colorMapImage is an image for mapping to X images
93 For example, for 8 bit pseudo-color when 484 color handling is used,
94 "pColors" points to 128 colors, and "colorMapImage" points to a 256
95 pixel image where each entry is the pixel to use for color
96 (red*4*8 + green*8 + blue).
97 If "colorMapImage" is null then the alloc failed or has not been tried.
98 Note: above applies also to Direct/TrueColor visuals, with the same
100 The above also applies to the "gray" fields, with the "gray" names.
103 ilObjectRec o; /* std header: MUST BE FIRST */
104 ilXWCInfo i; /* see above */
105 XVisualInfo visualInfo; /* X info on "visual" */
106 XColor *pColors; /* ptr to list of allocated
108 int nColors; /* size of *pColors list */
109 ilClientImage colorMapImage; /* see above */
110 ilBool mapDirect; /* ilMap(colorMapImage),
112 XColor *pGrays; /* ptr to list of allocated grays
114 int nGrays; /* size of *pGrays list */
115 ilClientImage grayMapImage; /* same as colorMapImage, but for
117 } ilXWCRec, *ilXWCPtr;
119 typedef ilError (*executeFunctionType)();
121 /* ------------------------ ilFreeColorData ---------------------- */
122 /* Free the color list and translation table in the given XWC if
123 present. "freeMasks" indicates which should be freed:
124 IL_FREE_XCOLORS/XGRAYS, or ~0 for everything.
126 static void ilFreeColorData (
128 unsigned long freeMask
134 /* If color list present: free each color if allocated (pad != 0);
137 if (freeMask & IL_FREE_XCOLORS) {
139 for (i = 0, pColor = pXWC->pColors; i < pXWC->nColors; i++) {
141 XFreeColors (pXWC->i.display, pXWC->i.colormap,
142 &pColor->pixel, 1, 0L);
145 IL_FREE (pXWC->pColors);
146 pXWC->pColors = (XColor *)NULL;
149 if (pXWC->colorMapImage) {
150 ilDestroyObject (pXWC->colorMapImage);
151 pXWC->colorMapImage = (ilClientImage)NULL;
155 /* Same for gray list
157 if (freeMask & IL_FREE_XGRAYS) {
159 for (i = 0, pColor = pXWC->pGrays; i < pXWC->nGrays; i++) {
161 XFreeColors (pXWC->i.display, pXWC->i.colormap,
162 &pColor->pixel, 1, 0L);
165 IL_FREE (pXWC->pGrays);
166 pXWC->pGrays = (XColor *)NULL;
169 if (pXWC->grayMapImage) {
170 ilDestroyObject (pXWC->grayMapImage);
171 pXWC->grayMapImage = (ilClientImage)NULL;
176 /* ----------------------- ilDestroyXWC -------------------------- */
177 /* Destroy() function for XWC objects. Free the color list if
179 The GC for the default XWC will be destroyed when the context is
180 freed, by ilXDestroyContext() below.
182 static void ilDestroyXWC (
186 ilObject object = (ilObject)pPrivate;
189 pXWC = (ilXWCPtr)object;
191 /* ~ on signed integer is not recommended, play it safe here */
192 ilFreeColorData (pXWC, ~(0UL));
196 /* --------------------- ilGammaCorrect -------------------------- */
197 /* Returns a value from 0..scaleValue, given "value", from
198 0.."maxValue" - 1, scaled up to "scaleValue" (e.g. 65535 for
200 Currently a misnomer - not doing any gamma correction
203 static int ilGammaCorrect (
213 else if (value == (maxValue - 1))
214 allocValue = scaleValue;
216 allocValue = value * scaleValue / (maxValue-1);
219 else if (allocValue > scaleValue)
220 allocValue = scaleValue;
226 /* --------------------- ilAllocateXDitherColors ------------------ */
227 /* Internal function to ilCreateXWC(). Attempts to allocate enough
228 colors in pXWC->i.colormap to support the visual as a 484
230 An error code is returned to the given context if an error
231 (e.g. malloc) error occurs; IL_OK if the grays could not be
232 alloc'd (but false is returned).
234 static ilBool ilAllocateXDitherColors (
240 int i, red, green, blue;
243 ilImageInfo imageInfo, *pImageInfo;
245 context->error = IL_OK; /* assume no errors */
246 if (pXWC->colorMapImage)
247 return TRUE; /* already alloc'd; EXIT */
249 /* Allocate a client image to use as LUT for mapping to X's
251 Point pTranslate to the allocated pixels.
253 imageInfo.pDes = IL_DES_GRAY;
254 imageInfo.pFormat = IL_FORMAT_BYTE;
255 imageInfo.width = 256;
256 imageInfo.height = 1;
257 imageInfo.clientPixels = FALSE;
258 pXWC->colorMapImage = ilCreateClientImage (context, &imageInfo, 0);
259 if (!pXWC->colorMapImage)
260 return FALSE; /* EXIT */
261 ilQueryClientImage (pXWC->colorMapImage, &pImageInfo, 0);
262 pTranslate = pImageInfo->plane[0].pPixels;
264 pXWC->nColors = NRED * NGREEN * NBLUE;
265 pXWC->pColors = (XColor *)IL_MALLOC (pXWC->nColors * sizeof(XColor));
266 if (!pXWC->pColors) {
267 ilDestroyObject (pXWC->colorMapImage);
268 pXWC->colorMapImage = (ilClientImage)NULL;
269 context->error = IL_ERROR_MALLOC;
270 return FALSE; /* EXIT */
272 for (i = 0, pColor = pXWC->pColors; i < pXWC->nColors; i++, pColor++)
273 pColor->pad = FALSE; /* init pad, in case below fails */
275 /* Allocate 484 colors (128 in all) */
276 pColor = pXWC->pColors;
277 for (red = 0; red < NRED; red++)
278 for (green = 0; green < NGREEN; green++)
279 for (blue = 0; blue < NBLUE; blue++) {
280 pColor->red = ilGammaCorrect (X_COLOR_MAX, red, NRED);
281 pColor->green = ilGammaCorrect (X_COLOR_MAX, green, NGREEN);
282 pColor->blue = ilGammaCorrect (X_COLOR_MAX, blue, NBLUE);
283 if (!XAllocColor (pXWC->i.display, pXWC->i.colormap, pColor)) {
284 ilFreeColorData (pXWC, IL_FREE_XCOLORS);
287 pTranslate [red*(NGREEN*NBLUE) + green*NBLUE + blue] =
289 pColor->pad = TRUE; /* mark as alloc'd */
293 return TRUE; /* colors successfully alloc'd */
297 /* ---------------------------- ilAllocateXGrays ---------------------- */
298 /* Allocate "nGrays" from the colormap associated with the given XWC or
300 The grays are ramped evenly from 0..nGrays-1. If there are "nGrays"
301 existing grays, they are used, else if not nGrays, they are
303 An error code is returned to the given context if an error
304 (e.g. malloc) error occurs; IL_OK if the grays could not be alloc'd
305 (but false is returned).
307 static ilBool ilAllocateXGrays (
316 ilImageInfo imageInfo, *pImageInfo;
319 /* Use the grays if the same number, else deallocate them.
321 context->error = IL_OK; /* assume no errors */
323 if (pXWC->nGrays == nGrays)
325 else ilFreeColorData (pXWC, IL_FREE_XGRAYS);
329 return FALSE; /* EXIT */
331 /* Allocate a client image to use as LUT for mapping to X's colors.
332 Point pTranslate to the allocated pixels.
334 imageInfo.pDes = IL_DES_GRAY;
335 imageInfo.pFormat = IL_FORMAT_BYTE;
336 imageInfo.width = 256;
337 imageInfo.height = 1;
338 imageInfo.clientPixels = FALSE;
339 pXWC->grayMapImage = ilCreateClientImage (context, &imageInfo, 0);
340 if (!pXWC->grayMapImage)
341 return FALSE; /* EXIT */
342 ilQueryClientImage (pXWC->grayMapImage, &pImageInfo, 0);
343 pTranslate = pImageInfo->plane[0].pPixels;
345 pXWC->nGrays = nGrays;
346 pXWC->pGrays = (XColor *)IL_MALLOC (pXWC->nGrays * sizeof(XColor));
348 ilDestroyObject (pXWC->grayMapImage);
349 pXWC->colorMapImage = (ilClientImage)NULL;
350 context->error = IL_ERROR_MALLOC;
351 return FALSE; /* EXIT */
353 for (i = 0, pColor = pXWC->pGrays; i < pXWC->nGrays; i++, pColor++)
354 pColor->pad = FALSE; /* init pad, in case below fails */
356 /* Allocate the grays; return error on any failure. */
357 for (i = 0; i < nGrays; i++) {
358 pColor = &pXWC->pGrays [i];
359 pColor->red = pColor->green = pColor->blue =
360 ilGammaCorrect (X_COLOR_MAX, i, nGrays);
361 if (!XAllocColor (pXWC->i.display, pXWC->i.colormap, pColor)) {
363 ilFreeColorData (pXWC, IL_FREE_XGRAYS);
364 return FALSE; /* EXIT */
369 /* Grays allocated ok; spread the allocated colors over the whole 256
370 area. In effect, color-slam all 256-level gray images into nGrays.
371 NOTE: gray images with other than 256 levels could be supported in
374 spreadFactor = ((double)(nGrays - 1)) / (double)255;
375 pColor = pXWC->pGrays;
376 for (i = 0; i < 256; i++) {
377 index = spreadFactor * (double)i + 0.5;
378 if (index > (nGrays - 1))
380 pTranslate [i] = pColor [index].pixel;
387 /* ---------------------- ilAllocateXDirectColors --------------------- */
388 /* Allocate "nLevels" levels of each of RGB for a DirectColor or a
390 "nLevels" should be passed as 256; it becomes 1/2 of that if failure
391 occurs this function recurses on failure until an unacceptable # of
394 static ilBool ilAllocateXDirectColors (
399 int i, j, pixel, red, green, blue, nReplicate;
402 ilImageInfo imageInfo, *pImageInfo;
404 #define MIN_DIRECT_LEVELS 32 /* min # of acceptable levels */
406 if (pXWC->colorMapImage)
407 return TRUE; /* already alloc'd; EXIT */
409 /* Create a 256x1 3 byte/pixel map image. */
410 context = pXWC->o.p.context;
411 imageInfo.pDes = IL_DES_RGB;
412 imageInfo.pFormat = IL_FORMAT_3BYTE_PIXEL;
413 imageInfo.width = 256;
414 imageInfo.height = 1;
415 imageInfo.clientPixels = FALSE;
416 pXWC->colorMapImage = ilCreateClientImage (context, &imageInfo, 0);
417 if (!pXWC->colorMapImage)
419 ilQueryClientImage (pXWC->colorMapImage, &pImageInfo, 0);
420 pTranslate = pImageInfo->plane[0].pPixels;
422 /* Try to allocate nLevels read-only levels each of RGB, in a logical
423 ramp order. Set pXWC->mapDirect to false if pixel value != RGB
424 value, in which case pipe image pixels must be ilMap()'d to X
426 If can't allocate, try to allocate nLevels/2 unless that is too
427 few colors, in which we fail. Spread the X pixels into the 256
430 pXWC->nColors = nLevels;
431 pXWC->pColors = (XColor *)IL_MALLOC_ZERO (pXWC->nColors * sizeof(XColor));
432 if (!pXWC->pColors) {
433 ilDestroyObject (pXWC->colorMapImage);
434 pXWC->colorMapImage = (ilClientImage)NULL;
435 context->error = IL_ERROR_MALLOC;
439 pXWC->mapDirect = FALSE;
440 nReplicate = 256 / nLevels; /* # of times to replicate pixel into map
442 for (i = 0, pColor = pXWC->pColors; i < nLevels; i++, pColor++) {
443 pColor->red = pColor->green = pColor->blue =
444 ilGammaCorrect (X_COLOR_MAX, i, nLevels);
445 pColor->flags = DoRed | DoGreen | DoBlue;
446 if (!XAllocColor (pXWC->i.display, pXWC->i.colormap, pColor)) {
447 ilFreeColorData (pXWC, IL_FREE_XCOLORS);
448 if (nLevels <= MIN_DIRECT_LEVELS)
450 else return ilAllocateXDirectColors (pXWC, nLevels / 2);
452 pColor->pad = TRUE; /* mark as alloc'd */
453 pixel = pColor->pixel;
454 red = (pixel >> 16) & 0xff;
455 green = (pixel >> 8) & 0xff;
457 if ((red != i) || (green != i) || (blue != i))
458 pXWC->mapDirect = TRUE;
459 for (j = 0; j < nReplicate; j++) { /* replicate into map image */
461 *pTranslate++ = green;
462 *pTranslate++ = blue;
470 /* ------------------------ ilChangeXWC --------------------------- */
471 /* Public function; see spec.
482 pXWC = (ilXWCPtr)XWC;
483 context = pXWC->o.p.context;
484 context->error = IL_OK; /* assume no error */
485 if (pXWC->o.p.objectType != IL_XWC) {
486 context->error = IL_ERROR_OBJECT_TYPE;
487 return FALSE; /* EXIT */
492 /* Allocate grays: allocate grays if gray or pseudo-color, else
493 return true if gray display supported (e.g. to True/DirectColor).
495 case IL_XWC_ALLOC_GRAYS:
497 context->error = IL_ERROR_OPTION_DATA;
500 switch (pXWC->i.visualType) {
505 if (ilAllocateXGrays (context, pXWC, IL_DEFAULT_X_GRAYS))
508 case IL_XWC_COLOR_24:
512 /* Allocate colors: 8 and 24 bit color only */
513 case IL_XWC_ALLOC_COLORS:
515 context->error = IL_ERROR_OPTION_DATA;
518 if ((pXWC->i.visualType == IL_XWC_COLOR_8)
519 && ilAllocateXDitherColors (context, pXWC))
521 else if ((pXWC->i.visualType == IL_XWC_COLOR_24)
522 && ilAllocateXDirectColors (pXWC, 256))
526 case IL_XWC_FREE_GRAYS:
528 context->error = IL_ERROR_OPTION_DATA;
531 ilFreeColorData (pXWC, IL_FREE_XGRAYS);
534 /* Free colors if 8 or 24 bit color */
535 case IL_XWC_FREE_COLORS:
537 context->error = IL_ERROR_OPTION_DATA;
540 if ((pXWC->i.visualType == IL_XWC_COLOR_8)
541 || (pXWC->i.visualType == IL_XWC_COLOR_24))
542 ilFreeColorData (pXWC, IL_FREE_XCOLORS);
545 case IL_XWC_SET_DITHER_METHOD:
546 { unsigned int ditherMethod;
547 ditherMethod = *((unsigned int *)pData);
548 if ((ditherMethod != IL_AREA_DITHER)
549 && (ditherMethod != IL_DIFFUSION)
550 && (ditherMethod != IL_QUICK_DIFFUSION)) {
551 context->error = IL_ERROR_OPTION_DATA;
554 pXWC->i.ditherMethod = ditherMethod;
558 case IL_XWC_SET_RAW_MODE:
559 pXWC->i.rawMode = *((ilBool *)pData);
563 context->error = IL_ERROR_INVALID_OPTION;
565 } /* END switch code */
571 /* ------------------------ ilQueryXWC --------------------------- */
572 /* Public function; see spec.
581 pXWC = (ilXWCPtr)XWC;
582 if (pXWC->o.p.objectType != IL_XWC) {
583 pXWC->o.p.context->error = IL_ERROR_OBJECT_TYPE;
584 return FALSE; /* EXIT */
588 pXWC->o.p.context->error = IL_OK;
593 /* ------------------------ ilCreateXWC ------------------------- */
594 /* Public function; see spec.
595 Return an error if no (null) display in this context.
604 unsigned long mustBeZero1,
605 unsigned long mustBeZero2
609 XVisualInfo template, *pVisualInfo;
612 if ((mustBeZero1 != 0) || (mustBeZero2 != 0)) {
613 context->error = IL_ERROR_PAR_NOT_ZERO;
614 return (ilXWC)NULL; /* EXIT */
617 /* A null visual or colormap means output will be to bitmap, else
618 get the info for the given visual; exit if not found.
620 if (!visual || !colormap) {
621 visual = (Visual *)NULL;
622 colormap = (Colormap)0;
625 template.visualid = XVisualIDFromVisual (visual);
626 pVisualInfo = XGetVisualInfo (display, VisualIDMask, &template,
629 context->error = IL_ERROR_X_RESOURCE;
630 return (ilXWC)NULL; /* EXIT */
634 /* Create an XWC object and fill it in.
636 pXWC = (ilXWCPtr)_ilCreateObject (context, IL_XWC, ilDestroyXWC,
639 return (ilXWC)NULL; /* EXIT */
641 pXWC->i.display = display;
642 pXWC->i.visual = visual;
644 pXWC->visualInfo = *pVisualInfo;
645 free (pVisualInfo); /* free list from XGetVisualInfo() */
648 pXWC->i.colormap = colormap;
649 pXWC->pColors = (XColor *)NULL;
651 pXWC->colorMapImage = (ilClientImage)NULL;
652 pXWC->pGrays = (XColor *)NULL;
654 pXWC->grayMapImage = (ilClientImage)NULL;
655 pXWC->i.ditherMethod = IL_AREA_DITHER;
656 pXWC->i.rawMode = FALSE;
658 /* Check the class of the given visual and fill in XWC des and format.
659 If visual class not supported default to bitonal.
660 May also default to bitonal (or color demote to gray) later if
661 insufficient colors or grays can be allocated.
662 If null visual, do bitonal output.
664 pXWC->i.staticVisual = TRUE; /* assume non-writeable colormap */
666 pXWC->i.visualType = IL_XWC_BITONAL;
667 else switch (pXWC->visualInfo.class) {
669 pXWC->i.staticVisual = FALSE;
671 if (pXWC->visualInfo.depth == 8)
672 pXWC->i.visualType = IL_XWC_COLOR_8;
673 else pXWC->i.visualType = IL_XWC_BITONAL;
676 /* Support True/DirectColor if 32 bits format
677 = "<unused 8><8R><8G><8B>". */
679 pXWC->i.staticVisual = FALSE;
681 if ((pXWC->visualInfo.depth == 24)
682 && (pXWC->visualInfo.red_mask == 0xff0000)
683 && (pXWC->visualInfo.green_mask == 0xff00)
684 && (pXWC->visualInfo.blue_mask == 0xff))
685 pXWC->i.visualType = IL_XWC_COLOR_24;
686 else pXWC->i.visualType = IL_XWC_BITONAL;
690 pXWC->i.staticVisual = FALSE;
692 if (pXWC->visualInfo.depth == 8)
693 pXWC->i.visualType = IL_XWC_GRAY_8;
694 else pXWC->i.visualType = IL_XWC_BITONAL;
696 } /* END switch visual class */
698 /* If a bitonal visual, mark as static (non-allocatable colors) */
699 if (pXWC->i.visualType == IL_XWC_BITONAL)
700 pXWC->i.staticVisual = TRUE;
702 context->error = IL_OK;
708 /* ======================== WRITE X DRAWABLE CODE ======================== */
710 /* Private block for ilRead/WriteXDrawable pipe element. Notes:
711 Inited by ilWriteXDrawable():
712 imageDepth depth of image to create - set into pPriv when added
713 imageFormat X format of image: XYBitmap (bitonal) or ZPixmap
714 isLongImage if true: image is 32bits/pixel: set image rowBytes
716 If false: set image rowBytes to row bytes of
718 bufferSize size of buffer to create and attach to Ximage.
719 pXWC ptr to XWC for this operation
720 drawable id of X drawable (Window or Pixmap) to read or write
721 x, y read: src (x,y).
722 write: dst (x,y) from caller
724 Inited by ilWriteXInit():
725 Ximage a temp XImage created by Init. Its data ptr is
726 pointed directly at the read/write buffer, or
728 pBuffer ptr to buffer allocated, if bufferSize > 0
729 linesDone zeroed by Init(): # of lines written / read so far,
730 i.e. y + linesDone is next line to read / write.
736 unsigned long bufferSize;
743 } ilXPrivRec, *ilXPrivPtr;
746 /* ----------------------- ilXDestroy ----------------------------- */
747 /* Destroy() function for ilWriteXDrawable() pipe element.
748 "Destroys" the associated XWC, whose refCount must have been
749 incremented when the element was successfully added to the pipe -
750 Destroy downcounts it.
752 static ilError ilXDestroy (
756 ilXPrivPtr pPriv = (ilXPrivPtr)pPrivate;
757 ilDestroyObject ((ilObject)pPriv->pXWC);
763 /* ------------------------- ilWriteXInit ------------------------- */
764 /* Init() function for ilWriteXDrawable() for all src image types.
765 Creates an XImage, which is just a data structure - creates no
767 The XImage is freed by ilWriteXCleanup().
769 static ilError ilWriteXInit (
771 ilImageInfo *pSrcImage,
772 ilImageInfo *pDstImage /* ignored */
775 ilXPrivPtr pPriv = (ilXPrivPtr)pPrivate;
779 /* Create a temp buffer for image pixels if requested. */
780 if (pPriv->bufferSize > 0) {
781 pPriv->pBuffer = (ilPtr)IL_MALLOC (pPriv->bufferSize);
783 return IL_ERROR_MALLOC; /* EXIT */
785 else pPriv->pBuffer = NULL;
787 /* Create an XImage that will be pointed to each buffer (strip) to
790 pXImage = XCreateImage (pXWC->i.display, pXWC->i.visual,
791 pPriv->imageDepth, pPriv->imageFormat, 0,
792 (char *)pPriv->pBuffer, pSrcImage->width,
793 pSrcImage->height, pSrcImage->pFormat->rowBitAlign,
794 (pPriv->isLongImage) ? (pSrcImage->width * 4) :
795 pSrcImage->plane[0].nBytesPerRow);
797 return IL_ERROR_MALLOC; /* EXIT */
799 /* Set bit/byte order to MSBFirst.
800 NOTE: byte order should be set to byte order of client machine!!!
804 pXImage->byte_order = LSBFirst;
806 pXImage->byte_order = MSBFirst;
808 pXImage->bitmap_bit_order = MSBFirst;
809 pPriv->pXImage = pXImage;
810 pPriv->linesDone = 0;
815 /* --------------------- ilWriteXCleanup -------------------------- */
816 /* Cleanup() function for ilWriteXDrawable() for all src image types.
817 Flushes the output if not aborted; frees the XImage created by
820 static ilError ilWriteXCleanup (
825 /* Flush if not aborting. Null the "data" field in image or else
826 XDestroyImage() will try to free the pixels; destroy the image,
829 ilXPrivPtr pPriv = (ilXPrivPtr)pPrivate;
831 XFlush (pPriv->pXWC->i.display);
833 IL_FREE (pPriv->pBuffer);
834 pPriv->pXImage->data = (char *)NULL;
835 XDestroyImage (pPriv->pXImage);
839 /* --------------------- ilWriteXExecute ------------------------- */
840 /* Execute() function for ilWriteXDrawable(), for rendering bit or
842 Points an XImage created by ilWriteXInit() to the src image bits
843 and does an XPutImage(), then bumps a line count so next strip is
844 written *pNLines below this one in the drawable.
846 static ilError ilWriteXExecute (
847 ilExecuteData *pData,
856 unsigned int nSrcLines;
857 unsigned int scaledWidth,scaledHeight;
858 int scaledX, scaledY;
860 pPriv = (ilXPrivPtr)pData->pPrivate;
861 nSrcLines = *pNLines;
862 pXImage = pPriv->pXImage;
863 pXImage->height = nSrcLines;
864 pXImage->data = (char *)(pData->pSrcImage->plane[0].pPixels +
865 pData->srcLine * pData->pSrcImage->plane[0].nBytesPerRow);
869 scaledWidth = pXImage->width * ratio + 0.5;
870 scaledX = pPriv->x * ratio + 0.5;
871 scaledY = (pPriv->y + pPriv->linesDone) * ratio + 0.5;
872 /* we have to think about rounding problem, so recalculate every time. */
873 scaledHeight = ((nSrcLines + pPriv->linesDone) * ratio + 0.5)
876 _XmPutScaledImage (pXWC->i.display, pPriv->drawable,
878 0, 0, scaledX, scaledY,
879 pXImage->width, nSrcLines,
880 scaledWidth,scaledHeight);
882 pPriv->linesDone += nSrcLines;
887 /* ------------------- ilWriteXOptLongExecute --------------------- */
888 /* Execute() function for ilWriteXDrawable(), for display to optimal
889 4 bytes pixel frame buffers. "Optimal" means the 4 bytes (CARD32)
890 = "<unused 8> <8 R> <8 G> <8 B>",
891 which is the format most commonly used right now.
892 Reformat the pipe image pixels, which are 3byte pixel RGB (as
893 required by pXWC->format), into 4 bytes words and do the
894 XPutImage(), then bump linesDone.
896 static ilError ilWriteXOptLongExecute (
897 ilExecuteData *pData,
904 ilImageInfo *pSrcImage;
908 long srcRowBytes, width, nSrcLines, nLinesM1;
912 unsigned int scaledWidth,scaledHeight;
913 int scaledX, scaledY ;
915 nSrcLines = *pNLines;
917 return 0; /* no lines, EXIT */
918 pPriv = (ilXPrivPtr)pData->pPrivate;
919 pSrcImage = pData->pSrcImage;
920 width = pSrcImage->width;
922 return 0; /* no width, EXIT */
923 srcRowBytes = pSrcImage->plane[0].nBytesPerRow;
924 pSrcLine = (ilPtr)(pSrcImage->plane[0].pPixels +
925 pData->srcLine * srcRowBytes);
926 pXImage = pPriv->pXImage;
927 pXImage->height = nSrcLines;
928 pXImage->data = (char *)pPriv->pBuffer;
929 pDst = (CARD32 *)pPriv->pBuffer;
931 /* pSrcLine points to first line of pipe image; pDst to buffer of
933 Convert 3 byte pipe image to CARD32 X buffer image. Dont need
934 dstRowBytes because buffer is exactly "width" longs wide (we
937 nLinesM1 = nSrcLines - 1;
940 pSrcLine += srcRowBytes;
941 nLongsM1 = width - 1;
949 } while (--nLongsM1 >= 0);
950 } while (--nLinesM1 >= 0);
954 scaledWidth = pXImage->width * ratio;
955 scaledHeight = nSrcLines * ratio;
956 scaledX = pPriv->x * ratio ;
957 scaledY = (pPriv->y + pPriv->linesDone)* ratio ;
959 _XmPutScaledImage (pXWC->i.display, pPriv->drawable, pXWC->i.gc, pXImage,
960 0, 0, scaledX, scaledY,
961 pXImage->width, nSrcLines,
962 scaledWidth,scaledHeight);
964 pPriv->linesDone += nSrcLines;
970 /* ------------------------ ilConvertForXWrite -------------------- */
971 /* Public function; see spec.
972 Side effect: set pXWC->i.writeType, code for how it will render.
974 ilBool ilConvertForXWrite (
978 unsigned long mustBeZero,
984 ilImageFormat format;
985 unsigned int writeType;
988 /* Table indexed by [dst visual type], yielding writeType when in raw
990 static unsigned int rawWriteMethodTable [(IL_X_MAX_VISUAL_TYPE + 1)] = {
991 IL_XWC_WRITE_BITONAL, /* IL_XWC_BITONAL */
992 IL_XWC_WRITE_GRAY, /* IL_XWC_GRAY_8 */
993 IL_XWC_WRITE_COLOR_DITHER, /* IL_XWC_COLOR_8 */
994 IL_XWC_WRITE_COLOR /* IL_XWC_COLOR_24 */ };
996 /* Table indexed by [image type, dst visual type], yielding writeType,
997 assuming best case: colors/grays alloc'd successfully; else writeType
1000 static unsigned int writeTypeTable [(IL_MAX_TYPE + 1) *
1001 (IL_X_MAX_VISUAL_TYPE + 1)] =
1002 { /* (src) image type (dst) visual type writeType */
1004 /* IL_BITONAL IL_XWC_BITONAL */ IL_XWC_WRITE_BITONAL,
1005 /* IL_XWC_GRAY_8 */ IL_XWC_WRITE_BITONAL,
1006 /* IL_XWC_COLOR_8 */ IL_XWC_WRITE_BITONAL,
1007 /* IL_XWC_COLOR_24 */ IL_XWC_WRITE_BITONAL,
1009 /* IL_GRAY IL_XWC_BITONAL */ IL_XWC_WRITE_BITONAL,
1010 /* IL_XWC_GRAY_8 */ IL_XWC_WRITE_GRAY,
1011 /* IL_XWC_COLOR_8 */ IL_XWC_WRITE_GRAY,
1012 /* IL_XWC_COLOR_24 */ IL_XWC_WRITE_COLOR,
1014 /* IL_PALETTE IL_XWC_BITONAL */ IL_XWC_WRITE_BITONAL,
1015 /* IL_XWC_GRAY_8 */ IL_XWC_WRITE_GRAY,
1016 /* IL_XWC_COLOR_8 */ IL_XWC_WRITE_COLOR_DITHER,
1017 /* IL_XWC_COLOR_24 */ IL_XWC_WRITE_COLOR,
1019 /* IL_RGB IL_XWC_BITONAL */ IL_XWC_WRITE_BITONAL,
1020 /* IL_XWC_GRAY_8 */ IL_XWC_WRITE_GRAY,
1021 /* IL_XWC_COLOR_8 */ IL_XWC_WRITE_COLOR_DITHER,
1022 /* IL_XWC_COLOR_24 */ IL_XWC_WRITE_COLOR,
1024 /* IL_YCBCR IL_XWC_BITONAL */ IL_XWC_WRITE_BITONAL,
1025 /* IL_XWC_GRAY_8 */ IL_XWC_WRITE_GRAY,
1026 /* IL_XWC_COLOR_8 */ IL_XWC_WRITE_COLOR_DITHER,
1027 /* IL_XWC_COLOR_24 */ IL_XWC_WRITE_COLOR
1032 if (pipe->objectType != IL_PIPE) {
1033 pipe->context->error = IL_ERROR_OBJECT_TYPE;
1036 if (mustBeZero || mustBeNull)
1037 return ilDeclarePipeInvalid (pipe, IL_ERROR_PAR_NOT_ZERO);
1039 /* Validate that given XWC is one, and is same context as pipe. */
1040 pXWC = (ilXWCPtr)XWC;
1041 if (pXWC->o.p.objectType != IL_XWC)
1042 return ilDeclarePipeInvalid (pipe, IL_ERROR_OBJECT_TYPE);
1043 if (pXWC->o.p.context != pipe->context)
1044 return ilDeclarePipeInvalid (pipe, IL_ERROR_CONTEXT_MISMATCH);
1046 /* Get pipe info and decompress; if pipe not in IL_PIPE_FORMING state,
1048 if (ilGetPipeInfo (pipe, TRUE, &info, &des, &format) != IL_PIPE_FORMING) {
1049 if (!pipe->context->error)
1050 ilDeclarePipeInvalid (pipe, IL_ERROR_PIPE_STATE);
1054 /* If raw mode, allocate no colors, output based on dst visual type,
1055 except for bit/pixel images: output using bitonal approach; else:
1056 get "writeType" based on des.type (private types not supported)
1057 and pXWC->i.visualType. Check for allocated dither colors
1058 (default to gray if not enough) and grays (default to bitonal if
1060 Pretend YCbCr is RGB - an ilConvert() to RGB will be done below
1063 if (pXWC->i.rawMode) {
1064 if ((des.nSamplesPerPixel == 1) && (format.nBitsPerSample[0] == 1))
1065 writeType = IL_XWC_WRITE_BITONAL;
1066 else writeType = rawWriteMethodTable [pXWC->i.visualType];
1069 if (des.type > IL_MAX_TYPE)
1070 return ilDeclarePipeInvalid (pipe, IL_ERROR_IMAGE_TYPE);
1071 if (des.type == IL_YCBCR)
1074 writeType = writeTypeTable
1075 [des.type * (IL_X_MAX_VISUAL_TYPE + 1) + pXWC->i.visualType];
1076 if (writeType == IL_XWC_WRITE_COLOR_DITHER) {
1077 if (!pXWC->colorMapImage)
1078 ilChangeXWC ((ilXWC)pXWC, IL_XWC_ALLOC_DITHER_COLORS,
1080 if (!pXWC->colorMapImage)
1081 writeType = IL_XWC_WRITE_GRAY;
1083 if (writeType == IL_XWC_WRITE_GRAY) {
1084 if (!pXWC->grayMapImage)
1085 ilChangeXWC ((ilXWC)pXWC, IL_XWC_ALLOC_GRAYS, (ilPtr)NULL);
1086 if (!pXWC->grayMapImage)
1087 writeType = IL_XWC_WRITE_BITONAL;
1090 /* If RGB display alloc colors or dflt to bitonal. */
1091 if (writeType == IL_XWC_WRITE_COLOR) {
1092 if (!pXWC->colorMapImage)
1093 if (!ilAllocateXDirectColors (pXWC, 256))
1094 writeType = IL_XWC_WRITE_BITONAL;
1096 } /* END not raw mode */
1098 /* Do ilConvert() and add filter(s) based on "writeType". */
1099 switch (writeType) {
1101 /* Bitonal: do an XPutImage() with XYBitmap, which renders image 0's
1102 with GC background color, 1's with foreground, as defined by IL
1104 If rawMode, must be bit/pixel.
1106 case IL_XWC_WRITE_BITONAL:
1107 if (pXWC->i.rawMode) {
1108 if ((des.nSamplesPerPixel != 1) || (format.nBitsPerSample[0] != 1))
1109 return ilDeclarePipeInvalid (pipe, IL_ERROR_RAW_MODE);
1111 else if (!ilConvert (pipe, IL_DES_BITONAL, IL_FORMAT_BIT, 0, NULL))
1115 /* Gray: do ilMap() which maps 256 gray shades to the equivalent
1116 X pixel values, possibly using fewer shades of gray (slam; not
1117 dithered to lesser # grays).
1119 case IL_XWC_WRITE_GRAY:
1120 if (pXWC->i.rawMode) {
1121 if ((des.nSamplesPerPixel != 1) || (format.nBitsPerSample[0] != 8))
1122 return ilDeclarePipeInvalid (pipe, IL_ERROR_RAW_MODE);
1125 if (!ilConvert (pipe, IL_DES_GRAY, IL_FORMAT_BYTE, 0, NULL))
1128 if (!ilMap (pipe, pXWC->grayMapImage))
1133 /* Dithered RGB: if raw mode, accept if byte/pixel;
1134 if a pre-dithered palette image in pipe, ilMap() to map colors to
1136 otherwise dither cvt to palette w/ map to the allocated colors.
1138 case IL_XWC_WRITE_COLOR_DITHER:
1139 if (pXWC->i.rawMode) {
1140 if ((des.nSamplesPerPixel != 1) || (format.nBitsPerSample[0] != 8))
1141 return ilDeclarePipeInvalid (pipe, IL_ERROR_RAW_MODE);
1143 else if ((des.flags & IL_DITHERED_PALETTE)
1144 && (des.typeInfo.palette.levels[0] == NRED)
1145 && (des.typeInfo.palette.levels[1] == NGREEN)
1146 && (des.typeInfo.palette.levels[2] == NBLUE)) {
1147 if ((format.nBitsPerSample[0] != 8)
1148 && !ilConvert (pipe, (ilImageDes *)NULL, IL_FORMAT_BYTE, 0,
1152 if (!ilMap (pipe, pXWC->colorMapImage))
1156 ilConvertToPaletteInfo cvt;
1157 cvt.method = pXWC->i.ditherMethod;
1158 cvt.levels[0] = NRED;
1159 cvt.levels[1] = NGREEN;
1160 cvt.levels[2] = NBLUE;
1163 cvt.dstType = IL_GRAY; /* any type other than IL_PALETTE */
1164 cvt.mapImage = pXWC->colorMapImage;
1167 cvt.dstType = IL_PALETTE;
1168 cvt.mapImage = (ilClientImage)NULL;
1170 if (!ilConvert (pipe, IL_DES_PALETTE, IL_FORMAT_BYTE,
1171 IL_CONVERT_TO_PALETTE, &cvt))
1176 /* RGB: if raw mode, check format, else convert to RGB, and if
1177 mapPixels and map needed (ramp not 0..255 each component) do
1180 case IL_XWC_WRITE_COLOR:
1182 if (pXWC->i.rawMode) {
1183 if ((des.nSamplesPerPixel != 3)
1184 || (format.nBitsPerSample[0] != 8)
1185 || (format.nBitsPerSample[1] != 8)
1186 || (format.nBitsPerSample[2] != 8)
1187 || (format.sampleOrder != IL_SAMPLE_PIXELS))
1188 return ilDeclarePipeInvalid (pipe, IL_ERROR_RAW_MODE);
1191 if (!ilConvert (pipe, IL_DES_RGB, IL_FORMAT_3BYTE_PIXEL, 0, NULL))
1193 if (mapPixels && pXWC->mapDirect)
1194 if (!ilMap (pipe, pXWC->colorMapImage))
1199 } /* END switch writeType */
1201 pXWC->i.writeType = writeType; /* set method of writing to be used */
1202 pipe->context->error = IL_OK;
1207 /* ------------------------ ilWriteXDrawable ---------------------- */
1208 /* Public function; see spec.
1210 ilBool ilWriteXDrawable (
1217 unsigned long mustBeZero
1223 ilSrcElementData *pSrcData, srcData;
1224 unsigned long bufferSize;
1226 ** We need to use the execute fucntion with the ratio parameter.
1228 ilError (*executeFunction)( ilExecuteData *,
1233 /* If a src clip rect, insert an ilCrop() element before us.
1234 In the future, should look at pipe and handle some cases directly.
1236 if (pSrcRect && !ilCrop (pipe, pSrcRect))
1239 /* Convert as necessary, mapping pixels to X pixels and get
1240 pXWC->i.writeType */
1241 pXWC = (ilXWCPtr)XWC;
1242 if (!ilConvertForXWrite (pipe, (ilXWC)pXWC, TRUE, 0, NULL))
1245 ilGetPipeInfo (pipe, FALSE, &info, (ilImageDes *)NULL,
1246 (ilImageFormat *)NULL);
1248 /* If writing 24 bits: use separate executeFunction, set "bufferSize"
1249 to buffer to be allocated, and if too large force pipe to give us
1252 if (pXWC->i.writeType == IL_XWC_WRITE_COLOR) {
1253 bufferSize = (info.width * 4) * info.stripHeight;
1254 if (bufferSize > MAX_IMAGE_BUFFER_SIZE) {
1255 srcData.consumerImage = (ilObject)NULL;
1256 srcData.stripHeight = BEST_IMAGE_BUFFER_SIZE / (4 * info.width);
1257 if (srcData.stripHeight < 1)
1258 srcData.stripHeight = 1;
1259 srcData.constantStrip = FALSE;
1260 srcData.minBufferHeight = 0;
1261 pSrcData = &srcData;
1263 else pSrcData = (ilSrcElementData *)NULL;
1264 executeFunction = ilWriteXOptLongExecute;
1267 pSrcData = (ilSrcElementData *)NULL;
1268 executeFunction = ilWriteXExecute;
1271 /* Add a consumer which does an XPutImage() using the pipe data
1273 Increment the XWC refCount; element's Destroy() function
1274 ilXDestroy() will decrement it when this pipe element is removed.
1276 pPriv = (ilXPrivPtr)ilAddPipeElement (pipe, IL_CONSUMER,
1277 sizeof(ilXPrivRec), 0, pSrcData, (ilDstElementData *)NULL,
1278 ilWriteXInit, ilWriteXCleanup, ilXDestroy, NULL, executeFunction, 0);
1279 if (!pPriv) return FALSE; /* EXIT */
1282 pPriv->drawable = drawable;
1287 /* Set writeType-specific values in *pPriv */
1288 switch (pXWC->i.writeType) {
1289 case IL_XWC_WRITE_BITONAL:
1290 pPriv->imageDepth = 1;
1291 pPriv->imageFormat = XYBitmap;
1292 pPriv->isLongImage = FALSE;
1293 pPriv->bufferSize = 0;
1295 case IL_XWC_WRITE_GRAY:
1296 pPriv->imageDepth = 8;
1297 pPriv->imageFormat = ZPixmap;
1298 pPriv->isLongImage = FALSE;
1299 pPriv->bufferSize = 0;
1301 case IL_XWC_WRITE_COLOR_DITHER:
1302 pPriv->imageDepth = 8;
1303 pPriv->imageFormat = ZPixmap;
1304 pPriv->isLongImage = FALSE;
1305 pPriv->bufferSize = 0;
1307 case IL_XWC_WRITE_COLOR:
1308 pPriv->bufferSize = bufferSize; /* from above */
1309 pPriv->imageDepth = 24;
1310 pPriv->imageFormat = ZPixmap;
1311 pPriv->isLongImage = TRUE;
1315 pipe->context->error = IL_OK;