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