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
28 #include "php.h"
29
30 #define MAX_XBM_LINE_SIZE 255
31
32 /* {{{ gdImagePtr gdImageCreateFromXbm */
gdImageCreateFromXbm(FILE * fd)33 gdImagePtr gdImageCreateFromXbm(FILE * fd)
34 {
35 char fline[MAX_XBM_LINE_SIZE];
36 char iname[MAX_XBM_LINE_SIZE];
37 char *type;
38 int value;
39 unsigned int width = 0, height = 0;
40 int fail = 0;
41 int max_bit = 0;
42
43 gdImagePtr im;
44 int bytes = 0, i;
45 int bit, x = 0, y = 0;
46 int ch;
47 char h[8];
48 unsigned int b;
49
50 rewind(fd);
51 while (fgets(fline, MAX_XBM_LINE_SIZE, fd)) {
52 fline[MAX_XBM_LINE_SIZE-1] = '\0';
53 if (strlen(fline) == MAX_XBM_LINE_SIZE-1) {
54 return 0;
55 }
56 if (sscanf(fline, "#define %s %d", iname, &value) == 2) {
57 if (!(type = strrchr(iname, '_'))) {
58 type = iname;
59 } else {
60 type++;
61 }
62
63 if (!strcmp("width", type)) {
64 width = (unsigned int) value;
65 }
66 if (!strcmp("height", type)) {
67 height = (unsigned int) value;
68 }
69 } else {
70 if ( sscanf(fline, "static unsigned char %s = {", iname) == 1
71 || sscanf(fline, "static char %s = {", iname) == 1)
72 {
73 max_bit = 128;
74 } else if (sscanf(fline, "static unsigned short %s = {", iname) == 1
75 || sscanf(fline, "static short %s = {", iname) == 1)
76 {
77 max_bit = 32768;
78 }
79 if (max_bit) {
80 bytes = (width + 7) / 8 * height;
81 if (!bytes) {
82 return 0;
83 }
84 if (!(type = strrchr(iname, '_'))) {
85 type = iname;
86 } else {
87 type++;
88 }
89 if (!strcmp("bits[]", type)) {
90 break;
91 }
92 }
93 }
94 }
95 if (!bytes || !max_bit) {
96 return 0;
97 }
98
99 if(!(im = gdImageCreate(width, height))) {
100 return 0;
101 }
102 gdImageColorAllocate(im, 255, 255, 255);
103 gdImageColorAllocate(im, 0, 0, 0);
104 h[2] = '\0';
105 h[4] = '\0';
106 for (i = 0; i < bytes; i++) {
107 while (1) {
108 if ((ch=getc(fd)) == EOF) {
109 fail = 1;
110 break;
111 }
112 if (ch == 'x') {
113 break;
114 }
115 }
116 if (fail) {
117 break;
118 }
119 /* Get hex value */
120 if ((ch=getc(fd)) == EOF) {
121 break;
122 }
123 h[0] = ch;
124 if ((ch=getc(fd)) == EOF) {
125 break;
126 }
127 h[1] = ch;
128 if (max_bit == 32768) {
129 if ((ch=getc(fd)) == EOF) {
130 break;
131 }
132 h[2] = ch;
133 if ((ch=getc(fd)) == EOF) {
134 break;
135 }
136 h[3] = ch;
137 }
138 if (sscanf(h, "%x", &b) != 1) {
139 php_gd_error("invalid XBM");
140 gdImageDestroy(im);
141 return 0;
142 }
143 for (bit = 1; bit <= max_bit; bit = bit << 1) {
144 gdImageSetPixel(im, x++, y, (b & bit) ? 1 : 0);
145 if (x == im->sx) {
146 x = 0;
147 y++;
148 if (y == im->sy) {
149 return im;
150 }
151 break;
152 }
153 }
154 }
155
156 php_gd_error("EOF before image was complete");
157 gdImageDestroy(im);
158 return 0;
159 }
160 /* }}} */
161
162 /* {{{ gdCtxPrintf */
gdCtxPrintf(gdIOCtx * out,const char * format,...)163 void gdCtxPrintf(gdIOCtx * out, const char *format, ...)
164 {
165 char *buf;
166 int len;
167 va_list args;
168
169 va_start(args, format);
170 len = vspprintf(&buf, 0, format, args);
171 va_end(args);
172 out->putBuf(out, buf, len);
173 efree(buf);
174 }
175 /* }}} */
176
177 /* {{{ gdImageXbmCtx */
gdImageXbmCtx(gdImagePtr image,char * file_name,int fg,gdIOCtx * out)178 void gdImageXbmCtx(gdImagePtr image, char* file_name, int fg, gdIOCtx * out)
179 {
180 int x, y, c, b, sx, sy, p;
181 char *name, *f;
182 size_t i, l;
183
184 name = file_name;
185 if ((f = strrchr(name, '/')) != NULL) name = f+1;
186 if ((f = strrchr(name, '\\')) != NULL) name = f+1;
187 name = estrdup(name);
188 if ((f = strrchr(name, '.')) != NULL && !strcasecmp(f, ".XBM")) *f = '\0';
189 if ((l = strlen(name)) == 0) {
190 efree(name);
191 name = estrdup("image");
192 } else {
193 for (i=0; i<l; i++) {
194 /* only in C-locale isalnum() would work */
195 if (!isupper(name[i]) && !islower(name[i]) && !isdigit(name[i])) {
196 name[i] = '_';
197 }
198 }
199 }
200
201 gdCtxPrintf(out, "#define %s_width %d\n", name, gdImageSX(image));
202 gdCtxPrintf(out, "#define %s_height %d\n", name, gdImageSY(image));
203 gdCtxPrintf(out, "static unsigned char %s_bits[] = {\n ", name);
204
205 efree(name);
206
207 b = 1;
208 p = 0;
209 c = 0;
210 sx = gdImageSX(image);
211 sy = gdImageSY(image);
212 for (y = 0; y < sy; y++) {
213 for (x = 0; x < sx; x++) {
214 if (gdImageGetPixel(image, x, y) == fg) {
215 c |= b;
216 }
217 if ((b == 128) || (x == sx - 1)) {
218 b = 1;
219 if (p) {
220 gdCtxPrintf(out, ", ");
221 if (!(p%12)) {
222 gdCtxPrintf(out, "\n ");
223 p = 12;
224 }
225 }
226 p++;
227 gdCtxPrintf(out, "0x%02X", c);
228 c = 0;
229 } else {
230 b <<= 1;
231 }
232 }
233 }
234 gdCtxPrintf(out, "};\n");
235 }
236 /* }}} */
237
238 /*
239 * Local variables:
240 * tab-width: 4
241 * c-basic-offset: 4
242 * End:
243 * vim600: sw=4 ts=4 fdm=marker
244 * vim<600: sw=4 ts=4
245 */
246