PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/CrBufFrI.c

#
C | 449 lines | 348 code | 44 blank | 57 comment | 41 complexity | b7d8f326922411aa594348b0bbecf313 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. * CrBufFrI.c: *
  27. * *
  28. * XPM library *
  29. * Scan an image and possibly its mask and create an XPM buffer *
  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(WriteColors, int, (char **dataptr, unsigned int *data_size,
  39. unsigned int *used_size, XpmColor *colors,
  40. unsigned int ncolors, unsigned int cpp));
  41. LFUNC(WritePixels, void, (char *dataptr, unsigned int data_size,
  42. unsigned int *used_size,
  43. unsigned int width, unsigned int height,
  44. unsigned int cpp, unsigned int *pixels,
  45. XpmColor *colors));
  46. LFUNC(WriteExtensions, void, (char *dataptr, unsigned int data_size,
  47. unsigned int *used_size,
  48. XpmExtension *ext, unsigned int num));
  49. LFUNC(ExtensionsSize, unsigned int, (XpmExtension *ext, unsigned int num));
  50. LFUNC(CommentsSize, int, (XpmInfo *info));
  51. int
  52. XpmCreateBufferFromImage(
  53. Display *display,
  54. char **buffer_return,
  55. XImage *image,
  56. XImage *shapeimage,
  57. XpmAttributes *attributes)
  58. {
  59. XpmImage xpmimage;
  60. XpmInfo info;
  61. int ErrorStatus;
  62. /* initialize return value */
  63. if (buffer_return)
  64. *buffer_return = NULL;
  65. /* create an XpmImage from the image */
  66. ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage,
  67. &xpmimage, attributes);
  68. if (ErrorStatus != XpmSuccess)
  69. return (ErrorStatus);
  70. /* create the buffer from the XpmImage */
  71. if (attributes) {
  72. xpmSetInfo(&info, attributes);
  73. ErrorStatus =
  74. XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, &info);
  75. } else
  76. ErrorStatus =
  77. XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, NULL);
  78. /* free the XpmImage */
  79. XpmFreeXpmImage(&xpmimage);
  80. return (ErrorStatus);
  81. }
  82. #undef RETURN
  83. #define RETURN(status) \
  84. do \
  85. { \
  86. ErrorStatus = status; \
  87. goto error; \
  88. }while(0)
  89. int
  90. XpmCreateBufferFromXpmImage(
  91. char **buffer_return,
  92. XpmImage *image,
  93. XpmInfo *info)
  94. {
  95. /* calculation variables */
  96. int ErrorStatus;
  97. char buf[BUFSIZ];
  98. unsigned int cmts, extensions, ext_size = 0;
  99. unsigned int l, cmt_size = 0;
  100. char *ptr = NULL, *p;
  101. unsigned int ptr_size, used_size, tmp;
  102. *buffer_return = NULL;
  103. cmts = info && (info->valuemask & XpmComments);
  104. extensions = info && (info->valuemask & XpmExtensions)
  105. && info->nextensions;
  106. /* compute the extensions and comments size */
  107. if (extensions)
  108. ext_size = ExtensionsSize(info->extensions, info->nextensions);
  109. if (cmts)
  110. cmt_size = CommentsSize(info);
  111. /* write the header line */
  112. #ifndef VOID_SPRINTF
  113. used_size =
  114. #endif
  115. sprintf(buf, "/* XPM */\nstatic char * image_name[] = {\n");
  116. #ifdef VOID_SPRINTF
  117. used_size = strlen(buf);
  118. #endif
  119. ptr_size = used_size + ext_size + cmt_size + 1; /* ptr_size can't be 0 */
  120. if(ptr_size <= used_size ||
  121. ptr_size <= ext_size ||
  122. ptr_size <= cmt_size)
  123. {
  124. return XpmNoMemory;
  125. }
  126. ptr = (char *) XpmMalloc(ptr_size);
  127. if (!ptr)
  128. return XpmNoMemory;
  129. strcpy(ptr, buf);
  130. /* write the values line */
  131. if (cmts && info->hints_cmt) {
  132. #ifndef VOID_SPRINTF
  133. used_size +=
  134. #endif
  135. snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->hints_cmt);
  136. #ifdef VOID_SPRINTF
  137. used_size += strlen(info->hints_cmt) + 5;
  138. #endif
  139. }
  140. #ifndef VOID_SPRINTF
  141. l =
  142. #endif
  143. sprintf(buf, "\"%d %d %d %d", image->width, image->height,
  144. image->ncolors, image->cpp);
  145. #ifdef VOID_SPRINTF
  146. l = strlen(buf);
  147. #endif
  148. if (info && (info->valuemask & XpmHotspot)) {
  149. #ifndef VOID_SPRINTF
  150. l +=
  151. #endif
  152. snprintf(buf + l, sizeof(buf)-l, " %d %d", info->x_hotspot, info->y_hotspot);
  153. #ifdef VOID_SPRINTF
  154. l = strlen(buf);
  155. #endif
  156. }
  157. if (extensions) {
  158. #ifndef VOID_SPRINTF
  159. l +=
  160. #endif
  161. sprintf(buf + l, " XPMEXT");
  162. #ifdef VOID_SPRINTF
  163. l = strlen(buf);
  164. #endif
  165. }
  166. #ifndef VOID_SPRINTF
  167. l +=
  168. #endif
  169. sprintf(buf + l, "\",\n");
  170. #ifdef VOID_SPRINTF
  171. l = strlen(buf);
  172. #endif
  173. ptr_size += l;
  174. if(ptr_size <= l)
  175. RETURN(XpmNoMemory);
  176. p = (char *) XpmRealloc(ptr, ptr_size);
  177. if (!p)
  178. RETURN(XpmNoMemory);
  179. ptr = p;
  180. strcpy(ptr + used_size, buf);
  181. used_size += l;
  182. /* write colors */
  183. if (cmts && info->colors_cmt) {
  184. #ifndef VOID_SPRINTF
  185. used_size +=
  186. #endif
  187. snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->colors_cmt);
  188. #ifdef VOID_SPRINTF
  189. used_size += strlen(info->colors_cmt) + 5;
  190. #endif
  191. }
  192. ErrorStatus = WriteColors(&ptr, &ptr_size, &used_size,
  193. image->colorTable, image->ncolors, image->cpp);
  194. if (ErrorStatus != XpmSuccess)
  195. RETURN(ErrorStatus);
  196. /*
  197. * now we know the exact size we need, realloc the data
  198. * 4 = 1 (for '"') + 3 (for '",\n')
  199. * 1 = - 2 (because the last line does not end with ',\n') + 3 (for '};\n')
  200. */
  201. if(image->width > UINT_MAX / image->cpp ||
  202. (tmp = image->width * image->cpp + 4) <= 4 ||
  203. image->height > UINT_MAX / tmp ||
  204. (tmp = image->height * tmp + 1) <= 1 ||
  205. (ptr_size += tmp) <= tmp)
  206. RETURN(XpmNoMemory);
  207. p = (char *) XpmRealloc(ptr, ptr_size);
  208. if (!p)
  209. RETURN(XpmNoMemory);
  210. ptr = p;
  211. /* print pixels */
  212. if (cmts && info->pixels_cmt) {
  213. #ifndef VOID_SPRINTF
  214. used_size +=
  215. #endif
  216. snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->pixels_cmt);
  217. #ifdef VOID_SPRINTF
  218. used_size += strlen(info->pixels_cmt) + 5;
  219. #endif
  220. }
  221. WritePixels(ptr + used_size, ptr_size - used_size, &used_size, image->width, image->height,
  222. image->cpp, image->data, image->colorTable);
  223. /* print extensions */
  224. if (extensions)
  225. WriteExtensions(ptr + used_size, ptr_size-used_size, &used_size,
  226. info->extensions, info->nextensions);
  227. /* close the array */
  228. strcpy(ptr + used_size, "};\n");
  229. *buffer_return = ptr;
  230. return (XpmSuccess);
  231. /* exit point in case of error, free only locally allocated variables */
  232. error:
  233. if (ptr)
  234. XpmFree(ptr);
  235. return (ErrorStatus);
  236. }
  237. static int
  238. WriteColors(
  239. char **dataptr,
  240. unsigned int *data_size,
  241. unsigned int *used_size,
  242. XpmColor *colors,
  243. unsigned int ncolors,
  244. unsigned int cpp)
  245. {
  246. char buf[BUFSIZ] = {0};
  247. unsigned int a, key, l;
  248. char *s, *s2;
  249. char **defaults;
  250. *buf = '"';
  251. for (a = 0; a < ncolors; a++, colors++) {
  252. defaults = (char **) colors;
  253. s = buf + 1;
  254. if(cpp > (sizeof(buf) - (s-buf)))
  255. return(XpmNoMemory);
  256. strncpy(s, *defaults++, cpp);
  257. s += cpp;
  258. for (key = 1; key <= NKEYS; key++, defaults++) {
  259. if ((s2 = *defaults)) {
  260. #ifndef VOID_SPRINTF
  261. s +=
  262. #endif
  263. /* assume C99 compliance */
  264. snprintf(s, sizeof(buf) - (s-buf), "\t%s %s", xpmColorKeys[key - 1], s2);
  265. #ifdef VOID_SPRINTF
  266. s += strlen(s);
  267. #endif
  268. /* now let's check if s points out-of-bounds */
  269. if((s-buf) > sizeof(buf))
  270. return(XpmNoMemory);
  271. }
  272. }
  273. if(sizeof(buf) - (s-buf) < 4)
  274. return(XpmNoMemory);
  275. strcpy(s, "\",\n");
  276. l = s + 3 - buf;
  277. if( *data_size >= UINT_MAX-l ||
  278. *data_size + l <= *used_size ||
  279. (*data_size + l - *used_size) <= sizeof(buf))
  280. return(XpmNoMemory);
  281. s = (char *) XpmRealloc(*dataptr, *data_size + l);
  282. if (!s)
  283. return (XpmNoMemory);
  284. *data_size += l;
  285. strcpy(s + *used_size, buf);
  286. *used_size += l;
  287. *dataptr = s;
  288. }
  289. return (XpmSuccess);
  290. }
  291. static void
  292. WritePixels(
  293. char *dataptr,
  294. unsigned int data_size,
  295. unsigned int *used_size,
  296. unsigned int width,
  297. unsigned int height,
  298. unsigned int cpp,
  299. unsigned int *pixels,
  300. XpmColor *colors)
  301. {
  302. char *s = dataptr;
  303. unsigned int x, y, h;
  304. if(height <= 1)
  305. return;
  306. h = height - 1;
  307. for (y = 0; y < h; y++) {
  308. *s++ = '"';
  309. for (x = 0; x < width; x++, pixels++) {
  310. if(cpp >= (data_size - (s-dataptr)))
  311. return;
  312. strncpy(s, colors[*pixels].string, cpp); /* how can we trust *pixels? :-\ */
  313. s += cpp;
  314. }
  315. if((data_size - (s-dataptr)) < 4)
  316. return;
  317. strcpy(s, "\",\n");
  318. s += 3;
  319. }
  320. /* duplicate some code to avoid a test in the loop */
  321. *s++ = '"';
  322. for (x = 0; x < width; x++, pixels++) {
  323. if(cpp >= (data_size - (s-dataptr)))
  324. return;
  325. strncpy(s, colors[*pixels].string, cpp); /* how can we trust *pixels? */
  326. s += cpp;
  327. }
  328. *s++ = '"';
  329. *used_size += s - dataptr;
  330. }
  331. static unsigned int
  332. ExtensionsSize(
  333. XpmExtension *ext,
  334. unsigned int num)
  335. {
  336. unsigned int x, y, a, size;
  337. char **line;
  338. size = 0;
  339. if(num == 0)
  340. return(0); /* ok? */
  341. for (x = 0; x < num; x++, ext++) {
  342. /* 11 = 10 (for ',\n"XPMEXT ') + 1 (for '"') */
  343. size += strlen(ext->name) + 11;
  344. a = ext->nlines; /* how can we trust ext->nlines to be not out-of-bounds? */
  345. for (y = 0, line = ext->lines; y < a; y++, line++)
  346. /* 4 = 3 (for ',\n"') + 1 (for '"') */
  347. size += strlen(*line) + 4;
  348. }
  349. /* 13 is for ',\n"XPMENDEXT"' */
  350. if(size > UINT_MAX - 13) /* unlikely */
  351. return(0);
  352. return size + 13;
  353. }
  354. static void
  355. WriteExtensions(
  356. char *dataptr,
  357. unsigned int data_size,
  358. unsigned int *used_size,
  359. XpmExtension *ext,
  360. unsigned int num)
  361. {
  362. unsigned int x, y, a;
  363. char **line;
  364. char *s = dataptr;
  365. for (x = 0; x < num; x++, ext++) {
  366. #ifndef VOID_SPRINTF
  367. s +=
  368. #endif
  369. snprintf(s, data_size - (s-dataptr), ",\n\"XPMEXT %s\"", ext->name);
  370. #ifdef VOID_SPRINTF
  371. s += strlen(ext->name) + 11;
  372. #endif
  373. a = ext->nlines;
  374. for (y = 0, line = ext->lines; y < a; y++, line++) {
  375. #ifndef VOID_SPRINTF
  376. s +=
  377. #endif
  378. snprintf(s, data_size - (s-dataptr), ",\n\"%s\"", *line);
  379. #ifdef VOID_SPRINTF
  380. s += strlen(*line) + 4;
  381. #endif
  382. }
  383. }
  384. strncpy(s, ",\n\"XPMENDEXT\"", data_size - (s-dataptr)-1);
  385. *used_size += s - dataptr + 13;
  386. }
  387. static int
  388. CommentsSize(XpmInfo *info)
  389. {
  390. int size = 0;
  391. /* 5 = 2 (for "/_*") + 3 (for "*_/\n") */
  392. /* wrap possible but *very* unlikely */
  393. if (info->hints_cmt)
  394. size += 5 + strlen(info->hints_cmt);
  395. if (info->colors_cmt)
  396. size += 5 + strlen(info->colors_cmt);
  397. if (info->pixels_cmt)
  398. size += 5 + strlen(info->pixels_cmt);
  399. return size;
  400. }