xref: /PHP-7.3/ext/gd/libgd/gd_xbm.c (revision 9bca9ef6)
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