1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Marcus Boerger <helly@php.net> |
14 +----------------------------------------------------------------------+
15 */
16
17 /* $Id$ */
18
19 #include <stdio.h>
20 #include <math.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include "gd.h"
24 #include "gdhelpers.h"
25 #include "gd_errors.h"
26
27 #include "php.h"
28
29 #define MAX_XBM_LINE_SIZE 255
30
31 /* {{{ gdImagePtr gdImageCreateFromXbm */
gdImageCreateFromXbm(FILE * fd)32 gdImagePtr gdImageCreateFromXbm(FILE * fd)
33 {
34 char fline[MAX_XBM_LINE_SIZE];
35 char iname[MAX_XBM_LINE_SIZE];
36 char *type;
37 int value;
38 unsigned int width = 0, height = 0;
39 int fail = 0;
40 int max_bit = 0;
41
42 gdImagePtr im;
43 int bytes = 0, i;
44 int bit, x = 0, y = 0;
45 int ch;
46 char h[8];
47 unsigned int b;
48
49 rewind(fd);
50 while (fgets(fline, MAX_XBM_LINE_SIZE, fd)) {
51 fline[MAX_XBM_LINE_SIZE-1] = '\0';
52 if (strlen(fline) == MAX_XBM_LINE_SIZE-1) {
53 return 0;
54 }
55 if (sscanf(fline, "#define %s %d", iname, &value) == 2) {
56 if (!(type = strrchr(iname, '_'))) {
57 type = iname;
58 } else {
59 type++;
60 }
61
62 if (!strcmp("width", type)) {
63 width = (unsigned int) value;
64 }
65 if (!strcmp("height", type)) {
66 height = (unsigned int) value;
67 }
68 } else {
69 if ( sscanf(fline, "static unsigned char %s = {", iname) == 1
70 || sscanf(fline, "static char %s = {", iname) == 1)
71 {
72 max_bit = 128;
73 } else if (sscanf(fline, "static unsigned short %s = {", iname) == 1
74 || sscanf(fline, "static short %s = {", iname) == 1)
75 {
76 max_bit = 32768;
77 }
78 if (max_bit) {
79 bytes = (width + 7) / 8 * height;
80 if (!bytes) {
81 return 0;
82 }
83 if (!(type = strrchr(iname, '_'))) {
84 type = iname;
85 } else {
86 type++;
87 }
88 if (!strcmp("bits[]", type)) {
89 break;
90 }
91 }
92 }
93 }
94 if (!bytes || !max_bit) {
95 return 0;
96 }
97
98 if(!(im = gdImageCreate(width, height))) {
99 return 0;
100 }
101 gdImageColorAllocate(im, 255, 255, 255);
102 gdImageColorAllocate(im, 0, 0, 0);
103 h[2] = '\0';
104 h[4] = '\0';
105 for (i = 0; i < bytes; i++) {
106 while (1) {
107 if ((ch=getc(fd)) == EOF) {
108 fail = 1;
109 break;
110 }
111 if (ch == 'x') {
112 break;
113 }
114 }
115 if (fail) {
116 break;
117 }
118 /* Get hex value */
119 if ((ch=getc(fd)) == EOF) {
120 break;
121 }
122 h[0] = ch;
123 if ((ch=getc(fd)) == EOF) {
124 break;
125 }
126 h[1] = ch;
127 if (max_bit == 32768) {
128 if ((ch=getc(fd)) == EOF) {
129 break;
130 }
131 h[2] = ch;
132 if ((ch=getc(fd)) == EOF) {
133 break;
134 }
135 h[3] = ch;
136 }
137 if (sscanf(h, "%x", &b) != 1) {
138 gd_error("Invalid XBM");
139 gdImageDestroy(im);
140 return 0;
141 }
142 for (bit = 1; bit <= max_bit; bit = bit << 1) {
143 gdImageSetPixel(im, x++, y, (b & bit) ? 1 : 0);
144 if (x == im->sx) {
145 x = 0;
146 y++;
147 if (y == im->sy) {
148 return im;
149 }
150 break;
151 }
152 }
153 }
154
155 gd_error("EOF before image was complete");
156 gdImageDestroy(im);
157 return 0;
158 }
159 /* }}} */
160
161 /* {{{ gdCtxPrintf */
gdCtxPrintf(gdIOCtx * out,const char * format,...)162 void gdCtxPrintf(gdIOCtx * out, const char *format, ...)
163 {
164 char *buf;
165 int len;
166 va_list args;
167
168 va_start(args, format);
169 len = vspprintf(&buf, 0, format, args);
170 va_end(args);
171 out->putBuf(out, buf, len);
172 efree(buf);
173 }
174 /* }}} */
175
176 /* {{{ gdImageXbmCtx */
gdImageXbmCtx(gdImagePtr image,char * file_name,int fg,gdIOCtx * out)177 void gdImageXbmCtx(gdImagePtr image, char* file_name, int fg, gdIOCtx * out)
178 {
179 int x, y, c, b, sx, sy, p;
180 char *name, *f;
181 size_t i, l;
182
183 name = file_name;
184 if ((f = strrchr(name, '/')) != NULL) name = f+1;
185 if ((f = strrchr(name, '\\')) != NULL) name = f+1;
186 name = estrdup(name);
187 if ((f = strrchr(name, '.')) != NULL && !strcasecmp(f, ".XBM")) *f = '\0';
188 if ((l = strlen(name)) == 0) {
189 efree(name);
190 name = estrdup("image");
191 } else {
192 for (i=0; i<l; i++) {
193 /* only in C-locale isalnum() would work */
194 if (!isupper(name[i]) && !islower(name[i]) && !isdigit(name[i])) {
195 name[i] = '_';
196 }
197 }
198 }
199
200 gdCtxPrintf(out, "#define %s_width %d\n", name, gdImageSX(image));
201 gdCtxPrintf(out, "#define %s_height %d\n", name, gdImageSY(image));
202 gdCtxPrintf(out, "static unsigned char %s_bits[] = {\n ", name);
203
204 efree(name);
205
206 b = 1;
207 p = 0;
208 c = 0;
209 sx = gdImageSX(image);
210 sy = gdImageSY(image);
211 for (y = 0; y < sy; y++) {
212 for (x = 0; x < sx; x++) {
213 if (gdImageGetPixel(image, x, y) == fg) {
214 c |= b;
215 }
216 if ((b == 128) || (x == sx - 1)) {
217 b = 1;
218 if (p) {
219 gdCtxPrintf(out, ", ");
220 if (!(p%12)) {
221 gdCtxPrintf(out, "\n ");
222 p = 12;
223 }
224 }
225 p++;
226 gdCtxPrintf(out, "0x%02X", c);
227 c = 0;
228 } else {
229 b <<= 1;
230 }
231 }
232 }
233 gdCtxPrintf(out, "};\n");
234 }
235 /* }}} */
236