~ubuntu-branches/ubuntu/quantal/libxpm/quantal

« back to all changes in this revision

Viewing changes to src/CrDatFrI.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Stone
  • Date: 2005-07-23 01:33:31 UTC
  • Revision ID: james.westby@ubuntu.com-20050723013331-3azqgwnbdc7sjosd
Tags: upstream-3.5.2
ImportĀ upstreamĀ versionĀ 3.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
*  CrDataFI.c:                                                                *
 
28
*                                                                             *
 
29
*  XPM library                                                                *
 
30
*  Scan an image and possibly its mask and create an XPM array                *
 
31
*                                                                             *
 
32
*  Developed by Arnaud Le Hors                                                *
 
33
\*****************************************************************************/
 
34
/* $XFree86$ */
 
35
 
 
36
/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
 
37
 
 
38
#ifdef HAVE_CONFIG_H
 
39
#include <config.h>
 
40
#endif
 
41
#include "XpmI.h"
 
42
 
 
43
LFUNC(CreateColors, int, (char **dataptr, unsigned int *data_size,
 
44
                          XpmColor *colors, unsigned int ncolors,
 
45
                          unsigned int cpp));
 
46
 
 
47
LFUNC(CreatePixels, void, (char **dataptr, unsigned int data_size,
 
48
                           unsigned int width,
 
49
                           unsigned int height, unsigned int cpp,
 
50
                           unsigned int *pixels, XpmColor *colors));
 
51
 
 
52
LFUNC(CountExtensions, void, (XpmExtension *ext, unsigned int num,
 
53
                              unsigned int *ext_size,
 
54
                              unsigned int *ext_nlines));
 
55
 
 
56
LFUNC(CreateExtensions, void, (char **dataptr, unsigned int data_size,
 
57
                               unsigned int offset,
 
58
                               XpmExtension *ext, unsigned int num,
 
59
                               unsigned int ext_nlines));
 
60
 
 
61
int
 
62
XpmCreateDataFromImage(display, data_return, image, shapeimage, attributes)
 
63
    Display *display;
 
64
    char ***data_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 (data_return)
 
75
        *data_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 data from the XpmImage */
 
84
    if (attributes) {
 
85
        xpmSetInfo(&info, attributes);
 
86
        ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, &info);
 
87
    } else
 
88
        ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, NULL);
 
89
 
 
90
    /* free the XpmImage */
 
91
    XpmFreeXpmImage(&xpmimage);
 
92
 
 
93
    return (ErrorStatus);
 
94
}
 
95
 
 
96
#undef RETURN
 
97
#define RETURN(status) \
 
98
do \
 
99
{ \
 
100
      ErrorStatus = status; \
 
101
      goto exit; \
 
102
} while(0)
 
103
 
 
104
int
 
105
XpmCreateDataFromXpmImage(data_return, image, info)
 
106
    char ***data_return;
 
107
    XpmImage *image;
 
108
    XpmInfo *info;
 
109
{
 
110
    /* calculation variables */
 
111
    int ErrorStatus;
 
112
    char buf[BUFSIZ];
 
113
    char **header = NULL, **data, **sptr, **sptr2, *s;
 
114
    unsigned int header_size, header_nlines;
 
115
    unsigned int data_size, data_nlines;
 
116
    unsigned int extensions = 0, ext_size = 0, ext_nlines = 0;
 
117
    unsigned int offset, l, n;
 
118
 
 
119
    *data_return = NULL;
 
120
 
 
121
    extensions = info && (info->valuemask & XpmExtensions)
 
122
        && info->nextensions;
 
123
 
 
124
    /* compute the number of extensions lines and size */
 
125
    if (extensions)
 
126
        CountExtensions(info->extensions, info->nextensions,
 
127
                        &ext_size, &ext_nlines);
 
128
 
 
129
    /*
 
130
     * alloc a temporary array of char pointer for the header section which
 
131
     * is the hints line + the color table lines
 
132
     */
 
133
    header_nlines = 1 + image->ncolors; /* this may wrap and/or become 0 */
 
134
 
 
135
    /* 2nd check superfluous if we do not need header_nlines any further */
 
136
    if(header_nlines <= image->ncolors ||
 
137
       header_nlines >= UINT_MAX / sizeof(char *))
 
138
        return(XpmNoMemory);
 
139
 
 
140
    header_size = sizeof(char *) * header_nlines;
 
141
    if (header_size >= UINT_MAX / sizeof(char *))
 
142
        return (XpmNoMemory);
 
143
    header = (char **) XpmCalloc(header_size, sizeof(char *)); /* can we trust image->ncolors */
 
144
    if (!header)
 
145
        return (XpmNoMemory);
 
146
 
 
147
    /* print the hints line */
 
148
    s = buf;
 
149
#ifndef VOID_SPRINTF
 
150
    s +=
 
151
#endif
 
152
    sprintf(s, "%d %d %d %d", image->width, image->height,
 
153
            image->ncolors, image->cpp);
 
154
#ifdef VOID_SPRINTF
 
155
    s += strlen(s);
 
156
#endif
 
157
 
 
158
    if (info && (info->valuemask & XpmHotspot)) {
 
159
#ifndef VOID_SPRINTF
 
160
        s +=
 
161
#endif
 
162
        sprintf(s, " %d %d", info->x_hotspot, info->y_hotspot);
 
163
#ifdef VOID_SPRINTF
 
164
        s += strlen(s);
 
165
#endif
 
166
    }
 
167
    if (extensions) {
 
168
        strcpy(s, " XPMEXT");
 
169
        s += 7;
 
170
    }
 
171
    l = s - buf + 1;
 
172
    *header = (char *) XpmMalloc(l);
 
173
    if (!*header)
 
174
        RETURN(XpmNoMemory);
 
175
    header_size += l;
 
176
    strcpy(*header, buf);
 
177
 
 
178
    /* print colors */
 
179
    ErrorStatus = CreateColors(header + 1, &header_size,
 
180
                               image->colorTable, image->ncolors, image->cpp);
 
181
 
 
182
    if (ErrorStatus != XpmSuccess)
 
183
        RETURN(ErrorStatus);
 
184
 
 
185
    /* now we know the size needed, alloc the data and copy the header lines */
 
186
    offset = image->width * image->cpp + 1;
 
187
 
 
188
    if(offset <= image->width || offset <= image->cpp)
 
189
        RETURN(XpmNoMemory);
 
190
 
 
191
    if( (image->height + ext_nlines) >= UINT_MAX / sizeof(char *))
 
192
        RETURN(XpmNoMemory);
 
193
    data_size = (image->height + ext_nlines) * sizeof(char *);
 
194
 
 
195
    if (image->height > UINT_MAX / offset ||
 
196
        image->height * offset > UINT_MAX - data_size)
 
197
        RETURN(XpmNoMemory);
 
198
    data_size += image->height * offset;
 
199
 
 
200
    if( (header_size + ext_size) >= (UINT_MAX - data_size) )
 
201
        RETURN(XpmNoMemory);
 
202
    data_size += header_size + ext_size;
 
203
 
 
204
    data = (char **) XpmMalloc(data_size);
 
205
    if (!data)
 
206
        RETURN(XpmNoMemory);
 
207
 
 
208
    data_nlines = header_nlines + image->height + ext_nlines;
 
209
    *data = (char *) (data + data_nlines);
 
210
 
 
211
    /* can header have less elements then n suggests? */
 
212
    n = image->ncolors;
 
213
    for (l = 0, sptr = data, sptr2 = header; l <= n && sptr && sptr2; l++, sptr++, sptr2++) {
 
214
        strcpy(*sptr, *sptr2);
 
215
        *(sptr + 1) = *sptr + strlen(*sptr2) + 1;
 
216
    }
 
217
 
 
218
    /* print pixels */
 
219
    data[header_nlines] = (char *) data + header_size
 
220
        + (image->height + ext_nlines) * sizeof(char *);
 
221
 
 
222
    CreatePixels(data + header_nlines, data_size-header_nlines, image->width, image->height,
 
223
                 image->cpp, image->data, image->colorTable);
 
224
 
 
225
    /* print extensions */
 
226
    if (extensions)
 
227
        CreateExtensions(data + header_nlines + image->height - 1,
 
228
                         data_size - header_nlines - image->height + 1, offset,
 
229
                         info->extensions, info->nextensions,
 
230
                         ext_nlines);
 
231
 
 
232
    *data_return = data;
 
233
    ErrorStatus = XpmSuccess;
 
234
 
 
235
/* exit point, free only locally allocated variables */
 
236
exit:
 
237
    if (header) {
 
238
        for (l = 0; l < header_nlines; l++)
 
239
            if (header[l])
 
240
                XpmFree(header[l]);
 
241
                XpmFree(header);
 
242
    }
 
243
    return(ErrorStatus);
 
244
}
 
245
 
 
246
static int
 
247
CreateColors(dataptr, data_size, colors, ncolors, cpp)
 
248
    char **dataptr;
 
249
    unsigned int *data_size;
 
250
    XpmColor *colors;
 
251
    unsigned int ncolors;
 
252
    unsigned int cpp;
 
253
{
 
254
    char buf[BUFSIZ];
 
255
    unsigned int a, key, l;
 
256
    char *s, *s2;
 
257
    char **defaults;
 
258
 
 
259
    /* can ncolors be trusted here? */
 
260
    for (a = 0; a < ncolors; a++, colors++, dataptr++) {
 
261
 
 
262
        defaults = (char **) colors;
 
263
        if(sizeof(buf) <= cpp)
 
264
            return(XpmNoMemory);
 
265
        strncpy(buf, *defaults++, cpp);
 
266
        s = buf + cpp;
 
267
 
 
268
        if(sizeof(buf) <= (s-buf))
 
269
                return XpmNoMemory;
 
270
 
 
271
        for (key = 1; key <= NKEYS; key++, defaults++) {
 
272
            if ((s2 = *defaults)) {
 
273
#ifndef VOID_SPRINTF
 
274
                s +=
 
275
#endif
 
276
                /* assume C99 compliance */
 
277
                        snprintf(s, sizeof(buf)-(s-buf), "\t%s %s", xpmColorKeys[key - 1], s2);
 
278
#ifdef VOID_SPRINTF
 
279
                s += strlen(s);
 
280
#endif
 
281
                /* does s point out-of-bounds? */
 
282
                if(sizeof(buf) < (s-buf))
 
283
                        return XpmNoMemory;
 
284
            }
 
285
        }
 
286
        /* what about using strdup()? */
 
287
        l = s - buf + 1;
 
288
        s = (char *) XpmMalloc(l);
 
289
        if (!s)
 
290
            return (XpmNoMemory);
 
291
        *data_size += l;
 
292
        *dataptr = strcpy(s, buf);
 
293
    }
 
294
    return (XpmSuccess);
 
295
}
 
296
 
 
297
static void
 
298
CreatePixels(dataptr, data_size, width, height, cpp, pixels, colors)
 
299
    char **dataptr;
 
300
    unsigned int data_size;
 
301
    unsigned int width;
 
302
    unsigned int height;
 
303
    unsigned int cpp;
 
304
    unsigned int *pixels;
 
305
    XpmColor *colors;
 
306
{
 
307
    char *s;
 
308
    unsigned int x, y, h, offset;
 
309
 
 
310
    if(height <= 1)
 
311
        return;
 
312
 
 
313
    h = height - 1;
 
314
 
 
315
    offset = width * cpp + 1;
 
316
 
 
317
    if(offset <= width || offset <= cpp)
 
318
        return;
 
319
 
 
320
    /* why trust h? */
 
321
    for (y = 0; y < h; y++, dataptr++) {
 
322
        s = *dataptr;
 
323
        /* why trust width? */
 
324
        for (x = 0; x < width; x++, pixels++) {
 
325
            if(cpp > (data_size - (s - *dataptr)))
 
326
                return;
 
327
            strncpy(s, colors[*pixels].string, cpp); /* why trust pixel? */
 
328
            s += cpp;
 
329
        }
 
330
        *s = '\0';
 
331
        if(offset > data_size)
 
332
                return;
 
333
        *(dataptr + 1) = *dataptr + offset;
 
334
    }
 
335
    /* duplicate some code to avoid a test in the loop */
 
336
    s = *dataptr;
 
337
    /* why trust width? */
 
338
    for (x = 0; x < width; x++, pixels++) {
 
339
        if(cpp > data_size - (s - *dataptr))
 
340
                return;
 
341
        strncpy(s, colors[*pixels].string, cpp); /* why should we trust *pixel? */
 
342
        s += cpp;
 
343
    }
 
344
    *s = '\0';
 
345
}
 
346
 
 
347
static void
 
348
CountExtensions(ext, num, ext_size, ext_nlines)
 
349
    XpmExtension *ext;
 
350
    unsigned int num;
 
351
    unsigned int *ext_size;
 
352
    unsigned int *ext_nlines;
 
353
{
 
354
    unsigned int x, y, a, size, nlines;
 
355
    char **line;
 
356
 
 
357
    size = 0;
 
358
    nlines = 0;
 
359
    for (x = 0; x < num; x++, ext++) {
 
360
        /* 1 for the name */
 
361
        nlines += ext->nlines + 1;
 
362
        /* 8 = 7 (for "XPMEXT ") + 1 (for 0) */
 
363
        size += strlen(ext->name) + 8;
 
364
        a = ext->nlines;
 
365
        for (y = 0, line = ext->lines; y < a; y++, line++)
 
366
            size += strlen(*line) + 1;
 
367
    }
 
368
    /* 10 and 1 are for the ending "XPMENDEXT" */
 
369
    *ext_size = size + 10;
 
370
    *ext_nlines = nlines + 1;
 
371
}
 
372
 
 
373
static void
 
374
CreateExtensions(dataptr, data_size, offset, ext, num, ext_nlines)
 
375
    char **dataptr;
 
376
    unsigned int data_size;
 
377
    unsigned int offset;
 
378
    XpmExtension *ext;
 
379
    unsigned int num;
 
380
    unsigned int ext_nlines;
 
381
{
 
382
    unsigned int x, y, a, b;
 
383
    char **line;
 
384
 
 
385
    *(dataptr + 1) = *dataptr + offset;
 
386
    dataptr++;
 
387
    a = 0;
 
388
    for (x = 0; x < num; x++, ext++) {
 
389
        snprintf(*dataptr, data_size, "XPMEXT %s", ext->name);
 
390
        a++;
 
391
        if (a < ext_nlines)
 
392
            *(dataptr + 1) = *dataptr + strlen(ext->name) + 8;
 
393
        dataptr++;
 
394
        b = ext->nlines; /* can we trust these values? */
 
395
        for (y = 0, line = ext->lines; y < b; y++, line++) {
 
396
            strcpy(*dataptr, *line);
 
397
            a++;
 
398
            if (a < ext_nlines)
 
399
                *(dataptr + 1) = *dataptr + strlen(*line) + 1;
 
400
            dataptr++;
 
401
        }
 
402
    }
 
403
    strcpy(*dataptr, "XPMENDEXT");
 
404
}