1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /* $XConsortium: ilX.c /main/11 1996/11/12 05:02:17 pascale $ */
- /**---------------------------------------------------------------------
- ***
- *** (c)Copyright 1991 Hewlett-Packard Co.
- ***
- *** RESTRICTED RIGHTS LEGEND
- *** Use, duplication, or disclosure by the U.S. Government is subject to
- *** restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
- *** Technical Data and Computer Software clause in DFARS 252.227-7013.
- *** Hewlett-Packard Company
- *** 3000 Hanover Street
- *** Palo Alto, CA 94304 U.S.A.
- *** Rights for non-DOD U.S. Government Departments and Agencies are as set
- *** forth in FAR 52.227-19(c)(1,2).
- ***
- ***-------------------------------------------------------------------*/
- #include "ilint.h"
- #include "ilcontext.h"
- #include "ilX.h"
- #include <math.h>
- #include <stdlib.h>
- #include <X11/Xutil.h>
- #include "ilpipelem.h"
- #include "ilerrors.h"
- #include <Xm/XmPrivate.h>
- #define X_COLOR_MAX 65535 /* max value for X colormap RGB
- value */
- /* Buffer allocation checks. Buffers are allocated for example when
- writing to a 24 bit drawable: the pipe image pixels are converted
- from 3 bytes to 4 bytes (CARD32).
- */
- #define MAX_IMAGE_BUFFER_SIZE 100000 /* force strips if larger than
- this ... */
- #define BEST_IMAGE_BUFFER_SIZE 50000 /* to strips of this size */
- /* Masks for ilFreeColorData(); see below.
- */
- #define IL_FREE_XCOLORS (1<<0)
- #define IL_FREE_XGRAYS (1<<1)
- /* Codes for view of X , in "ilXWCRec.i.visualType". When the visual is
- unsupported or an insufficient # of colors can be allocated from the
- colormap, the drawable defaults to IL_XWC_BITONAL. Images rendered
- to such an XWC are converted to bitonal, then XPutImage() of an
- XYBitmap is done - the XWC GC's foreground/background colors are used
- for black/white.
- */
- #define IL_X_MAX_VISUAL_TYPE 3 /* max value of IL_XWC_BITONAL
- et al*/
- /* Default # of grays or dither colors to allocate for pseudo-color. */
- #define IL_DEFAULT_X_GRAYS 32
- #define NRED 4
- #define NGREEN 8
- #define NBLUE 4
- /* Internals of an XWC (X Write Context), an IL object created by
- ilCreateXWC().
- An XWC is associated with the visual "visual" and "colormap".
- "i" contains basic information returned by ilQueryXWC().
- If pColors is non-null, it points to a list of length "nColors",
- of colors allocated from "colormap". "pad" in each colorcell is
- used as a flag:
- == 0 if color not allocated, else color was sucessfully allocated.
- If non-null, colorMapImage is an image for mapping to X images
- using ilMap().
- For example, for 8 bit pseudo-color when 484 color handling is used,
- "pColors" points to 128 colors, and "colorMapImage" points to a 256
- pixel image where each entry is the pixel to use for color
- (red*4*8 + green*8 + blue).
- If "colorMapImage" is null then the alloc failed or has not been tried.
- Note: above applies also to Direct/TrueColor visuals, with the same
- names.
- The above also applies to the "gray" fields, with the "gray" names.
- */
- typedef struct {
- ilObjectRec o; /* std header: MUST BE FIRST */
- ilXWCInfo i; /* see above */
- XVisualInfo visualInfo; /* X info on "visual" */
- XColor *pColors; /* ptr to list of allocated
- colors or null */
- int nColors; /* size of *pColors list */
- ilClientImage colorMapImage; /* see above */
- ilBool mapDirect; /* ilMap(colorMapImage),
- Direct/TrueColor */
- XColor *pGrays; /* ptr to list of allocated grays
- or null */
- int nGrays; /* size of *pGrays list */
- ilClientImage grayMapImage; /* same as colorMapImage, but for
- grays */
- } ilXWCRec, *ilXWCPtr;
- typedef ilError (*executeFunctionType)();
- /* ------------------------ ilFreeColorData ---------------------- */
- /* Free the color list and translation table in the given XWC if
- present. "freeMasks" indicates which should be freed:
- IL_FREE_XCOLORS/XGRAYS, or ~0 for everything.
- */
- static void ilFreeColorData (
- ilXWCPtr pXWC,
- unsigned long freeMask
- )
- {
- int i;
- XColor *pColor;
- /* If color list present: free each color if allocated (pad != 0);
- free list.
- */
- if (freeMask & IL_FREE_XCOLORS) {
- if (pXWC->pColors) {
- for (i = 0, pColor = pXWC->pColors; i < pXWC->nColors; i++) {
- if (pColor->pad)
- XFreeColors (pXWC->i.display, pXWC->i.colormap,
- &pColor->pixel, 1, 0L);
- pColor++;
- }
- IL_FREE (pXWC->pColors);
- pXWC->pColors = (XColor *)NULL;
- pXWC->nColors = 0;
- }
- if (pXWC->colorMapImage) {
- ilDestroyObject (pXWC->colorMapImage);
- pXWC->colorMapImage = (ilClientImage)NULL;
- }
- }
- /* Same for gray list
- */
- if (freeMask & IL_FREE_XGRAYS) {
- if (pXWC->pGrays) {
- for (i = 0, pColor = pXWC->pGrays; i < pXWC->nGrays; i++) {
- if (pColor->pad)
- XFreeColors (pXWC->i.display, pXWC->i.colormap,
- &pColor->pixel, 1, 0L);
- pColor++;
- }
- IL_FREE (pXWC->pGrays);
- pXWC->pGrays = (XColor *)NULL;
- pXWC->nGrays = 0;
- }
- if (pXWC->grayMapImage) {
- ilDestroyObject (pXWC->grayMapImage);
- pXWC->grayMapImage = (ilClientImage)NULL;
- }
- }
- }
- /* ----------------------- ilDestroyXWC -------------------------- */
- /* Destroy() function for XWC objects. Free the color list if
- present.
- The GC for the default XWC will be destroyed when the context is
- freed, by ilXDestroyContext() below.
- */
- static void ilDestroyXWC (
- ilPtr pPrivate
- )
- {
- ilObject object = (ilObject)pPrivate;
- ilXWCPtr pXWC;
- pXWC = (ilXWCPtr)object;
- /* ~ on signed integer is not recommended, play it safe here */
- ilFreeColorData (pXWC, ~(0UL));
- }
- /* --------------------- ilGammaCorrect -------------------------- */
- /* Returns a value from 0..scaleValue, given "value", from
- 0.."maxValue" - 1, scaled up to "scaleValue" (e.g. 65535 for
- X color values).
- Currently a misnomer - not doing any gamma correction
- (gamma = 1.0).
- */
- static int ilGammaCorrect (
- long scaleValue,
- int value,
- int maxValue
- )
- {
- int allocValue;
- if (value == 0)
- allocValue = 0;
- else if (value == (maxValue - 1))
- allocValue = scaleValue;
- else {
- allocValue = value * scaleValue / (maxValue-1);
- if (allocValue < 0)
- allocValue = 0;
- else if (allocValue > scaleValue)
- allocValue = scaleValue;
- }
- return allocValue;
- }
- /* --------------------- ilAllocateXDitherColors ------------------ */
- /* Internal function to ilCreateXWC(). Attempts to allocate enough
- colors in pXWC->i.colormap to support the visual as a 484
- pseudo-color visual.
- An error code is returned to the given context if an error
- (e.g. malloc) error occurs; IL_OK if the grays could not be
- alloc'd (but false is returned).
- */
- static ilBool ilAllocateXDitherColors (
- ilContext context,
- ilXWCPtr pXWC
- )
- {
- int i, red, green, blue;
- XColor *pColor;
- ilPtr pTranslate;
- ilImageInfo imageInfo, *pImageInfo;
- context->error = IL_OK; /* assume no errors */
- if (pXWC->colorMapImage)
- return TRUE; /* already alloc'd; EXIT */
- /* Allocate a client image to use as LUT for mapping to X's
- colors.
- Point pTranslate to the allocated pixels.
- */
- imageInfo.pDes = IL_DES_GRAY;
- imageInfo.pFormat = IL_FORMAT_BYTE;
- imageInfo.width = 256;
- imageInfo.height = 1;
- imageInfo.clientPixels = FALSE;
- pXWC->colorMapImage = ilCreateClientImage (context, &imageInfo, 0);
- if (!pXWC->colorMapImage)
- return FALSE; /* EXIT */
- ilQueryClientImage (pXWC->colorMapImage, &pImageInfo, 0);
- pTranslate = pImageInfo->plane[0].pPixels;
- pXWC->nColors = NRED * NGREEN * NBLUE;
- pXWC->pColors = (XColor *)IL_MALLOC (pXWC->nColors * sizeof(XColor));
- if (!pXWC->pColors) {
- ilDestroyObject (pXWC->colorMapImage);
- pXWC->colorMapImage = (ilClientImage)NULL;
- context->error = IL_ERROR_MALLOC;
- return FALSE; /* EXIT */
- }
- for (i = 0, pColor = pXWC->pColors; i < pXWC->nColors; i++, pColor++)
- pColor->pad = FALSE; /* init pad, in case below fails */
-
- /* Allocate 484 colors (128 in all) */
- pColor = pXWC->pColors;
- for (red = 0; red < NRED; red++)
- for (green = 0; green < NGREEN; green++)
- for (blue = 0; blue < NBLUE; blue++) {
- pColor->red = ilGammaCorrect (X_COLOR_MAX, red, NRED);
- pColor->green = ilGammaCorrect (X_COLOR_MAX, green, NGREEN);
- pColor->blue = ilGammaCorrect (X_COLOR_MAX, blue, NBLUE);
- if (!XAllocColor (pXWC->i.display, pXWC->i.colormap, pColor)) {
- ilFreeColorData (pXWC, IL_FREE_XCOLORS);
- return FALSE;
- }
- pTranslate [red*(NGREEN*NBLUE) + green*NBLUE + blue] =
- pColor->pixel;
- pColor->pad = TRUE; /* mark as alloc'd */
- pColor++;
- }
- return TRUE; /* colors successfully alloc'd */
- }
-
- /* ---------------------------- ilAllocateXGrays ---------------------- */
- /* Allocate "nGrays" from the colormap associated with the given XWC or
- return error.
- The grays are ramped evenly from 0..nGrays-1. If there are "nGrays"
- existing grays, they are used, else if not nGrays, they are
- deallocated.
- An error code is returned to the given context if an error
- (e.g. malloc) error occurs; IL_OK if the grays could not be alloc'd
- (but false is returned).
- */
- static ilBool ilAllocateXGrays (
- ilContext context,
- ilXWCPtr pXWC,
- int nGrays
- )
- {
- int i, index;
- XColor *pColor;
- ilPtr pTranslate;
- ilImageInfo imageInfo, *pImageInfo;
- double spreadFactor;
- /* Use the grays if the same number, else deallocate them.
- */
- context->error = IL_OK; /* assume no errors */
- if (pXWC->pGrays) {
- if (pXWC->nGrays == nGrays)
- return TRUE;
- else ilFreeColorData (pXWC, IL_FREE_XGRAYS);
- }
- if (nGrays > 256)
- return FALSE; /* EXIT */
- /* Allocate a client image to use as LUT for mapping to X's colors.
- Point pTranslate to the allocated pixels.
- */
- imageInfo.pDes = IL_DES_GRAY;
- imageInfo.pFormat = IL_FORMAT_BYTE;
- imageInfo.width = 256;
- imageInfo.height = 1;
- imageInfo.clientPixels = FALSE;
- pXWC->grayMapImage = ilCreateClientImage (context, &imageInfo, 0);
- if (!pXWC->grayMapImage)
- return FALSE; /* EXIT */
- ilQueryClientImage (pXWC->grayMapImage, &pImageInfo, 0);
- pTranslate = pImageInfo->plane[0].pPixels;
- pXWC->nGrays = nGrays;
- pXWC->pGrays = (XColor *)IL_MALLOC (pXWC->nGrays * sizeof(XColor));
- if (!pXWC->pGrays) {
- ilDestroyObject (pXWC->grayMapImage);
- pXWC->colorMapImage = (ilClientImage)NULL;
- context->error = IL_ERROR_MALLOC;
- return FALSE; /* EXIT */
- }
- for (i = 0, pColor = pXWC->pGrays; i < pXWC->nGrays; i++, pColor++)
- pColor->pad = FALSE; /* init pad, in case below fails */
-
- /* Allocate the grays; return error on any failure. */
- for (i = 0; i < nGrays; i++) {
- pColor = &pXWC->pGrays [i];
- pColor->red = pColor->green = pColor->blue =
- ilGammaCorrect (X_COLOR_MAX, i, nGrays);
- if (!XAllocColor (pXWC->i.display, pXWC->i.colormap, pColor)) {
- pColor->pad = FALSE;
- ilFreeColorData (pXWC, IL_FREE_XGRAYS);
- return FALSE; /* EXIT */
- }
- pColor->pad = TRUE;
- }
- /* Grays allocated ok; spread the allocated colors over the whole 256
- area. In effect, color-slam all 256-level gray images into nGrays.
- NOTE: gray images with other than 256 levels could be supported in
- future!
- */
- spreadFactor = ((double)(nGrays - 1)) / (double)255;
- pColor = pXWC->pGrays;
- for (i = 0; i < 256; i++) {
- index = spreadFactor * (double)i + 0.5;
- if (index > (nGrays - 1))
- index = nGrays - 1;
- pTranslate [i] = pColor [index].pixel;
- }
- return TRUE;
- }
- /* ---------------------- ilAllocateXDirectColors --------------------- */
- /* Allocate "nLevels" levels of each of RGB for a DirectColor or a
- TrueColor visual.
- "nLevels" should be passed as 256; it becomes 1/2 of that if failure
- occurs this function recurses on failure until an unacceptable # of
- levels not alloc'd.
- */
- static ilBool ilAllocateXDirectColors (
- ilXWCPtr pXWC,
- int nLevels
- )
- {
- int i, j, pixel, red, green, blue, nReplicate;
- XColor *pColor;
- ilPtr pTranslate;
- ilImageInfo imageInfo, *pImageInfo;
- ilContext context;
- #define MIN_DIRECT_LEVELS 32 /* min # of acceptable levels */
- if (pXWC->colorMapImage)
- return TRUE; /* already alloc'd; EXIT */
- /* Create a 256x1 3 byte/pixel map image. */
- context = pXWC->o.p.context;
- imageInfo.pDes = IL_DES_RGB;
- imageInfo.pFormat = IL_FORMAT_3BYTE_PIXEL;
- imageInfo.width = 256;
- imageInfo.height = 1;
- imageInfo.clientPixels = FALSE;
- pXWC->colorMapImage = ilCreateClientImage (context, &imageInfo, 0);
- if (!pXWC->colorMapImage)
- return FALSE;
- ilQueryClientImage (pXWC->colorMapImage, &pImageInfo, 0);
- pTranslate = pImageInfo->plane[0].pPixels;
- /* Try to allocate nLevels read-only levels each of RGB, in a logical
- ramp order. Set pXWC->mapDirect to false if pixel value != RGB
- value, in which case pipe image pixels must be ilMap()'d to X
- pixel values.
- If can't allocate, try to allocate nLevels/2 unless that is too
- few colors, in which we fail. Spread the X pixels into the 256
- entry map image.
- */
- pXWC->nColors = nLevels;
- pXWC->pColors = (XColor *)IL_MALLOC_ZERO (pXWC->nColors * sizeof(XColor));
- if (!pXWC->pColors) {
- ilDestroyObject (pXWC->colorMapImage);
- pXWC->colorMapImage = (ilClientImage)NULL;
- context->error = IL_ERROR_MALLOC;
- return FALSE;
- }
- pXWC->mapDirect = FALSE;
- nReplicate = 256 / nLevels; /* # of times to replicate pixel into map
- image */
- for (i = 0, pColor = pXWC->pColors; i < nLevels; i++, pColor++) {
- pColor->red = pColor->green = pColor->blue =
- ilGammaCorrect (X_COLOR_MAX, i, nLevels);
- pColor->flags = DoRed | DoGreen | DoBlue;
- if (!XAllocColor (pXWC->i.display, pXWC->i.colormap, pColor)) {
- ilFreeColorData (pXWC, IL_FREE_XCOLORS);
- if (nLevels <= MIN_DIRECT_LEVELS)
- return FALSE;
- else return ilAllocateXDirectColors (pXWC, nLevels / 2);
- }
- pColor->pad = TRUE; /* mark as alloc'd */
- pixel = pColor->pixel;
- red = (pixel >> 16) & 0xff;
- green = (pixel >> 8) & 0xff;
- blue = pixel & 0xff;
- if ((red != i) || (green != i) || (blue != i))
- pXWC->mapDirect = TRUE;
- for (j = 0; j < nReplicate; j++) { /* replicate into map image */
- *pTranslate++ = red;
- *pTranslate++ = green;
- *pTranslate++ = blue;
- }
- }
- return TRUE;
- }
- /* ------------------------ ilChangeXWC --------------------------- */
- /* Public function; see spec.
- */
- ilBool ilChangeXWC (
- ilXWC XWC,
- unsigned int code,
- void *pData
- )
- {
- ilXWCPtr pXWC;
- ilContext context;
- pXWC = (ilXWCPtr)XWC;
- context = pXWC->o.p.context;
- context->error = IL_OK; /* assume no error */
- if (pXWC->o.p.objectType != IL_XWC) {
- context->error = IL_ERROR_OBJECT_TYPE;
- return FALSE; /* EXIT */
- }
- switch (code) {
- /* Allocate grays: allocate grays if gray or pseudo-color, else
- return true if gray display supported (e.g. to True/DirectColor).
- */
- case IL_XWC_ALLOC_GRAYS:
- if (pData) {
- context->error = IL_ERROR_OPTION_DATA;
- return FALSE;
- }
- switch (pXWC->i.visualType) {
- case IL_XWC_BITONAL:
- return FALSE;
- case IL_XWC_GRAY_8:
- case IL_XWC_COLOR_8:
- if (ilAllocateXGrays (context, pXWC, IL_DEFAULT_X_GRAYS))
- return TRUE;
- else return FALSE;
- case IL_XWC_COLOR_24:
- return TRUE;
- }
- /* Allocate colors: 8 and 24 bit color only */
- case IL_XWC_ALLOC_COLORS:
- if (pData) {
- context->error = IL_ERROR_OPTION_DATA;
- return FALSE;
- }
- if ((pXWC->i.visualType == IL_XWC_COLOR_8)
- && ilAllocateXDitherColors (context, pXWC))
- return TRUE;
- else if ((pXWC->i.visualType == IL_XWC_COLOR_24)
- && ilAllocateXDirectColors (pXWC, 256))
- return TRUE;
- else return FALSE;
- case IL_XWC_FREE_GRAYS:
- if (pData) {
- context->error = IL_ERROR_OPTION_DATA;
- return FALSE;
- }
- ilFreeColorData (pXWC, IL_FREE_XGRAYS);
- break;
- /* Free colors if 8 or 24 bit color */
- case IL_XWC_FREE_COLORS:
- if (pData) {
- context->error = IL_ERROR_OPTION_DATA;
- return FALSE;
- }
- if ((pXWC->i.visualType == IL_XWC_COLOR_8)
- || (pXWC->i.visualType == IL_XWC_COLOR_24))
- ilFreeColorData (pXWC, IL_FREE_XCOLORS);
- break;
- case IL_XWC_SET_DITHER_METHOD:
- { unsigned int ditherMethod;
- ditherMethod = *((unsigned int *)pData);
- if ((ditherMethod != IL_AREA_DITHER)
- && (ditherMethod != IL_DIFFUSION)
- && (ditherMethod != IL_QUICK_DIFFUSION)) {
- context->error = IL_ERROR_OPTION_DATA;
- return FALSE;
- }
- pXWC->i.ditherMethod = ditherMethod;
- break;
- }
- case IL_XWC_SET_RAW_MODE:
- pXWC->i.rawMode = *((ilBool *)pData);
- break;
- default:
- context->error = IL_ERROR_INVALID_OPTION;
- return FALSE;
- } /* END switch code */
- return TRUE;
- }
- /* ------------------------ ilQueryXWC --------------------------- */
- /* Public function; see spec.
- */
- ilBool ilQueryXWC (
- ilXWC XWC,
- ilXWCInfo *pInfo
- )
- {
- ilXWCPtr pXWC;
- pXWC = (ilXWCPtr)XWC;
- if (pXWC->o.p.objectType != IL_XWC) {
- pXWC->o.p.context->error = IL_ERROR_OBJECT_TYPE;
- return FALSE; /* EXIT */
- }
- *pInfo = pXWC->i;
- pXWC->o.p.context->error = IL_OK;
- return TRUE;
- }
- /* ------------------------ ilCreateXWC ------------------------- */
- /* Public function; see spec.
- Return an error if no (null) display in this context.
- */
- ilXWC ilCreateXWC (
- ilContext context,
- Display *display,
- Visual *visual,
- Colormap colormap,
- GC gc,
- unsigned long mustBeZero1,
- unsigned long mustBeZero2
- )
- {
- ilXWCPtr pXWC;
- XVisualInfo template, *pVisualInfo;
- int notUsed;
- if ((mustBeZero1 != 0) || (mustBeZero2 != 0)) {
- context->error = IL_ERROR_PAR_NOT_ZERO;
- return (ilXWC)NULL; /* EXIT */
- }
- /* A null visual or colormap means output will be to bitmap, else
- get the info for the given visual; exit if not found.
- */
- if (!visual || !colormap) {
- visual = (Visual *)NULL;
- colormap = (Colormap)0;
- }
- else {
- template.visualid = XVisualIDFromVisual (visual);
- pVisualInfo = XGetVisualInfo (display, VisualIDMask, &template,
- ¬Used);
- if (!pVisualInfo) {
- context->error = IL_ERROR_X_RESOURCE;
- return (ilXWC)NULL; /* EXIT */
- }
- }
- /* Create an XWC object and fill it in.
- */
- pXWC = (ilXWCPtr)_ilCreateObject (context, IL_XWC, ilDestroyXWC,
- sizeof (ilXWCRec));
- if (!pXWC)
- return (ilXWC)NULL; /* EXIT */
- pXWC->i.display = display;
- pXWC->i.visual = visual;
- if (visual) {
- pXWC->visualInfo = *pVisualInfo;
- free (pVisualInfo); /* free list from XGetVisualInfo() */
- }
- pXWC->i.gc = gc;
- pXWC->i.colormap = colormap;
- pXWC->pColors = (XColor *)NULL;
- pXWC->nColors = 0;
- pXWC->colorMapImage = (ilClientImage)NULL;
- pXWC->pGrays = (XColor *)NULL;
- pXWC->nGrays = 0;
- pXWC->grayMapImage = (ilClientImage)NULL;
- pXWC->i.ditherMethod = IL_AREA_DITHER;
- pXWC->i.rawMode = FALSE;
- /* Check the class of the given visual and fill in XWC des and format.
- If visual class not supported default to bitonal.
- May also default to bitonal (or color demote to gray) later if
- insufficient colors or grays can be allocated.
- If null visual, do bitonal output.
- */
- pXWC->i.staticVisual = TRUE; /* assume non-writeable colormap */
- if (!visual)
- pXWC->i.visualType = IL_XWC_BITONAL;
- else switch (pXWC->visualInfo.class) {
- case PseudoColor:
- pXWC->i.staticVisual = FALSE;
- case StaticColor:
- if (pXWC->visualInfo.depth == 8)
- pXWC->i.visualType = IL_XWC_COLOR_8;
- else pXWC->i.visualType = IL_XWC_BITONAL;
- break;
- /* Support True/DirectColor if 32 bits format
- = "<unused 8><8R><8G><8B>". */
- case DirectColor:
- pXWC->i.staticVisual = FALSE;
- case TrueColor:
- if ((pXWC->visualInfo.depth == 24)
- && (pXWC->visualInfo.red_mask == 0xff0000)
- && (pXWC->visualInfo.green_mask == 0xff00)
- && (pXWC->visualInfo.blue_mask == 0xff))
- pXWC->i.visualType = IL_XWC_COLOR_24;
- else pXWC->i.visualType = IL_XWC_BITONAL;
- break;
- case GrayScale:
- pXWC->i.staticVisual = FALSE;
- case StaticGray:
- if (pXWC->visualInfo.depth == 8)
- pXWC->i.visualType = IL_XWC_GRAY_8;
- else pXWC->i.visualType = IL_XWC_BITONAL;
- break;
- } /* END switch visual class */
- /* If a bitonal visual, mark as static (non-allocatable colors) */
- if (pXWC->i.visualType == IL_XWC_BITONAL)
- pXWC->i.staticVisual = TRUE;
- context->error = IL_OK;
- return (ilXWC)pXWC;
- }
- /* ======================== WRITE X DRAWABLE CODE ======================== */
- /* Private block for ilRead/WriteXDrawable pipe element. Notes:
- Inited by ilWriteXDrawable():
- imageDepth depth of image to create - set into pPriv when added
- imageFormat X format of image: XYBitmap (bitonal) or ZPixmap
- isLongImage if true: image is 32bits/pixel: set image rowBytes
- to width*4.
- If false: set image rowBytes to row bytes of
- pSrcImage.
- bufferSize size of buffer to create and attach to Ximage.
- pXWC ptr to XWC for this operation
- drawable id of X drawable (Window or Pixmap) to read or write
- x, y read: src (x,y).
- write: dst (x,y) from caller
- Inited by ilWriteXInit():
- Ximage a temp XImage created by Init. Its data ptr is
- pointed directly at the read/write buffer, or
- equals "pBuffer"
- pBuffer ptr to buffer allocated, if bufferSize > 0
- linesDone zeroed by Init(): # of lines written / read so far,
- i.e. y + linesDone is next line to read / write.
- */
- typedef struct {
- int imageDepth;
- int imageFormat;
- ilBool isLongImage;
- unsigned long bufferSize;
- ilXWCPtr pXWC;
- Drawable drawable;
- ilPtr pBuffer;
- XImage *pXImage;
- int x, y;
- long linesDone;
- } ilXPrivRec, *ilXPrivPtr;
- /* ----------------------- ilXDestroy ----------------------------- */
- /* Destroy() function for ilWriteXDrawable() pipe element.
- "Destroys" the associated XWC, whose refCount must have been
- incremented when the element was successfully added to the pipe -
- Destroy downcounts it.
- */
- static ilError ilXDestroy (
- ilPtr pPrivate
- )
- {
- ilXPrivPtr pPriv = (ilXPrivPtr)pPrivate;
- ilDestroyObject ((ilObject)pPriv->pXWC);
- return IL_OK;
- }
- /* ------------------------- ilWriteXInit ------------------------- */
- /* Init() function for ilWriteXDrawable() for all src image types.
- Creates an XImage, which is just a data structure - creates no
- pixel buffer.
- The XImage is freed by ilWriteXCleanup().
- */
- static ilError ilWriteXInit (
- ilPtr pPrivate,
- ilImageInfo *pSrcImage,
- ilImageInfo *pDstImage /* ignored */
- )
- {
- ilXPrivPtr pPriv = (ilXPrivPtr)pPrivate;
- ilXWCPtr pXWC;
- XImage *pXImage;
- /* Create a temp buffer for image pixels if requested. */
- if (pPriv->bufferSize > 0) {
- pPriv->pBuffer = (ilPtr)IL_MALLOC (pPriv->bufferSize);
- if (!pPriv->pBuffer)
- return IL_ERROR_MALLOC; /* EXIT */
- }
- else pPriv->pBuffer = NULL;
- /* Create an XImage that will be pointed to each buffer (strip) to
- write. */
- pXWC = pPriv->pXWC;
- pXImage = XCreateImage (pXWC->i.display, pXWC->i.visual,
- pPriv->imageDepth, pPriv->imageFormat, 0,
- (char *)pPriv->pBuffer, pSrcImage->width,
- pSrcImage->height, pSrcImage->pFormat->rowBitAlign,
- (pPriv->isLongImage) ? (pSrcImage->width * 4) :
- pSrcImage->plane[0].nBytesPerRow);
- if (!pXImage)
- return IL_ERROR_MALLOC; /* EXIT */
- /* Set bit/byte order to MSBFirst.
- NOTE: byte order should be set to byte order of client machine!!!
- */
- #ifdef LSB_BIT_ORDER
- pXImage->byte_order = LSBFirst;
- #else
- pXImage->byte_order = MSBFirst;
- #endif
- pXImage->bitmap_bit_order = MSBFirst;
- pPriv->pXImage = pXImage;
- pPriv->linesDone = 0;
- return IL_OK;
- }
- /* --------------------- ilWriteXCleanup -------------------------- */
- /* Cleanup() function for ilWriteXDrawable() for all src image types.
- Flushes the output if not aborted; frees the XImage created by
- Init() below.
- */
- static ilError ilWriteXCleanup (
- ilPtr pPrivate,
- ilBool aborting
- )
- {
- /* Flush if not aborting. Null the "data" field in image or else
- XDestroyImage() will try to free the pixels; destroy the image,
- created by Init().
- */
- ilXPrivPtr pPriv = (ilXPrivPtr)pPrivate;
- if (!aborting)
- XFlush (pPriv->pXWC->i.display);
- if (pPriv->pBuffer)
- IL_FREE (pPriv->pBuffer);
- pPriv->pXImage->data = (char *)NULL;
- XDestroyImage (pPriv->pXImage);
- return IL_OK;
- }
- /* --------------------- ilWriteXExecute ------------------------- */
- /* Execute() function for ilWriteXDrawable(), for rendering bit or
- byte data.
- Points an XImage created by ilWriteXInit() to the src image bits
- and does an XPutImage(), then bumps a line count so next strip is
- written *pNLines below this one in the drawable.
- */
- static ilError ilWriteXExecute (
- ilExecuteData *pData,
- long dstLine,
- long *pNLines,
- float ratio
- )
- {
- ilXPrivPtr pPriv;
- XImage *pXImage;
- ilXWCPtr pXWC;
- unsigned int nSrcLines;
- unsigned int scaledWidth,scaledHeight;
- int scaledX, scaledY;
- pPriv = (ilXPrivPtr)pData->pPrivate;
- nSrcLines = *pNLines;
- pXImage = pPriv->pXImage;
- pXImage->height = nSrcLines;
- pXImage->data = (char *)(pData->pSrcImage->plane[0].pPixels +
- pData->srcLine * pData->pSrcImage->plane[0].nBytesPerRow);
- pXWC = pPriv->pXWC;
- scaledWidth = pXImage->width * ratio + 0.5;
- scaledX = pPriv->x * ratio + 0.5;
- scaledY = (pPriv->y + pPriv->linesDone) * ratio + 0.5;
- /* we have to think about rounding problem, so recalculate every time. */
- scaledHeight = ((nSrcLines + pPriv->linesDone) * ratio + 0.5)
- - scaledY;
- _XmPutScaledImage (pXWC->i.display, pPriv->drawable,
- pXWC->i.gc, pXImage,
- 0, 0, scaledX, scaledY,
- pXImage->width, nSrcLines,
- scaledWidth,scaledHeight);
- pPriv->linesDone += nSrcLines;
- return IL_OK;
- }
- /* ------------------- ilWriteXOptLongExecute --------------------- */
- /* Execute() function for ilWriteXDrawable(), for display to optimal
- 4 bytes pixel frame buffers. "Optimal" means the 4 bytes (CARD32)
- = "<unused 8> <8 R> <8 G> <8 B>",
- which is the format most commonly used right now.
- Reformat the pipe image pixels, which are 3byte pixel RGB (as
- required by pXWC->format), into 4 bytes words and do the
- XPutImage(), then bump linesDone.
- */
- static ilError ilWriteXOptLongExecute (
- ilExecuteData *pData,
- long dstLine,
- long *pNLines,
- float ratio
- )
- {
- ilXPrivPtr pPriv;
- ilImageInfo *pSrcImage;
- XImage *pXImage;
- ilXWCPtr pXWC;
- ilPtr pSrcLine;
- long srcRowBytes, width, nSrcLines, nLinesM1;
- long nLongsM1;
- ilPtr pSrc;
- CARD32 *pDst, temp;
- unsigned int scaledWidth,scaledHeight;
- int scaledX, scaledY ;
- nSrcLines = *pNLines;
- if (nSrcLines <= 0)
- return 0; /* no lines, EXIT */
- pPriv = (ilXPrivPtr)pData->pPrivate;
- pSrcImage = pData->pSrcImage;
- width = pSrcImage->width;
- if (width <= 0)
- return 0; /* no width, EXIT */
- srcRowBytes = pSrcImage->plane[0].nBytesPerRow;
- pSrcLine = (ilPtr)(pSrcImage->plane[0].pPixels +
- pData->srcLine * srcRowBytes);
- pXImage = pPriv->pXImage;
- pXImage->height = nSrcLines;
- pXImage->data = (char *)pPriv->pBuffer;
- pDst = (CARD32 *)pPriv->pBuffer;
- /* pSrcLine points to first line of pipe image; pDst to buffer of
- X image.
- Convert 3 byte pipe image to CARD32 X buffer image. Dont need
- dstRowBytes because buffer is exactly "width" longs wide (we
- created it.)
- */
- nLinesM1 = nSrcLines - 1;
- do {
- pSrc = pSrcLine;
- pSrcLine += srcRowBytes;
- nLongsM1 = width - 1;
- do {
- temp = *pSrc++;
- temp <<= 8;
- temp |= *pSrc++;
- temp <<= 8;
- temp |= *pSrc++;
- *pDst++ = temp;
- } while (--nLongsM1 >= 0);
- } while (--nLinesM1 >= 0);
- pXWC = pPriv->pXWC;
- scaledWidth = pXImage->width * ratio;
- scaledHeight = nSrcLines * ratio;
- scaledX = pPriv->x * ratio ;
- scaledY = (pPriv->y + pPriv->linesDone)* ratio ;
- _XmPutScaledImage (pXWC->i.display, pPriv->drawable, pXWC->i.gc, pXImage,
- 0, 0, scaledX, scaledY,
- pXImage->width, nSrcLines,
- scaledWidth,scaledHeight);
- pPriv->linesDone += nSrcLines;
- return IL_OK;
- }
- /* ------------------------ ilConvertForXWrite -------------------- */
- /* Public function; see spec.
- Side effect: set pXWC->i.writeType, code for how it will render.
- */
- ilBool ilConvertForXWrite (
- ilPipe pipe,
- ilXWC XWC,
- ilBool mapPixels,
- unsigned long mustBeZero,
- void *mustBeNull
- )
- {
- ilPipeInfo info;
- ilImageDes des;
- ilImageFormat format;
- unsigned int writeType;
- ilXWCPtr pXWC;
- /* Table indexed by [dst visual type], yielding writeType when in raw
- mode */
- static unsigned int rawWriteMethodTable [(IL_X_MAX_VISUAL_TYPE + 1)] = {
- IL_XWC_WRITE_BITONAL, /* IL_XWC_BITONAL */
- IL_XWC_WRITE_GRAY, /* IL_XWC_GRAY_8 */
- IL_XWC_WRITE_COLOR_DITHER, /* IL_XWC_COLOR_8 */
- IL_XWC_WRITE_COLOR /* IL_XWC_COLOR_24 */ };
- /* Table indexed by [image type, dst visual type], yielding writeType,
- assuming best case: colors/grays alloc'd successfully; else writeType
- degrades.
- */
- static unsigned int writeTypeTable [(IL_MAX_TYPE + 1) *
- (IL_X_MAX_VISUAL_TYPE + 1)] =
- { /* (src) image type (dst) visual type writeType */
- /* IL_BITONAL IL_XWC_BITONAL */ IL_XWC_WRITE_BITONAL,
- /* IL_XWC_GRAY_8 */ IL_XWC_WRITE_BITONAL,
- /* IL_XWC_COLOR_8 */ IL_XWC_WRITE_BITONAL,
- /* IL_XWC_COLOR_24 */ IL_XWC_WRITE_BITONAL,
- /* IL_GRAY IL_XWC_BITONAL */ IL_XWC_WRITE_BITONAL,
- /* IL_XWC_GRAY_8 */ IL_XWC_WRITE_GRAY,
- /* IL_XWC_COLOR_8 */ IL_XWC_WRITE_GRAY,
- /* IL_XWC_COLOR_24 */ IL_XWC_WRITE_COLOR,
- /* IL_PALETTE IL_XWC_BITONAL */ IL_XWC_WRITE_BITONAL,
- /* IL_XWC_GRAY_8 */ IL_XWC_WRITE_GRAY,
- /* IL_XWC_COLOR_8 */ IL_XWC_WRITE_COLOR_DITHER,
- /* IL_XWC_COLOR_24 */ IL_XWC_WRITE_COLOR,
- /* IL_RGB IL_XWC_BITONAL */ IL_XWC_WRITE_BITONAL,
- /* IL_XWC_GRAY_8 */ IL_XWC_WRITE_GRAY,
- /* IL_XWC_COLOR_8 */ IL_XWC_WRITE_COLOR_DITHER,
- /* IL_XWC_COLOR_24 */ IL_XWC_WRITE_COLOR,
- /* IL_YCBCR IL_XWC_BITONAL */ IL_XWC_WRITE_BITONAL,
- /* IL_XWC_GRAY_8 */ IL_XWC_WRITE_GRAY,
- /* IL_XWC_COLOR_8 */ IL_XWC_WRITE_COLOR_DITHER,
- /* IL_XWC_COLOR_24 */ IL_XWC_WRITE_COLOR
- };
-
- if (pipe->objectType != IL_PIPE) {
- pipe->context->error = IL_ERROR_OBJECT_TYPE;
- return FALSE;
- }
- if (mustBeZero || mustBeNull)
- return ilDeclarePipeInvalid (pipe, IL_ERROR_PAR_NOT_ZERO);
- /* Validate that given XWC is one, and is same context as pipe. */
- pXWC = (ilXWCPtr)XWC;
- if (pXWC->o.p.objectType != IL_XWC)
- return ilDeclarePipeInvalid (pipe, IL_ERROR_OBJECT_TYPE);
- if (pXWC->o.p.context != pipe->context)
- return ilDeclarePipeInvalid (pipe, IL_ERROR_CONTEXT_MISMATCH);
- /* Get pipe info and decompress; if pipe not in IL_PIPE_FORMING state,
- error. */
- if (ilGetPipeInfo (pipe, TRUE, &info, &des, &format) != IL_PIPE_FORMING) {
- if (!pipe->context->error)
- ilDeclarePipeInvalid (pipe, IL_ERROR_PIPE_STATE);
- return FALSE;
- }
- /* If raw mode, allocate no colors, output based on dst visual type,
- except for bit/pixel images: output using bitonal approach; else:
- get "writeType" based on des.type (private types not supported)
- and pXWC->i.visualType. Check for allocated dither colors
- (default to gray if not enough) and grays (default to bitonal if
- not enough).
- Pretend YCbCr is RGB - an ilConvert() to RGB will be done below
- anyway.
- */
- if (pXWC->i.rawMode) {
- if ((des.nSamplesPerPixel == 1) && (format.nBitsPerSample[0] == 1))
- writeType = IL_XWC_WRITE_BITONAL;
- else writeType = rawWriteMethodTable [pXWC->i.visualType];
- }
- else {
- if (des.type > IL_MAX_TYPE)
- return ilDeclarePipeInvalid (pipe, IL_ERROR_IMAGE_TYPE);
- if (des.type == IL_YCBCR)
- des.type = IL_RGB;
- writeType = writeTypeTable
- [des.type * (IL_X_MAX_VISUAL_TYPE + 1) + pXWC->i.visualType];
- if (writeType == IL_XWC_WRITE_COLOR_DITHER) {
- if (!pXWC->colorMapImage)
- ilChangeXWC ((ilXWC)pXWC, IL_XWC_ALLOC_DITHER_COLORS,
- (ilPtr)NULL);
- if (!pXWC->colorMapImage)
- writeType = IL_XWC_WRITE_GRAY;
- }
- if (writeType == IL_XWC_WRITE_GRAY) {
- if (!pXWC->grayMapImage)
- ilChangeXWC ((ilXWC)pXWC, IL_XWC_ALLOC_GRAYS, (ilPtr)NULL);
- if (!pXWC->grayMapImage)
- writeType = IL_XWC_WRITE_BITONAL;
- }
- /* If RGB display alloc colors or dflt to bitonal. */
- if (writeType == IL_XWC_WRITE_COLOR) {
- if (!pXWC->colorMapImage)
- if (!ilAllocateXDirectColors (pXWC, 256))
- writeType = IL_XWC_WRITE_BITONAL;
- }
- } /* END not raw mode */
- /* Do ilConvert() and add filter(s) based on "writeType". */
- switch (writeType) {
- /* Bitonal: do an XPutImage() with XYBitmap, which renders image 0's
- with GC background color, 1's with foreground, as defined by IL
- spec.
- If rawMode, must be bit/pixel.
- */
- case IL_XWC_WRITE_BITONAL:
- if (pXWC->i.rawMode) {
- if ((des.nSamplesPerPixel != 1) || (format.nBitsPerSample[0] != 1))
- return ilDeclarePipeInvalid (pipe, IL_ERROR_RAW_MODE);
- }
- else if (!ilConvert (pipe, IL_DES_BITONAL, IL_FORMAT_BIT, 0, NULL))
- return FALSE;
- break;
- /* Gray: do ilMap() which maps 256 gray shades to the equivalent
- X pixel values, possibly using fewer shades of gray (slam; not
- dithered to lesser # grays).
- */
- case IL_XWC_WRITE_GRAY:
- if (pXWC->i.rawMode) {
- if ((des.nSamplesPerPixel != 1) || (format.nBitsPerSample[0] != 8))
- return ilDeclarePipeInvalid (pipe, IL_ERROR_RAW_MODE);
- }
- else {
- if (!ilConvert (pipe, IL_DES_GRAY, IL_FORMAT_BYTE, 0, NULL))
- return FALSE;
- if (mapPixels)
- if (!ilMap (pipe, pXWC->grayMapImage))
- return FALSE;
- }
- break;
- /* Dithered RGB: if raw mode, accept if byte/pixel;
- if a pre-dithered palette image in pipe, ilMap() to map colors to
- X pixels;
- otherwise dither cvt to palette w/ map to the allocated colors.
- */
- case IL_XWC_WRITE_COLOR_DITHER:
- if (pXWC->i.rawMode) {
- if ((des.nSamplesPerPixel != 1) || (format.nBitsPerSample[0] != 8))
- return ilDeclarePipeInvalid (pipe, IL_ERROR_RAW_MODE);
- }
- else if ((des.flags & IL_DITHERED_PALETTE)
- && (des.typeInfo.palette.levels[0] == NRED)
- && (des.typeInfo.palette.levels[1] == NGREEN)
- && (des.typeInfo.palette.levels[2] == NBLUE)) {
- if ((format.nBitsPerSample[0] != 8)
- && !ilConvert (pipe, (ilImageDes *)NULL, IL_FORMAT_BYTE, 0,
- NULL))
- return FALSE;
- if (mapPixels)
- if (!ilMap (pipe, pXWC->colorMapImage))
- return FALSE;
- }
- else {
- ilConvertToPaletteInfo cvt;
- cvt.method = pXWC->i.ditherMethod;
- cvt.levels[0] = NRED;
- cvt.levels[1] = NGREEN;
- cvt.levels[2] = NBLUE;
- cvt.kernelSize = 8;
- if (mapPixels) {
- cvt.dstType = IL_GRAY; /* any type other than IL_PALETTE */
- cvt.mapImage = pXWC->colorMapImage;
- }
- else {
- cvt.dstType = IL_PALETTE;
- cvt.mapImage = (ilClientImage)NULL;
- }
- if (!ilConvert (pipe, IL_DES_PALETTE, IL_FORMAT_BYTE,
- IL_CONVERT_TO_PALETTE, &cvt))
- return FALSE;
- }
- break;
- /* RGB: if raw mode, check format, else convert to RGB, and if
- mapPixels and map needed (ramp not 0..255 each component) do
- an ilMap().
- */
- case IL_XWC_WRITE_COLOR:
- {
- if (pXWC->i.rawMode) {
- if ((des.nSamplesPerPixel != 3)
- || (format.nBitsPerSample[0] != 8)
- || (format.nBitsPerSample[1] != 8)
- || (format.nBitsPerSample[2] != 8)
- || (format.sampleOrder != IL_SAMPLE_PIXELS))
- return ilDeclarePipeInvalid (pipe, IL_ERROR_RAW_MODE);
- }
- else {
- if (!ilConvert (pipe, IL_DES_RGB, IL_FORMAT_3BYTE_PIXEL, 0, NULL))
- return FALSE;
- if (mapPixels && pXWC->mapDirect)
- if (!ilMap (pipe, pXWC->colorMapImage))
- return FALSE;
- }
- }
- break;
- } /* END switch writeType */
- pXWC->i.writeType = writeType; /* set method of writing to be used */
- pipe->context->error = IL_OK;
- return TRUE;
- }
- /* ------------------------ ilWriteXDrawable ---------------------- */
- /* Public function; see spec.
- */
- ilBool ilWriteXDrawable (
- ilPipe pipe,
- Drawable drawable,
- ilXWC XWC,
- ilRect *pSrcRect,
- int dstX,
- int dstY,
- unsigned long mustBeZero
- )
- {
- ilPipeInfo info;
- ilXWCPtr pXWC;
- ilXPrivPtr pPriv;
- ilSrcElementData *pSrcData, srcData;
- unsigned long bufferSize = 0;
- /*
- ** We need to use the execute fucntion with the ratio parameter.
- */
- ilError (*executeFunction)( ilExecuteData *,
- long,
- long *,
- float);
- /* If a src clip rect, insert an ilCrop() element before us.
- In the future, should look at pipe and handle some cases directly.
- */
- if (pSrcRect && !ilCrop (pipe, pSrcRect))
- return FALSE;
- /* Convert as necessary, mapping pixels to X pixels and get
- pXWC->i.writeType */
- pXWC = (ilXWCPtr)XWC;
- if (!ilConvertForXWrite (pipe, (ilXWC)pXWC, TRUE, 0, NULL))
- return FALSE;
- ilGetPipeInfo (pipe, FALSE, &info, (ilImageDes *)NULL,
- (ilImageFormat *)NULL);
- /* If writing 24 bits: use separate executeFunction, set "bufferSize"
- to buffer to be allocated, and if too large force pipe to give us
- smaller strips.
- */
- if (pXWC->i.writeType == IL_XWC_WRITE_COLOR) {
- bufferSize = (info.width * 4) * info.stripHeight;
- if (bufferSize > MAX_IMAGE_BUFFER_SIZE) {
- srcData.consumerImage = (ilObject)NULL;
- srcData.stripHeight = BEST_IMAGE_BUFFER_SIZE / (4 * info.width);
- if (srcData.stripHeight < 1)
- srcData.stripHeight = 1;
- srcData.constantStrip = FALSE;
- srcData.minBufferHeight = 0;
- pSrcData = &srcData;
- }
- else pSrcData = (ilSrcElementData *)NULL;
- executeFunction = ilWriteXOptLongExecute;
- }
- else {
- pSrcData = (ilSrcElementData *)NULL;
- executeFunction = ilWriteXExecute;
- }
- /* Add a consumer which does an XPutImage() using the pipe data
- cvt'd above.
- Increment the XWC refCount; element's Destroy() function
- ilXDestroy() will decrement it when this pipe element is removed.
- */
- pPriv = (ilXPrivPtr)ilAddPipeElement (pipe, IL_CONSUMER,
- sizeof(ilXPrivRec), 0, pSrcData, (ilDstElementData *)NULL,
- ilWriteXInit, ilWriteXCleanup, ilXDestroy, NULL, executeFunction, 0);
- if (!pPriv) return FALSE; /* EXIT */
- pPriv->pXWC = pXWC;
- pPriv->drawable = drawable;
- pPriv->x = dstX;
- pPriv->y = dstY;
- pXWC->o.refCount++;
- /* Set writeType-specific values in *pPriv */
- switch (pXWC->i.writeType) {
- case IL_XWC_WRITE_BITONAL:
- pPriv->imageDepth = 1;
- pPriv->imageFormat = XYBitmap;
- pPriv->isLongImage = FALSE;
- pPriv->bufferSize = 0;
- break;
- case IL_XWC_WRITE_GRAY:
- pPriv->imageDepth = 8;
- pPriv->imageFormat = ZPixmap;
- pPriv->isLongImage = FALSE;
- pPriv->bufferSize = 0;
- break;
- case IL_XWC_WRITE_COLOR_DITHER:
- pPriv->imageDepth = 8;
- pPriv->imageFormat = ZPixmap;
- pPriv->isLongImage = FALSE;
- pPriv->bufferSize = 0;
- break;
- case IL_XWC_WRITE_COLOR:
- pPriv->bufferSize = bufferSize; /* from above */
- pPriv->imageDepth = 24;
- pPriv->imageFormat = ZPixmap;
- pPriv->isLongImage = TRUE;
- break;
- }
- pipe->context->error = IL_OK;
- return TRUE;
- }
|