PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/src/CrDatFrI.c

#
C | 403 lines | 288 code | 53 blank | 62 comment | 51 complexity | 32581a330304cf42736c297e5f5f8647 MD5 | raw file
  1. /*
  2. * Copyright (C) 1989-95 GROUPE BULL
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to
  6. * deal in the Software without restriction, including without limitation the
  7. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. * sell copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  18. * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  19. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. *
  21. * Except as contained in this notice, the name of GROUPE BULL shall not be
  22. * used in advertising or otherwise to promote the sale, use or other dealings
  23. * in this Software without prior written authorization from GROUPE BULL.
  24. */
  25. /*****************************************************************************\
  26. * CrDataFI.c: *
  27. * *
  28. * XPM library *
  29. * Scan an image and possibly its mask and create an XPM array *
  30. * *
  31. * Developed by Arnaud Le Hors *
  32. \*****************************************************************************/
  33. /* October 2004, source code review by Thomas Biege <thomas@suse.de> */
  34. #ifdef HAVE_CONFIG_H
  35. #include <config.h>
  36. #endif
  37. #include "XpmI.h"
  38. LFUNC(CreateColors, int, (char **dataptr, unsigned int *data_size,
  39. XpmColor *colors, unsigned int ncolors,
  40. unsigned int cpp));
  41. LFUNC(CreatePixels, void, (char **dataptr, unsigned int data_size,
  42. unsigned int width,
  43. unsigned int height, unsigned int cpp,
  44. unsigned int *pixels, XpmColor *colors));
  45. LFUNC(CountExtensions, void, (XpmExtension *ext, unsigned int num,
  46. unsigned int *ext_size,
  47. unsigned int *ext_nlines));
  48. LFUNC(CreateExtensions, void, (char **dataptr, unsigned int data_size,
  49. unsigned int offset,
  50. XpmExtension *ext, unsigned int num,
  51. unsigned int ext_nlines));
  52. int
  53. XpmCreateDataFromImage(
  54. Display *display,
  55. char ***data_return,
  56. XImage *image,
  57. XImage *shapeimage,
  58. XpmAttributes *attributes)
  59. {
  60. XpmImage xpmimage;
  61. XpmInfo info;
  62. int ErrorStatus;
  63. /* initialize return value */
  64. if (data_return)
  65. *data_return = NULL;
  66. /* create an XpmImage from the image */
  67. ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage,
  68. &xpmimage, attributes);
  69. if (ErrorStatus != XpmSuccess)
  70. return (ErrorStatus);
  71. /* create the data from the XpmImage */
  72. if (attributes) {
  73. xpmSetInfo(&info, attributes);
  74. ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, &info);
  75. } else
  76. ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, NULL);
  77. /* free the XpmImage */
  78. XpmFreeXpmImage(&xpmimage);
  79. return (ErrorStatus);
  80. }
  81. #undef RETURN
  82. #define RETURN(status) \
  83. do \
  84. { \
  85. ErrorStatus = status; \
  86. goto exit; \
  87. } while(0)
  88. int
  89. XpmCreateDataFromXpmImage(
  90. char ***data_return,
  91. XpmImage *image,
  92. XpmInfo *info)
  93. {
  94. /* calculation variables */
  95. int ErrorStatus;
  96. char buf[BUFSIZ];
  97. char **header = NULL, **data, **sptr, **sptr2, *s;
  98. unsigned int header_size, header_nlines;
  99. unsigned int data_size, data_nlines;
  100. unsigned int extensions = 0, ext_size = 0, ext_nlines = 0;
  101. unsigned int offset, l, n;
  102. *data_return = NULL;
  103. extensions = info && (info->valuemask & XpmExtensions)
  104. && info->nextensions;
  105. /* compute the number of extensions lines and size */
  106. if (extensions)
  107. CountExtensions(info->extensions, info->nextensions,
  108. &ext_size, &ext_nlines);
  109. /*
  110. * alloc a temporary array of char pointer for the header section which
  111. * is the hints line + the color table lines
  112. */
  113. header_nlines = 1 + image->ncolors; /* this may wrap and/or become 0 */
  114. /* 2nd check superfluous if we do not need header_nlines any further */
  115. if(header_nlines <= image->ncolors ||
  116. header_nlines >= UINT_MAX / sizeof(char *))
  117. return(XpmNoMemory);
  118. header_size = sizeof(char *) * header_nlines;
  119. if (header_size >= UINT_MAX / sizeof(char *))
  120. return (XpmNoMemory);
  121. header = (char **) XpmCalloc(header_size, sizeof(char *)); /* can we trust image->ncolors */
  122. if (!header)
  123. return (XpmNoMemory);
  124. /* print the hints line */
  125. s = buf;
  126. #ifndef VOID_SPRINTF
  127. s +=
  128. #endif
  129. sprintf(s, "%d %d %d %d", image->width, image->height,
  130. image->ncolors, image->cpp);
  131. #ifdef VOID_SPRINTF
  132. s += strlen(s);
  133. #endif
  134. if (info && (info->valuemask & XpmHotspot)) {
  135. #ifndef VOID_SPRINTF
  136. s +=
  137. #endif
  138. sprintf(s, " %d %d", info->x_hotspot, info->y_hotspot);
  139. #ifdef VOID_SPRINTF
  140. s += strlen(s);
  141. #endif
  142. }
  143. if (extensions) {
  144. strcpy(s, " XPMEXT");
  145. s += 7;
  146. }
  147. l = s - buf + 1;
  148. *header = (char *) XpmMalloc(l);
  149. if (!*header)
  150. RETURN(XpmNoMemory);
  151. header_size += l;
  152. strcpy(*header, buf);
  153. /* print colors */
  154. ErrorStatus = CreateColors(header + 1, &header_size,
  155. image->colorTable, image->ncolors, image->cpp);
  156. if (ErrorStatus != XpmSuccess)
  157. RETURN(ErrorStatus);
  158. /* now we know the size needed, alloc the data and copy the header lines */
  159. offset = image->width * image->cpp + 1;
  160. if(offset <= image->width || offset <= image->cpp)
  161. RETURN(XpmNoMemory);
  162. if( (image->height + ext_nlines) >= UINT_MAX / sizeof(char *))
  163. RETURN(XpmNoMemory);
  164. data_size = (image->height + ext_nlines) * sizeof(char *);
  165. if (image->height > UINT_MAX / offset ||
  166. image->height * offset > UINT_MAX - data_size)
  167. RETURN(XpmNoMemory);
  168. data_size += image->height * offset;
  169. if( (header_size + ext_size) >= (UINT_MAX - data_size) )
  170. RETURN(XpmNoMemory);
  171. data_size += header_size + ext_size;
  172. data = (char **) XpmMalloc(data_size);
  173. if (!data)
  174. RETURN(XpmNoMemory);
  175. data_nlines = header_nlines + image->height + ext_nlines;
  176. *data = (char *) (data + data_nlines);
  177. /* can header have less elements then n suggests? */
  178. n = image->ncolors;
  179. for (l = 0, sptr = data, sptr2 = header; l <= n && sptr && sptr2; l++, sptr++, sptr2++) {
  180. strcpy(*sptr, *sptr2);
  181. *(sptr + 1) = *sptr + strlen(*sptr2) + 1;
  182. }
  183. /* print pixels */
  184. data[header_nlines] = (char *) data + header_size
  185. + (image->height + ext_nlines) * sizeof(char *);
  186. CreatePixels(data + header_nlines, data_size-header_nlines, image->width, image->height,
  187. image->cpp, image->data, image->colorTable);
  188. /* print extensions */
  189. if (extensions)
  190. CreateExtensions(data + header_nlines + image->height - 1,
  191. data_size - header_nlines - image->height + 1, offset,
  192. info->extensions, info->nextensions,
  193. ext_nlines);
  194. *data_return = data;
  195. ErrorStatus = XpmSuccess;
  196. /* exit point, free only locally allocated variables */
  197. exit:
  198. if (header) {
  199. for (l = 0; l < header_nlines; l++)
  200. if (header[l])
  201. XpmFree(header[l]);
  202. XpmFree(header);
  203. }
  204. return(ErrorStatus);
  205. }
  206. static int
  207. CreateColors(
  208. char **dataptr,
  209. unsigned int *data_size,
  210. XpmColor *colors,
  211. unsigned int ncolors,
  212. unsigned int cpp)
  213. {
  214. char buf[BUFSIZ];
  215. unsigned int a, key, l;
  216. char *s, *s2;
  217. char **defaults;
  218. /* can ncolors be trusted here? */
  219. for (a = 0; a < ncolors; a++, colors++, dataptr++) {
  220. defaults = (char **) colors;
  221. if(sizeof(buf) <= cpp)
  222. return(XpmNoMemory);
  223. strncpy(buf, *defaults++, cpp);
  224. s = buf + cpp;
  225. if(sizeof(buf) <= (s-buf))
  226. return XpmNoMemory;
  227. for (key = 1; key <= NKEYS; key++, defaults++) {
  228. if ((s2 = *defaults)) {
  229. #ifndef VOID_SPRINTF
  230. s +=
  231. #endif
  232. /* assume C99 compliance */
  233. snprintf(s, sizeof(buf)-(s-buf), "\t%s %s", xpmColorKeys[key - 1], s2);
  234. #ifdef VOID_SPRINTF
  235. s += strlen(s);
  236. #endif
  237. /* does s point out-of-bounds? */
  238. if(sizeof(buf) < (s-buf))
  239. return XpmNoMemory;
  240. }
  241. }
  242. /* what about using strdup()? */
  243. l = s - buf + 1;
  244. s = (char *) XpmMalloc(l);
  245. if (!s)
  246. return (XpmNoMemory);
  247. *data_size += l;
  248. *dataptr = strcpy(s, buf);
  249. }
  250. return (XpmSuccess);
  251. }
  252. static void
  253. CreatePixels(
  254. char **dataptr,
  255. unsigned int data_size,
  256. unsigned int width,
  257. unsigned int height,
  258. unsigned int cpp,
  259. unsigned int *pixels,
  260. XpmColor *colors)
  261. {
  262. char *s;
  263. unsigned int x, y, h, offset;
  264. if(height <= 1)
  265. return;
  266. h = height - 1;
  267. offset = width * cpp + 1;
  268. if(offset <= width || offset <= cpp)
  269. return;
  270. /* why trust h? */
  271. for (y = 0; y < h; y++, dataptr++) {
  272. s = *dataptr;
  273. /* why trust width? */
  274. for (x = 0; x < width; x++, pixels++) {
  275. if(cpp > (data_size - (s - *dataptr)))
  276. return;
  277. strncpy(s, colors[*pixels].string, cpp); /* why trust pixel? */
  278. s += cpp;
  279. }
  280. *s = '\0';
  281. if(offset > data_size)
  282. return;
  283. *(dataptr + 1) = *dataptr + offset;
  284. }
  285. /* duplicate some code to avoid a test in the loop */
  286. s = *dataptr;
  287. /* why trust width? */
  288. for (x = 0; x < width; x++, pixels++) {
  289. if(cpp > data_size - (s - *dataptr))
  290. return;
  291. strncpy(s, colors[*pixels].string, cpp); /* why should we trust *pixel? */
  292. s += cpp;
  293. }
  294. *s = '\0';
  295. }
  296. static void
  297. CountExtensions(
  298. XpmExtension *ext,
  299. unsigned int num,
  300. unsigned int *ext_size,
  301. unsigned int *ext_nlines)
  302. {
  303. unsigned int x, y, a, size, nlines;
  304. char **line;
  305. size = 0;
  306. nlines = 0;
  307. for (x = 0; x < num; x++, ext++) {
  308. /* 1 for the name */
  309. nlines += ext->nlines + 1;
  310. /* 8 = 7 (for "XPMEXT ") + 1 (for 0) */
  311. size += strlen(ext->name) + 8;
  312. a = ext->nlines;
  313. for (y = 0, line = ext->lines; y < a; y++, line++)
  314. size += strlen(*line) + 1;
  315. }
  316. /* 10 and 1 are for the ending "XPMENDEXT" */
  317. *ext_size = size + 10;
  318. *ext_nlines = nlines + 1;
  319. }
  320. static void
  321. CreateExtensions(
  322. char **dataptr,
  323. unsigned int data_size,
  324. unsigned int offset,
  325. XpmExtension *ext,
  326. unsigned int num,
  327. unsigned int ext_nlines)
  328. {
  329. unsigned int x, y, a, b;
  330. char **line;
  331. *(dataptr + 1) = *dataptr + offset;
  332. dataptr++;
  333. a = 0;
  334. for (x = 0; x < num; x++, ext++) {
  335. snprintf(*dataptr, data_size, "XPMEXT %s", ext->name);
  336. a++;
  337. if (a < ext_nlines)
  338. *(dataptr + 1) = *dataptr + strlen(ext->name) + 8;
  339. dataptr++;
  340. b = ext->nlines; /* can we trust these values? */
  341. for (y = 0, line = ext->lines; y < b; y++, line++) {
  342. strcpy(*dataptr, *line);
  343. a++;
  344. if (a < ext_nlines)
  345. *(dataptr + 1) = *dataptr + strlen(*line) + 1;
  346. dataptr++;
  347. }
  348. }
  349. strcpy(*dataptr, "XPMENDEXT");
  350. }