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