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