2
0

ilX.c 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  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)
  10. * any later version.
  11. *
  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
  16. * details.
  17. *
  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
  22. */
  23. /* $XConsortium: ilX.c /main/11 1996/11/12 05:02:17 pascale $ */
  24. /**---------------------------------------------------------------------
  25. ***
  26. *** (c)Copyright 1991 Hewlett-Packard Co.
  27. ***
  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).
  37. ***
  38. ***-------------------------------------------------------------------*/
  39. #include "ilint.h"
  40. #include "ilcontext.h"
  41. #include "ilX.h"
  42. #include <math.h>
  43. #include <stdlib.h>
  44. #include <X11/Xutil.h>
  45. #include "ilpipelem.h"
  46. #include "ilerrors.h"
  47. #include <Xm/XmPrivate.h>
  48. #define X_COLOR_MAX 65535 /* max value for X colormap RGB
  49. value */
  50. /* Buffer allocation checks. Buffers are allocated for example when
  51. writing to a 24 bit drawable: the pipe image pixels are converted
  52. from 3 bytes to 4 bytes (CARD32).
  53. */
  54. #define MAX_IMAGE_BUFFER_SIZE 100000 /* force strips if larger than
  55. this ... */
  56. #define BEST_IMAGE_BUFFER_SIZE 50000 /* to strips of this size */
  57. /* Masks for ilFreeColorData(); see below.
  58. */
  59. #define IL_FREE_XCOLORS (1<<0)
  60. #define IL_FREE_XGRAYS (1<<1)
  61. /* Codes for view of X , in "ilXWCRec.i.visualType". When the visual is
  62. unsupported or an insufficient # of colors can be allocated from the
  63. colormap, the drawable defaults to IL_XWC_BITONAL. Images rendered
  64. to such an XWC are converted to bitonal, then XPutImage() of an
  65. XYBitmap is done - the XWC GC's foreground/background colors are used
  66. for black/white.
  67. */
  68. #define IL_X_MAX_VISUAL_TYPE 3 /* max value of IL_XWC_BITONAL
  69. et al*/
  70. /* Default # of grays or dither colors to allocate for pseudo-color. */
  71. #define IL_DEFAULT_X_GRAYS 32
  72. #define NRED 4
  73. #define NGREEN 8
  74. #define NBLUE 4
  75. /* Internals of an XWC (X Write Context), an IL object created by
  76. ilCreateXWC().
  77. An XWC is associated with the visual "visual" and "colormap".
  78. "i" contains basic information returned by ilQueryXWC().
  79. If pColors is non-null, it points to a list of length "nColors",
  80. of colors allocated from "colormap". "pad" in each colorcell is
  81. used as a flag:
  82. == 0 if color not allocated, else color was sucessfully allocated.
  83. If non-null, colorMapImage is an image for mapping to X images
  84. using ilMap().
  85. For example, for 8 bit pseudo-color when 484 color handling is used,
  86. "pColors" points to 128 colors, and "colorMapImage" points to a 256
  87. pixel image where each entry is the pixel to use for color
  88. (red*4*8 + green*8 + blue).
  89. If "colorMapImage" is null then the alloc failed or has not been tried.
  90. Note: above applies also to Direct/TrueColor visuals, with the same
  91. names.
  92. The above also applies to the "gray" fields, with the "gray" names.
  93. */
  94. typedef struct {
  95. ilObjectRec o; /* std header: MUST BE FIRST */
  96. ilXWCInfo i; /* see above */
  97. XVisualInfo visualInfo; /* X info on "visual" */
  98. XColor *pColors; /* ptr to list of allocated
  99. colors or null */
  100. int nColors; /* size of *pColors list */
  101. ilClientImage colorMapImage; /* see above */
  102. ilBool mapDirect; /* ilMap(colorMapImage),
  103. Direct/TrueColor */
  104. XColor *pGrays; /* ptr to list of allocated grays
  105. or null */
  106. int nGrays; /* size of *pGrays list */
  107. ilClientImage grayMapImage; /* same as colorMapImage, but for
  108. grays */
  109. } ilXWCRec, *ilXWCPtr;
  110. typedef ilError (*executeFunctionType)();
  111. /* ------------------------ ilFreeColorData ---------------------- */
  112. /* Free the color list and translation table in the given XWC if
  113. present. "freeMasks" indicates which should be freed:
  114. IL_FREE_XCOLORS/XGRAYS, or ~0 for everything.
  115. */
  116. static void ilFreeColorData (
  117. ilXWCPtr pXWC,
  118. unsigned long freeMask
  119. )
  120. {
  121. int i;
  122. XColor *pColor;
  123. /* If color list present: free each color if allocated (pad != 0);
  124. free list.
  125. */
  126. if (freeMask & IL_FREE_XCOLORS) {
  127. if (pXWC->pColors) {
  128. for (i = 0, pColor = pXWC->pColors; i < pXWC->nColors; i++) {
  129. if (pColor->pad)
  130. XFreeColors (pXWC->i.display, pXWC->i.colormap,
  131. &pColor->pixel, 1, 0L);
  132. pColor++;
  133. }
  134. IL_FREE (pXWC->pColors);
  135. pXWC->pColors = (XColor *)NULL;
  136. pXWC->nColors = 0;
  137. }
  138. if (pXWC->colorMapImage) {
  139. ilDestroyObject (pXWC->colorMapImage);
  140. pXWC->colorMapImage = (ilClientImage)NULL;
  141. }
  142. }
  143. /* Same for gray list
  144. */
  145. if (freeMask & IL_FREE_XGRAYS) {
  146. if (pXWC->pGrays) {
  147. for (i = 0, pColor = pXWC->pGrays; i < pXWC->nGrays; i++) {
  148. if (pColor->pad)
  149. XFreeColors (pXWC->i.display, pXWC->i.colormap,
  150. &pColor->pixel, 1, 0L);
  151. pColor++;
  152. }
  153. IL_FREE (pXWC->pGrays);
  154. pXWC->pGrays = (XColor *)NULL;
  155. pXWC->nGrays = 0;
  156. }
  157. if (pXWC->grayMapImage) {
  158. ilDestroyObject (pXWC->grayMapImage);
  159. pXWC->grayMapImage = (ilClientImage)NULL;
  160. }
  161. }
  162. }
  163. /* ----------------------- ilDestroyXWC -------------------------- */
  164. /* Destroy() function for XWC objects. Free the color list if
  165. present.
  166. The GC for the default XWC will be destroyed when the context is
  167. freed, by ilXDestroyContext() below.
  168. */
  169. static void ilDestroyXWC (
  170. ilPtr pPrivate
  171. )
  172. {
  173. ilObject object = (ilObject)pPrivate;
  174. ilXWCPtr pXWC;
  175. pXWC = (ilXWCPtr)object;
  176. /* ~ on signed integer is not recommended, play it safe here */
  177. ilFreeColorData (pXWC, ~(0UL));
  178. }
  179. /* --------------------- ilGammaCorrect -------------------------- */
  180. /* Returns a value from 0..scaleValue, given "value", from
  181. 0.."maxValue" - 1, scaled up to "scaleValue" (e.g. 65535 for
  182. X color values).
  183. Currently a misnomer - not doing any gamma correction
  184. (gamma = 1.0).
  185. */
  186. static int ilGammaCorrect (
  187. long scaleValue,
  188. int value,
  189. int maxValue
  190. )
  191. {
  192. int allocValue;
  193. if (value == 0)
  194. allocValue = 0;
  195. else if (value == (maxValue - 1))
  196. allocValue = scaleValue;
  197. else {
  198. allocValue = value * scaleValue / (maxValue-1);
  199. if (allocValue < 0)
  200. allocValue = 0;
  201. else if (allocValue > scaleValue)
  202. allocValue = scaleValue;
  203. }
  204. return allocValue;
  205. }
  206. /* --------------------- ilAllocateXDitherColors ------------------ */
  207. /* Internal function to ilCreateXWC(). Attempts to allocate enough
  208. colors in pXWC->i.colormap to support the visual as a 484
  209. pseudo-color visual.
  210. An error code is returned to the given context if an error
  211. (e.g. malloc) error occurs; IL_OK if the grays could not be
  212. alloc'd (but false is returned).
  213. */
  214. static ilBool ilAllocateXDitherColors (
  215. ilContext context,
  216. ilXWCPtr pXWC
  217. )
  218. {
  219. int i, red, green, blue;
  220. XColor *pColor;
  221. ilPtr pTranslate;
  222. ilImageInfo imageInfo, *pImageInfo;
  223. context->error = IL_OK; /* assume no errors */
  224. if (pXWC->colorMapImage)
  225. return TRUE; /* already alloc'd; EXIT */
  226. /* Allocate a client image to use as LUT for mapping to X's
  227. colors.
  228. Point pTranslate to the allocated pixels.
  229. */
  230. imageInfo.pDes = IL_DES_GRAY;
  231. imageInfo.pFormat = IL_FORMAT_BYTE;
  232. imageInfo.width = 256;
  233. imageInfo.height = 1;
  234. imageInfo.clientPixels = FALSE;
  235. pXWC->colorMapImage = ilCreateClientImage (context, &imageInfo, 0);
  236. if (!pXWC->colorMapImage)
  237. return FALSE; /* EXIT */
  238. ilQueryClientImage (pXWC->colorMapImage, &pImageInfo, 0);
  239. pTranslate = pImageInfo->plane[0].pPixels;
  240. pXWC->nColors = NRED * NGREEN * NBLUE;
  241. pXWC->pColors = (XColor *)IL_MALLOC (pXWC->nColors * sizeof(XColor));
  242. if (!pXWC->pColors) {
  243. ilDestroyObject (pXWC->colorMapImage);
  244. pXWC->colorMapImage = (ilClientImage)NULL;
  245. context->error = IL_ERROR_MALLOC;
  246. return FALSE; /* EXIT */
  247. }
  248. for (i = 0, pColor = pXWC->pColors; i < pXWC->nColors; i++, pColor++)
  249. pColor->pad = FALSE; /* init pad, in case below fails */
  250. /* Allocate 484 colors (128 in all) */
  251. pColor = pXWC->pColors;
  252. for (red = 0; red < NRED; red++)
  253. for (green = 0; green < NGREEN; green++)
  254. for (blue = 0; blue < NBLUE; blue++) {
  255. pColor->red = ilGammaCorrect (X_COLOR_MAX, red, NRED);
  256. pColor->green = ilGammaCorrect (X_COLOR_MAX, green, NGREEN);
  257. pColor->blue = ilGammaCorrect (X_COLOR_MAX, blue, NBLUE);
  258. if (!XAllocColor (pXWC->i.display, pXWC->i.colormap, pColor)) {
  259. ilFreeColorData (pXWC, IL_FREE_XCOLORS);
  260. return FALSE;
  261. }
  262. pTranslate [red*(NGREEN*NBLUE) + green*NBLUE + blue] =
  263. pColor->pixel;
  264. pColor->pad = TRUE; /* mark as alloc'd */
  265. pColor++;
  266. }
  267. return TRUE; /* colors successfully alloc'd */
  268. }
  269. /* ---------------------------- ilAllocateXGrays ---------------------- */
  270. /* Allocate "nGrays" from the colormap associated with the given XWC or
  271. return error.
  272. The grays are ramped evenly from 0..nGrays-1. If there are "nGrays"
  273. existing grays, they are used, else if not nGrays, they are
  274. deallocated.
  275. An error code is returned to the given context if an error
  276. (e.g. malloc) error occurs; IL_OK if the grays could not be alloc'd
  277. (but false is returned).
  278. */
  279. static ilBool ilAllocateXGrays (
  280. ilContext context,
  281. ilXWCPtr pXWC,
  282. int nGrays
  283. )
  284. {
  285. int i, index;
  286. XColor *pColor;
  287. ilPtr pTranslate;
  288. ilImageInfo imageInfo, *pImageInfo;
  289. double spreadFactor;
  290. /* Use the grays if the same number, else deallocate them.
  291. */
  292. context->error = IL_OK; /* assume no errors */
  293. if (pXWC->pGrays) {
  294. if (pXWC->nGrays == nGrays)
  295. return TRUE;
  296. else ilFreeColorData (pXWC, IL_FREE_XGRAYS);
  297. }
  298. if (nGrays > 256)
  299. return FALSE; /* EXIT */
  300. /* Allocate a client image to use as LUT for mapping to X's colors.
  301. Point pTranslate to the allocated pixels.
  302. */
  303. imageInfo.pDes = IL_DES_GRAY;
  304. imageInfo.pFormat = IL_FORMAT_BYTE;
  305. imageInfo.width = 256;
  306. imageInfo.height = 1;
  307. imageInfo.clientPixels = FALSE;
  308. pXWC->grayMapImage = ilCreateClientImage (context, &imageInfo, 0);
  309. if (!pXWC->grayMapImage)
  310. return FALSE; /* EXIT */
  311. ilQueryClientImage (pXWC->grayMapImage, &pImageInfo, 0);
  312. pTranslate = pImageInfo->plane[0].pPixels;
  313. pXWC->nGrays = nGrays;
  314. pXWC->pGrays = (XColor *)IL_MALLOC (pXWC->nGrays * sizeof(XColor));
  315. if (!pXWC->pGrays) {
  316. ilDestroyObject (pXWC->grayMapImage);
  317. pXWC->colorMapImage = (ilClientImage)NULL;
  318. context->error = IL_ERROR_MALLOC;
  319. return FALSE; /* EXIT */
  320. }
  321. for (i = 0, pColor = pXWC->pGrays; i < pXWC->nGrays; i++, pColor++)
  322. pColor->pad = FALSE; /* init pad, in case below fails */
  323. /* Allocate the grays; return error on any failure. */
  324. for (i = 0; i < nGrays; i++) {
  325. pColor = &pXWC->pGrays [i];
  326. pColor->red = pColor->green = pColor->blue =
  327. ilGammaCorrect (X_COLOR_MAX, i, nGrays);
  328. if (!XAllocColor (pXWC->i.display, pXWC->i.colormap, pColor)) {
  329. pColor->pad = FALSE;
  330. ilFreeColorData (pXWC, IL_FREE_XGRAYS);
  331. return FALSE; /* EXIT */
  332. }
  333. pColor->pad = TRUE;
  334. }
  335. /* Grays allocated ok; spread the allocated colors over the whole 256
  336. area. In effect, color-slam all 256-level gray images into nGrays.
  337. NOTE: gray images with other than 256 levels could be supported in
  338. future!
  339. */
  340. spreadFactor = ((double)(nGrays - 1)) / (double)255;
  341. pColor = pXWC->pGrays;
  342. for (i = 0; i < 256; i++) {
  343. index = spreadFactor * (double)i + 0.5;
  344. if (index > (nGrays - 1))
  345. index = nGrays - 1;
  346. pTranslate [i] = pColor [index].pixel;
  347. }
  348. return TRUE;
  349. }
  350. /* ---------------------- ilAllocateXDirectColors --------------------- */
  351. /* Allocate "nLevels" levels of each of RGB for a DirectColor or a
  352. TrueColor visual.
  353. "nLevels" should be passed as 256; it becomes 1/2 of that if failure
  354. occurs this function recurses on failure until an unacceptable # of
  355. levels not alloc'd.
  356. */
  357. static ilBool ilAllocateXDirectColors (
  358. ilXWCPtr pXWC,
  359. int nLevels
  360. )
  361. {
  362. int i, j, pixel, red, green, blue, nReplicate;
  363. XColor *pColor;
  364. ilPtr pTranslate;
  365. ilImageInfo imageInfo, *pImageInfo;
  366. ilContext context;
  367. #define MIN_DIRECT_LEVELS 32 /* min # of acceptable levels */
  368. if (pXWC->colorMapImage)
  369. return TRUE; /* already alloc'd; EXIT */
  370. /* Create a 256x1 3 byte/pixel map image. */
  371. context = pXWC->o.p.context;
  372. imageInfo.pDes = IL_DES_RGB;
  373. imageInfo.pFormat = IL_FORMAT_3BYTE_PIXEL;
  374. imageInfo.width = 256;
  375. imageInfo.height = 1;
  376. imageInfo.clientPixels = FALSE;
  377. pXWC->colorMapImage = ilCreateClientImage (context, &imageInfo, 0);
  378. if (!pXWC->colorMapImage)
  379. return FALSE;
  380. ilQueryClientImage (pXWC->colorMapImage, &pImageInfo, 0);
  381. pTranslate = pImageInfo->plane[0].pPixels;
  382. /* Try to allocate nLevels read-only levels each of RGB, in a logical
  383. ramp order. Set pXWC->mapDirect to false if pixel value != RGB
  384. value, in which case pipe image pixels must be ilMap()'d to X
  385. pixel values.
  386. If can't allocate, try to allocate nLevels/2 unless that is too
  387. few colors, in which we fail. Spread the X pixels into the 256
  388. entry map image.
  389. */
  390. pXWC->nColors = nLevels;
  391. pXWC->pColors = (XColor *)IL_MALLOC_ZERO (pXWC->nColors * sizeof(XColor));
  392. if (!pXWC->pColors) {
  393. ilDestroyObject (pXWC->colorMapImage);
  394. pXWC->colorMapImage = (ilClientImage)NULL;
  395. context->error = IL_ERROR_MALLOC;
  396. return FALSE;
  397. }
  398. pXWC->mapDirect = FALSE;
  399. nReplicate = 256 / nLevels; /* # of times to replicate pixel into map
  400. image */
  401. for (i = 0, pColor = pXWC->pColors; i < nLevels; i++, pColor++) {
  402. pColor->red = pColor->green = pColor->blue =
  403. ilGammaCorrect (X_COLOR_MAX, i, nLevels);
  404. pColor->flags = DoRed | DoGreen | DoBlue;
  405. if (!XAllocColor (pXWC->i.display, pXWC->i.colormap, pColor)) {
  406. ilFreeColorData (pXWC, IL_FREE_XCOLORS);
  407. if (nLevels <= MIN_DIRECT_LEVELS)
  408. return FALSE;
  409. else return ilAllocateXDirectColors (pXWC, nLevels / 2);
  410. }
  411. pColor->pad = TRUE; /* mark as alloc'd */
  412. pixel = pColor->pixel;
  413. red = (pixel >> 16) & 0xff;
  414. green = (pixel >> 8) & 0xff;
  415. blue = pixel & 0xff;
  416. if ((red != i) || (green != i) || (blue != i))
  417. pXWC->mapDirect = TRUE;
  418. for (j = 0; j < nReplicate; j++) { /* replicate into map image */
  419. *pTranslate++ = red;
  420. *pTranslate++ = green;
  421. *pTranslate++ = blue;
  422. }
  423. }
  424. return TRUE;
  425. }
  426. /* ------------------------ ilChangeXWC --------------------------- */
  427. /* Public function; see spec.
  428. */
  429. ilBool ilChangeXWC (
  430. ilXWC XWC,
  431. unsigned int code,
  432. void *pData
  433. )
  434. {
  435. ilXWCPtr pXWC;
  436. ilContext context;
  437. pXWC = (ilXWCPtr)XWC;
  438. context = pXWC->o.p.context;
  439. context->error = IL_OK; /* assume no error */
  440. if (pXWC->o.p.objectType != IL_XWC) {
  441. context->error = IL_ERROR_OBJECT_TYPE;
  442. return FALSE; /* EXIT */
  443. }
  444. switch (code) {
  445. /* Allocate grays: allocate grays if gray or pseudo-color, else
  446. return true if gray display supported (e.g. to True/DirectColor).
  447. */
  448. case IL_XWC_ALLOC_GRAYS:
  449. if (pData) {
  450. context->error = IL_ERROR_OPTION_DATA;
  451. return FALSE;
  452. }
  453. switch (pXWC->i.visualType) {
  454. case IL_XWC_BITONAL:
  455. return FALSE;
  456. case IL_XWC_GRAY_8:
  457. case IL_XWC_COLOR_8:
  458. if (ilAllocateXGrays (context, pXWC, IL_DEFAULT_X_GRAYS))
  459. return TRUE;
  460. else return FALSE;
  461. case IL_XWC_COLOR_24:
  462. return TRUE;
  463. }
  464. /* Allocate colors: 8 and 24 bit color only */
  465. case IL_XWC_ALLOC_COLORS:
  466. if (pData) {
  467. context->error = IL_ERROR_OPTION_DATA;
  468. return FALSE;
  469. }
  470. if ((pXWC->i.visualType == IL_XWC_COLOR_8)
  471. && ilAllocateXDitherColors (context, pXWC))
  472. return TRUE;
  473. else if ((pXWC->i.visualType == IL_XWC_COLOR_24)
  474. && ilAllocateXDirectColors (pXWC, 256))
  475. return TRUE;
  476. else return FALSE;
  477. case IL_XWC_FREE_GRAYS:
  478. if (pData) {
  479. context->error = IL_ERROR_OPTION_DATA;
  480. return FALSE;
  481. }
  482. ilFreeColorData (pXWC, IL_FREE_XGRAYS);
  483. break;
  484. /* Free colors if 8 or 24 bit color */
  485. case IL_XWC_FREE_COLORS:
  486. if (pData) {
  487. context->error = IL_ERROR_OPTION_DATA;
  488. return FALSE;
  489. }
  490. if ((pXWC->i.visualType == IL_XWC_COLOR_8)
  491. || (pXWC->i.visualType == IL_XWC_COLOR_24))
  492. ilFreeColorData (pXWC, IL_FREE_XCOLORS);
  493. break;
  494. case IL_XWC_SET_DITHER_METHOD:
  495. { unsigned int ditherMethod;
  496. ditherMethod = *((unsigned int *)pData);
  497. if ((ditherMethod != IL_AREA_DITHER)
  498. && (ditherMethod != IL_DIFFUSION)
  499. && (ditherMethod != IL_QUICK_DIFFUSION)) {
  500. context->error = IL_ERROR_OPTION_DATA;
  501. return FALSE;
  502. }
  503. pXWC->i.ditherMethod = ditherMethod;
  504. break;
  505. }
  506. case IL_XWC_SET_RAW_MODE:
  507. pXWC->i.rawMode = *((ilBool *)pData);
  508. break;
  509. default:
  510. context->error = IL_ERROR_INVALID_OPTION;
  511. return FALSE;
  512. } /* END switch code */
  513. return TRUE;
  514. }
  515. /* ------------------------ ilQueryXWC --------------------------- */
  516. /* Public function; see spec.
  517. */
  518. ilBool ilQueryXWC (
  519. ilXWC XWC,
  520. ilXWCInfo *pInfo
  521. )
  522. {
  523. ilXWCPtr pXWC;
  524. pXWC = (ilXWCPtr)XWC;
  525. if (pXWC->o.p.objectType != IL_XWC) {
  526. pXWC->o.p.context->error = IL_ERROR_OBJECT_TYPE;
  527. return FALSE; /* EXIT */
  528. }
  529. *pInfo = pXWC->i;
  530. pXWC->o.p.context->error = IL_OK;
  531. return TRUE;
  532. }
  533. /* ------------------------ ilCreateXWC ------------------------- */
  534. /* Public function; see spec.
  535. Return an error if no (null) display in this context.
  536. */
  537. ilXWC ilCreateXWC (
  538. ilContext context,
  539. Display *display,
  540. Visual *visual,
  541. Colormap colormap,
  542. GC gc,
  543. unsigned long mustBeZero1,
  544. unsigned long mustBeZero2
  545. )
  546. {
  547. ilXWCPtr pXWC;
  548. XVisualInfo template, *pVisualInfo;
  549. int notUsed;
  550. if ((mustBeZero1 != 0) || (mustBeZero2 != 0)) {
  551. context->error = IL_ERROR_PAR_NOT_ZERO;
  552. return (ilXWC)NULL; /* EXIT */
  553. }
  554. /* A null visual or colormap means output will be to bitmap, else
  555. get the info for the given visual; exit if not found.
  556. */
  557. if (!visual || !colormap) {
  558. visual = (Visual *)NULL;
  559. colormap = (Colormap)0;
  560. }
  561. else {
  562. template.visualid = XVisualIDFromVisual (visual);
  563. pVisualInfo = XGetVisualInfo (display, VisualIDMask, &template,
  564. &notUsed);
  565. if (!pVisualInfo) {
  566. context->error = IL_ERROR_X_RESOURCE;
  567. return (ilXWC)NULL; /* EXIT */
  568. }
  569. }
  570. /* Create an XWC object and fill it in.
  571. */
  572. pXWC = (ilXWCPtr)_ilCreateObject (context, IL_XWC, ilDestroyXWC,
  573. sizeof (ilXWCRec));
  574. if (!pXWC)
  575. return (ilXWC)NULL; /* EXIT */
  576. pXWC->i.display = display;
  577. pXWC->i.visual = visual;
  578. if (visual) {
  579. pXWC->visualInfo = *pVisualInfo;
  580. free (pVisualInfo); /* free list from XGetVisualInfo() */
  581. }
  582. pXWC->i.gc = gc;
  583. pXWC->i.colormap = colormap;
  584. pXWC->pColors = (XColor *)NULL;
  585. pXWC->nColors = 0;
  586. pXWC->colorMapImage = (ilClientImage)NULL;
  587. pXWC->pGrays = (XColor *)NULL;
  588. pXWC->nGrays = 0;
  589. pXWC->grayMapImage = (ilClientImage)NULL;
  590. pXWC->i.ditherMethod = IL_AREA_DITHER;
  591. pXWC->i.rawMode = FALSE;
  592. /* Check the class of the given visual and fill in XWC des and format.
  593. If visual class not supported default to bitonal.
  594. May also default to bitonal (or color demote to gray) later if
  595. insufficient colors or grays can be allocated.
  596. If null visual, do bitonal output.
  597. */
  598. pXWC->i.staticVisual = TRUE; /* assume non-writeable colormap */
  599. if (!visual)
  600. pXWC->i.visualType = IL_XWC_BITONAL;
  601. else switch (pXWC->visualInfo.class) {
  602. case PseudoColor:
  603. pXWC->i.staticVisual = FALSE;
  604. case StaticColor:
  605. if (pXWC->visualInfo.depth == 8)
  606. pXWC->i.visualType = IL_XWC_COLOR_8;
  607. else pXWC->i.visualType = IL_XWC_BITONAL;
  608. break;
  609. /* Support True/DirectColor if 32 bits format
  610. = "<unused 8><8R><8G><8B>". */
  611. case DirectColor:
  612. pXWC->i.staticVisual = FALSE;
  613. case TrueColor:
  614. if ((pXWC->visualInfo.depth == 24)
  615. && (pXWC->visualInfo.red_mask == 0xff0000)
  616. && (pXWC->visualInfo.green_mask == 0xff00)
  617. && (pXWC->visualInfo.blue_mask == 0xff))
  618. pXWC->i.visualType = IL_XWC_COLOR_24;
  619. else pXWC->i.visualType = IL_XWC_BITONAL;
  620. break;
  621. case GrayScale:
  622. pXWC->i.staticVisual = FALSE;
  623. case StaticGray:
  624. if (pXWC->visualInfo.depth == 8)
  625. pXWC->i.visualType = IL_XWC_GRAY_8;
  626. else pXWC->i.visualType = IL_XWC_BITONAL;
  627. break;
  628. } /* END switch visual class */
  629. /* If a bitonal visual, mark as static (non-allocatable colors) */
  630. if (pXWC->i.visualType == IL_XWC_BITONAL)
  631. pXWC->i.staticVisual = TRUE;
  632. context->error = IL_OK;
  633. return (ilXWC)pXWC;
  634. }
  635. /* ======================== WRITE X DRAWABLE CODE ======================== */
  636. /* Private block for ilRead/WriteXDrawable pipe element. Notes:
  637. Inited by ilWriteXDrawable():
  638. imageDepth depth of image to create - set into pPriv when added
  639. imageFormat X format of image: XYBitmap (bitonal) or ZPixmap
  640. isLongImage if true: image is 32bits/pixel: set image rowBytes
  641. to width*4.
  642. If false: set image rowBytes to row bytes of
  643. pSrcImage.
  644. bufferSize size of buffer to create and attach to Ximage.
  645. pXWC ptr to XWC for this operation
  646. drawable id of X drawable (Window or Pixmap) to read or write
  647. x, y read: src (x,y).
  648. write: dst (x,y) from caller
  649. Inited by ilWriteXInit():
  650. Ximage a temp XImage created by Init. Its data ptr is
  651. pointed directly at the read/write buffer, or
  652. equals "pBuffer"
  653. pBuffer ptr to buffer allocated, if bufferSize > 0
  654. linesDone zeroed by Init(): # of lines written / read so far,
  655. i.e. y + linesDone is next line to read / write.
  656. */
  657. typedef struct {
  658. int imageDepth;
  659. int imageFormat;
  660. ilBool isLongImage;
  661. unsigned long bufferSize;
  662. ilXWCPtr pXWC;
  663. Drawable drawable;
  664. ilPtr pBuffer;
  665. XImage *pXImage;
  666. int x, y;
  667. long linesDone;
  668. } ilXPrivRec, *ilXPrivPtr;
  669. /* ----------------------- ilXDestroy ----------------------------- */
  670. /* Destroy() function for ilWriteXDrawable() pipe element.
  671. "Destroys" the associated XWC, whose refCount must have been
  672. incremented when the element was successfully added to the pipe -
  673. Destroy downcounts it.
  674. */
  675. static ilError ilXDestroy (
  676. ilPtr pPrivate
  677. )
  678. {
  679. ilXPrivPtr pPriv = (ilXPrivPtr)pPrivate;
  680. ilDestroyObject ((ilObject)pPriv->pXWC);
  681. return IL_OK;
  682. }
  683. /* ------------------------- ilWriteXInit ------------------------- */
  684. /* Init() function for ilWriteXDrawable() for all src image types.
  685. Creates an XImage, which is just a data structure - creates no
  686. pixel buffer.
  687. The XImage is freed by ilWriteXCleanup().
  688. */
  689. static ilError ilWriteXInit (
  690. ilPtr pPrivate,
  691. ilImageInfo *pSrcImage,
  692. ilImageInfo *pDstImage /* ignored */
  693. )
  694. {
  695. ilXPrivPtr pPriv = (ilXPrivPtr)pPrivate;
  696. ilXWCPtr pXWC;
  697. XImage *pXImage;
  698. /* Create a temp buffer for image pixels if requested. */
  699. if (pPriv->bufferSize > 0) {
  700. pPriv->pBuffer = (ilPtr)IL_MALLOC (pPriv->bufferSize);
  701. if (!pPriv->pBuffer)
  702. return IL_ERROR_MALLOC; /* EXIT */
  703. }
  704. else pPriv->pBuffer = NULL;
  705. /* Create an XImage that will be pointed to each buffer (strip) to
  706. write. */
  707. pXWC = pPriv->pXWC;
  708. pXImage = XCreateImage (pXWC->i.display, pXWC->i.visual,
  709. pPriv->imageDepth, pPriv->imageFormat, 0,
  710. (char *)pPriv->pBuffer, pSrcImage->width,
  711. pSrcImage->height, pSrcImage->pFormat->rowBitAlign,
  712. (pPriv->isLongImage) ? (pSrcImage->width * 4) :
  713. pSrcImage->plane[0].nBytesPerRow);
  714. if (!pXImage)
  715. return IL_ERROR_MALLOC; /* EXIT */
  716. /* Set bit/byte order to MSBFirst.
  717. NOTE: byte order should be set to byte order of client machine!!!
  718. */
  719. #ifdef LSB_BIT_ORDER
  720. pXImage->byte_order = LSBFirst;
  721. #else
  722. pXImage->byte_order = MSBFirst;
  723. #endif
  724. pXImage->bitmap_bit_order = MSBFirst;
  725. pPriv->pXImage = pXImage;
  726. pPriv->linesDone = 0;
  727. return IL_OK;
  728. }
  729. /* --------------------- ilWriteXCleanup -------------------------- */
  730. /* Cleanup() function for ilWriteXDrawable() for all src image types.
  731. Flushes the output if not aborted; frees the XImage created by
  732. Init() below.
  733. */
  734. static ilError ilWriteXCleanup (
  735. ilPtr pPrivate,
  736. ilBool aborting
  737. )
  738. {
  739. /* Flush if not aborting. Null the "data" field in image or else
  740. XDestroyImage() will try to free the pixels; destroy the image,
  741. created by Init().
  742. */
  743. ilXPrivPtr pPriv = (ilXPrivPtr)pPrivate;
  744. if (!aborting)
  745. XFlush (pPriv->pXWC->i.display);
  746. if (pPriv->pBuffer)
  747. IL_FREE (pPriv->pBuffer);
  748. pPriv->pXImage->data = (char *)NULL;
  749. XDestroyImage (pPriv->pXImage);
  750. return IL_OK;
  751. }
  752. /* --------------------- ilWriteXExecute ------------------------- */
  753. /* Execute() function for ilWriteXDrawable(), for rendering bit or
  754. byte data.
  755. Points an XImage created by ilWriteXInit() to the src image bits
  756. and does an XPutImage(), then bumps a line count so next strip is
  757. written *pNLines below this one in the drawable.
  758. */
  759. static ilError ilWriteXExecute (
  760. ilExecuteData *pData,
  761. long dstLine,
  762. long *pNLines,
  763. float ratio
  764. )
  765. {
  766. ilXPrivPtr pPriv;
  767. XImage *pXImage;
  768. ilXWCPtr pXWC;
  769. unsigned int nSrcLines;
  770. unsigned int scaledWidth,scaledHeight;
  771. int scaledX, scaledY;
  772. pPriv = (ilXPrivPtr)pData->pPrivate;
  773. nSrcLines = *pNLines;
  774. pXImage = pPriv->pXImage;
  775. pXImage->height = nSrcLines;
  776. pXImage->data = (char *)(pData->pSrcImage->plane[0].pPixels +
  777. pData->srcLine * pData->pSrcImage->plane[0].nBytesPerRow);
  778. pXWC = pPriv->pXWC;
  779. scaledWidth = pXImage->width * ratio + 0.5;
  780. scaledX = pPriv->x * ratio + 0.5;
  781. scaledY = (pPriv->y + pPriv->linesDone) * ratio + 0.5;
  782. /* we have to think about rounding problem, so recalculate every time. */
  783. scaledHeight = ((nSrcLines + pPriv->linesDone) * ratio + 0.5)
  784. - scaledY;
  785. _XmPutScaledImage (pXWC->i.display, pPriv->drawable,
  786. pXWC->i.gc, pXImage,
  787. 0, 0, scaledX, scaledY,
  788. pXImage->width, nSrcLines,
  789. scaledWidth,scaledHeight);
  790. pPriv->linesDone += nSrcLines;
  791. return IL_OK;
  792. }
  793. /* ------------------- ilWriteXOptLongExecute --------------------- */
  794. /* Execute() function for ilWriteXDrawable(), for display to optimal
  795. 4 bytes pixel frame buffers. "Optimal" means the 4 bytes (CARD32)
  796. = "<unused 8> <8 R> <8 G> <8 B>",
  797. which is the format most commonly used right now.
  798. Reformat the pipe image pixels, which are 3byte pixel RGB (as
  799. required by pXWC->format), into 4 bytes words and do the
  800. XPutImage(), then bump linesDone.
  801. */
  802. static ilError ilWriteXOptLongExecute (
  803. ilExecuteData *pData,
  804. long dstLine,
  805. long *pNLines,
  806. float ratio
  807. )
  808. {
  809. ilXPrivPtr pPriv;
  810. ilImageInfo *pSrcImage;
  811. XImage *pXImage;
  812. ilXWCPtr pXWC;
  813. ilPtr pSrcLine;
  814. long srcRowBytes, width, nSrcLines, nLinesM1;
  815. long nLongsM1;
  816. ilPtr pSrc;
  817. CARD32 *pDst, temp;
  818. unsigned int scaledWidth,scaledHeight;
  819. int scaledX, scaledY ;
  820. nSrcLines = *pNLines;
  821. if (nSrcLines <= 0)
  822. return 0; /* no lines, EXIT */
  823. pPriv = (ilXPrivPtr)pData->pPrivate;
  824. pSrcImage = pData->pSrcImage;
  825. width = pSrcImage->width;
  826. if (width <= 0)
  827. return 0; /* no width, EXIT */
  828. srcRowBytes = pSrcImage->plane[0].nBytesPerRow;
  829. pSrcLine = (ilPtr)(pSrcImage->plane[0].pPixels +
  830. pData->srcLine * srcRowBytes);
  831. pXImage = pPriv->pXImage;
  832. pXImage->height = nSrcLines;
  833. pXImage->data = (char *)pPriv->pBuffer;
  834. pDst = (CARD32 *)pPriv->pBuffer;
  835. /* pSrcLine points to first line of pipe image; pDst to buffer of
  836. X image.
  837. Convert 3 byte pipe image to CARD32 X buffer image. Dont need
  838. dstRowBytes because buffer is exactly "width" longs wide (we
  839. created it.)
  840. */
  841. nLinesM1 = nSrcLines - 1;
  842. do {
  843. pSrc = pSrcLine;
  844. pSrcLine += srcRowBytes;
  845. nLongsM1 = width - 1;
  846. do {
  847. temp = *pSrc++;
  848. temp <<= 8;
  849. temp |= *pSrc++;
  850. temp <<= 8;
  851. temp |= *pSrc++;
  852. *pDst++ = temp;
  853. } while (--nLongsM1 >= 0);
  854. } while (--nLinesM1 >= 0);
  855. pXWC = pPriv->pXWC;
  856. scaledWidth = pXImage->width * ratio;
  857. scaledHeight = nSrcLines * ratio;
  858. scaledX = pPriv->x * ratio ;
  859. scaledY = (pPriv->y + pPriv->linesDone)* ratio ;
  860. _XmPutScaledImage (pXWC->i.display, pPriv->drawable, pXWC->i.gc, pXImage,
  861. 0, 0, scaledX, scaledY,
  862. pXImage->width, nSrcLines,
  863. scaledWidth,scaledHeight);
  864. pPriv->linesDone += nSrcLines;
  865. return IL_OK;
  866. }
  867. /* ------------------------ ilConvertForXWrite -------------------- */
  868. /* Public function; see spec.
  869. Side effect: set pXWC->i.writeType, code for how it will render.
  870. */
  871. ilBool ilConvertForXWrite (
  872. ilPipe pipe,
  873. ilXWC XWC,
  874. ilBool mapPixels,
  875. unsigned long mustBeZero,
  876. void *mustBeNull
  877. )
  878. {
  879. ilPipeInfo info;
  880. ilImageDes des;
  881. ilImageFormat format;
  882. unsigned int writeType;
  883. ilXWCPtr pXWC;
  884. /* Table indexed by [dst visual type], yielding writeType when in raw
  885. mode */
  886. static unsigned int rawWriteMethodTable [(IL_X_MAX_VISUAL_TYPE + 1)] = {
  887. IL_XWC_WRITE_BITONAL, /* IL_XWC_BITONAL */
  888. IL_XWC_WRITE_GRAY, /* IL_XWC_GRAY_8 */
  889. IL_XWC_WRITE_COLOR_DITHER, /* IL_XWC_COLOR_8 */
  890. IL_XWC_WRITE_COLOR /* IL_XWC_COLOR_24 */ };
  891. /* Table indexed by [image type, dst visual type], yielding writeType,
  892. assuming best case: colors/grays alloc'd successfully; else writeType
  893. degrades.
  894. */
  895. static unsigned int writeTypeTable [(IL_MAX_TYPE + 1) *
  896. (IL_X_MAX_VISUAL_TYPE + 1)] =
  897. { /* (src) image type (dst) visual type writeType */
  898. /* IL_BITONAL IL_XWC_BITONAL */ IL_XWC_WRITE_BITONAL,
  899. /* IL_XWC_GRAY_8 */ IL_XWC_WRITE_BITONAL,
  900. /* IL_XWC_COLOR_8 */ IL_XWC_WRITE_BITONAL,
  901. /* IL_XWC_COLOR_24 */ IL_XWC_WRITE_BITONAL,
  902. /* IL_GRAY IL_XWC_BITONAL */ IL_XWC_WRITE_BITONAL,
  903. /* IL_XWC_GRAY_8 */ IL_XWC_WRITE_GRAY,
  904. /* IL_XWC_COLOR_8 */ IL_XWC_WRITE_GRAY,
  905. /* IL_XWC_COLOR_24 */ IL_XWC_WRITE_COLOR,
  906. /* IL_PALETTE IL_XWC_BITONAL */ IL_XWC_WRITE_BITONAL,
  907. /* IL_XWC_GRAY_8 */ IL_XWC_WRITE_GRAY,
  908. /* IL_XWC_COLOR_8 */ IL_XWC_WRITE_COLOR_DITHER,
  909. /* IL_XWC_COLOR_24 */ IL_XWC_WRITE_COLOR,
  910. /* IL_RGB IL_XWC_BITONAL */ IL_XWC_WRITE_BITONAL,
  911. /* IL_XWC_GRAY_8 */ IL_XWC_WRITE_GRAY,
  912. /* IL_XWC_COLOR_8 */ IL_XWC_WRITE_COLOR_DITHER,
  913. /* IL_XWC_COLOR_24 */ IL_XWC_WRITE_COLOR,
  914. /* IL_YCBCR IL_XWC_BITONAL */ IL_XWC_WRITE_BITONAL,
  915. /* IL_XWC_GRAY_8 */ IL_XWC_WRITE_GRAY,
  916. /* IL_XWC_COLOR_8 */ IL_XWC_WRITE_COLOR_DITHER,
  917. /* IL_XWC_COLOR_24 */ IL_XWC_WRITE_COLOR
  918. };
  919. if (pipe->objectType != IL_PIPE) {
  920. pipe->context->error = IL_ERROR_OBJECT_TYPE;
  921. return FALSE;
  922. }
  923. if (mustBeZero || mustBeNull)
  924. return ilDeclarePipeInvalid (pipe, IL_ERROR_PAR_NOT_ZERO);
  925. /* Validate that given XWC is one, and is same context as pipe. */
  926. pXWC = (ilXWCPtr)XWC;
  927. if (pXWC->o.p.objectType != IL_XWC)
  928. return ilDeclarePipeInvalid (pipe, IL_ERROR_OBJECT_TYPE);
  929. if (pXWC->o.p.context != pipe->context)
  930. return ilDeclarePipeInvalid (pipe, IL_ERROR_CONTEXT_MISMATCH);
  931. /* Get pipe info and decompress; if pipe not in IL_PIPE_FORMING state,
  932. error. */
  933. if (ilGetPipeInfo (pipe, TRUE, &info, &des, &format) != IL_PIPE_FORMING) {
  934. if (!pipe->context->error)
  935. ilDeclarePipeInvalid (pipe, IL_ERROR_PIPE_STATE);
  936. return FALSE;
  937. }
  938. /* If raw mode, allocate no colors, output based on dst visual type,
  939. except for bit/pixel images: output using bitonal approach; else:
  940. get "writeType" based on des.type (private types not supported)
  941. and pXWC->i.visualType. Check for allocated dither colors
  942. (default to gray if not enough) and grays (default to bitonal if
  943. not enough).
  944. Pretend YCbCr is RGB - an ilConvert() to RGB will be done below
  945. anyway.
  946. */
  947. if (pXWC->i.rawMode) {
  948. if ((des.nSamplesPerPixel == 1) && (format.nBitsPerSample[0] == 1))
  949. writeType = IL_XWC_WRITE_BITONAL;
  950. else writeType = rawWriteMethodTable [pXWC->i.visualType];
  951. }
  952. else {
  953. if (des.type > IL_MAX_TYPE)
  954. return ilDeclarePipeInvalid (pipe, IL_ERROR_IMAGE_TYPE);
  955. if (des.type == IL_YCBCR)
  956. des.type = IL_RGB;
  957. writeType = writeTypeTable
  958. [des.type * (IL_X_MAX_VISUAL_TYPE + 1) + pXWC->i.visualType];
  959. if (writeType == IL_XWC_WRITE_COLOR_DITHER) {
  960. if (!pXWC->colorMapImage)
  961. ilChangeXWC ((ilXWC)pXWC, IL_XWC_ALLOC_DITHER_COLORS,
  962. (ilPtr)NULL);
  963. if (!pXWC->colorMapImage)
  964. writeType = IL_XWC_WRITE_GRAY;
  965. }
  966. if (writeType == IL_XWC_WRITE_GRAY) {
  967. if (!pXWC->grayMapImage)
  968. ilChangeXWC ((ilXWC)pXWC, IL_XWC_ALLOC_GRAYS, (ilPtr)NULL);
  969. if (!pXWC->grayMapImage)
  970. writeType = IL_XWC_WRITE_BITONAL;
  971. }
  972. /* If RGB display alloc colors or dflt to bitonal. */
  973. if (writeType == IL_XWC_WRITE_COLOR) {
  974. if (!pXWC->colorMapImage)
  975. if (!ilAllocateXDirectColors (pXWC, 256))
  976. writeType = IL_XWC_WRITE_BITONAL;
  977. }
  978. } /* END not raw mode */
  979. /* Do ilConvert() and add filter(s) based on "writeType". */
  980. switch (writeType) {
  981. /* Bitonal: do an XPutImage() with XYBitmap, which renders image 0's
  982. with GC background color, 1's with foreground, as defined by IL
  983. spec.
  984. If rawMode, must be bit/pixel.
  985. */
  986. case IL_XWC_WRITE_BITONAL:
  987. if (pXWC->i.rawMode) {
  988. if ((des.nSamplesPerPixel != 1) || (format.nBitsPerSample[0] != 1))
  989. return ilDeclarePipeInvalid (pipe, IL_ERROR_RAW_MODE);
  990. }
  991. else if (!ilConvert (pipe, IL_DES_BITONAL, IL_FORMAT_BIT, 0, NULL))
  992. return FALSE;
  993. break;
  994. /* Gray: do ilMap() which maps 256 gray shades to the equivalent
  995. X pixel values, possibly using fewer shades of gray (slam; not
  996. dithered to lesser # grays).
  997. */
  998. case IL_XWC_WRITE_GRAY:
  999. if (pXWC->i.rawMode) {
  1000. if ((des.nSamplesPerPixel != 1) || (format.nBitsPerSample[0] != 8))
  1001. return ilDeclarePipeInvalid (pipe, IL_ERROR_RAW_MODE);
  1002. }
  1003. else {
  1004. if (!ilConvert (pipe, IL_DES_GRAY, IL_FORMAT_BYTE, 0, NULL))
  1005. return FALSE;
  1006. if (mapPixels)
  1007. if (!ilMap (pipe, pXWC->grayMapImage))
  1008. return FALSE;
  1009. }
  1010. break;
  1011. /* Dithered RGB: if raw mode, accept if byte/pixel;
  1012. if a pre-dithered palette image in pipe, ilMap() to map colors to
  1013. X pixels;
  1014. otherwise dither cvt to palette w/ map to the allocated colors.
  1015. */
  1016. case IL_XWC_WRITE_COLOR_DITHER:
  1017. if (pXWC->i.rawMode) {
  1018. if ((des.nSamplesPerPixel != 1) || (format.nBitsPerSample[0] != 8))
  1019. return ilDeclarePipeInvalid (pipe, IL_ERROR_RAW_MODE);
  1020. }
  1021. else if ((des.flags & IL_DITHERED_PALETTE)
  1022. && (des.typeInfo.palette.levels[0] == NRED)
  1023. && (des.typeInfo.palette.levels[1] == NGREEN)
  1024. && (des.typeInfo.palette.levels[2] == NBLUE)) {
  1025. if ((format.nBitsPerSample[0] != 8)
  1026. && !ilConvert (pipe, (ilImageDes *)NULL, IL_FORMAT_BYTE, 0,
  1027. NULL))
  1028. return FALSE;
  1029. if (mapPixels)
  1030. if (!ilMap (pipe, pXWC->colorMapImage))
  1031. return FALSE;
  1032. }
  1033. else {
  1034. ilConvertToPaletteInfo cvt;
  1035. cvt.method = pXWC->i.ditherMethod;
  1036. cvt.levels[0] = NRED;
  1037. cvt.levels[1] = NGREEN;
  1038. cvt.levels[2] = NBLUE;
  1039. cvt.kernelSize = 8;
  1040. if (mapPixels) {
  1041. cvt.dstType = IL_GRAY; /* any type other than IL_PALETTE */
  1042. cvt.mapImage = pXWC->colorMapImage;
  1043. }
  1044. else {
  1045. cvt.dstType = IL_PALETTE;
  1046. cvt.mapImage = (ilClientImage)NULL;
  1047. }
  1048. if (!ilConvert (pipe, IL_DES_PALETTE, IL_FORMAT_BYTE,
  1049. IL_CONVERT_TO_PALETTE, &cvt))
  1050. return FALSE;
  1051. }
  1052. break;
  1053. /* RGB: if raw mode, check format, else convert to RGB, and if
  1054. mapPixels and map needed (ramp not 0..255 each component) do
  1055. an ilMap().
  1056. */
  1057. case IL_XWC_WRITE_COLOR:
  1058. {
  1059. if (pXWC->i.rawMode) {
  1060. if ((des.nSamplesPerPixel != 3)
  1061. || (format.nBitsPerSample[0] != 8)
  1062. || (format.nBitsPerSample[1] != 8)
  1063. || (format.nBitsPerSample[2] != 8)
  1064. || (format.sampleOrder != IL_SAMPLE_PIXELS))
  1065. return ilDeclarePipeInvalid (pipe, IL_ERROR_RAW_MODE);
  1066. }
  1067. else {
  1068. if (!ilConvert (pipe, IL_DES_RGB, IL_FORMAT_3BYTE_PIXEL, 0, NULL))
  1069. return FALSE;
  1070. if (mapPixels && pXWC->mapDirect)
  1071. if (!ilMap (pipe, pXWC->colorMapImage))
  1072. return FALSE;
  1073. }
  1074. }
  1075. break;
  1076. } /* END switch writeType */
  1077. pXWC->i.writeType = writeType; /* set method of writing to be used */
  1078. pipe->context->error = IL_OK;
  1079. return TRUE;
  1080. }
  1081. /* ------------------------ ilWriteXDrawable ---------------------- */
  1082. /* Public function; see spec.
  1083. */
  1084. ilBool ilWriteXDrawable (
  1085. ilPipe pipe,
  1086. Drawable drawable,
  1087. ilXWC XWC,
  1088. ilRect *pSrcRect,
  1089. int dstX,
  1090. int dstY,
  1091. unsigned long mustBeZero
  1092. )
  1093. {
  1094. ilPipeInfo info;
  1095. ilXWCPtr pXWC;
  1096. ilXPrivPtr pPriv;
  1097. ilSrcElementData *pSrcData, srcData;
  1098. unsigned long bufferSize = 0;
  1099. /*
  1100. ** We need to use the execute fucntion with the ratio parameter.
  1101. */
  1102. ilError (*executeFunction)( ilExecuteData *,
  1103. long,
  1104. long *,
  1105. float);
  1106. /* If a src clip rect, insert an ilCrop() element before us.
  1107. In the future, should look at pipe and handle some cases directly.
  1108. */
  1109. if (pSrcRect && !ilCrop (pipe, pSrcRect))
  1110. return FALSE;
  1111. /* Convert as necessary, mapping pixels to X pixels and get
  1112. pXWC->i.writeType */
  1113. pXWC = (ilXWCPtr)XWC;
  1114. if (!ilConvertForXWrite (pipe, (ilXWC)pXWC, TRUE, 0, NULL))
  1115. return FALSE;
  1116. ilGetPipeInfo (pipe, FALSE, &info, (ilImageDes *)NULL,
  1117. (ilImageFormat *)NULL);
  1118. /* If writing 24 bits: use separate executeFunction, set "bufferSize"
  1119. to buffer to be allocated, and if too large force pipe to give us
  1120. smaller strips.
  1121. */
  1122. if (pXWC->i.writeType == IL_XWC_WRITE_COLOR) {
  1123. bufferSize = (info.width * 4) * info.stripHeight;
  1124. if (bufferSize > MAX_IMAGE_BUFFER_SIZE) {
  1125. srcData.consumerImage = (ilObject)NULL;
  1126. srcData.stripHeight = BEST_IMAGE_BUFFER_SIZE / (4 * info.width);
  1127. if (srcData.stripHeight < 1)
  1128. srcData.stripHeight = 1;
  1129. srcData.constantStrip = FALSE;
  1130. srcData.minBufferHeight = 0;
  1131. pSrcData = &srcData;
  1132. }
  1133. else pSrcData = (ilSrcElementData *)NULL;
  1134. executeFunction = ilWriteXOptLongExecute;
  1135. }
  1136. else {
  1137. pSrcData = (ilSrcElementData *)NULL;
  1138. executeFunction = ilWriteXExecute;
  1139. }
  1140. /* Add a consumer which does an XPutImage() using the pipe data
  1141. cvt'd above.
  1142. Increment the XWC refCount; element's Destroy() function
  1143. ilXDestroy() will decrement it when this pipe element is removed.
  1144. */
  1145. pPriv = (ilXPrivPtr)ilAddPipeElement (pipe, IL_CONSUMER,
  1146. sizeof(ilXPrivRec), 0, pSrcData, (ilDstElementData *)NULL,
  1147. ilWriteXInit, ilWriteXCleanup, ilXDestroy, NULL, executeFunction, 0);
  1148. if (!pPriv) return FALSE; /* EXIT */
  1149. pPriv->pXWC = pXWC;
  1150. pPriv->drawable = drawable;
  1151. pPriv->x = dstX;
  1152. pPriv->y = dstY;
  1153. pXWC->o.refCount++;
  1154. /* Set writeType-specific values in *pPriv */
  1155. switch (pXWC->i.writeType) {
  1156. case IL_XWC_WRITE_BITONAL:
  1157. pPriv->imageDepth = 1;
  1158. pPriv->imageFormat = XYBitmap;
  1159. pPriv->isLongImage = FALSE;
  1160. pPriv->bufferSize = 0;
  1161. break;
  1162. case IL_XWC_WRITE_GRAY:
  1163. pPriv->imageDepth = 8;
  1164. pPriv->imageFormat = ZPixmap;
  1165. pPriv->isLongImage = FALSE;
  1166. pPriv->bufferSize = 0;
  1167. break;
  1168. case IL_XWC_WRITE_COLOR_DITHER:
  1169. pPriv->imageDepth = 8;
  1170. pPriv->imageFormat = ZPixmap;
  1171. pPriv->isLongImage = FALSE;
  1172. pPriv->bufferSize = 0;
  1173. break;
  1174. case IL_XWC_WRITE_COLOR:
  1175. pPriv->bufferSize = bufferSize; /* from above */
  1176. pPriv->imageDepth = 24;
  1177. pPriv->imageFormat = ZPixmap;
  1178. pPriv->isLongImage = TRUE;
  1179. break;
  1180. }
  1181. pipe->context->error = IL_OK;
  1182. return TRUE;
  1183. }