xref: /PHP-7.0/ext/gd/libgd/xbm.c (revision f67d599a)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2017 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 		sscanf(h, "%x", &b);
139 		for (bit = 1; bit <= max_bit; bit = bit << 1) {
140 			gdImageSetPixel(im, x++, y, (b & bit) ? 1 : 0);
141 			if (x == im->sx) {
142 				x = 0;
143 				y++;
144 				if (y == im->sy) {
145 					return im;
146 				}
147 				break;
148 			}
149 		}
150 	}
151 
152 	php_gd_error("EOF before image was complete");
153 	gdImageDestroy(im);
154 	return 0;
155 }
156 /* }}} */
157 
158 /* {{{ gdCtxPrintf */
gdCtxPrintf(gdIOCtx * out,const char * format,...)159 void gdCtxPrintf(gdIOCtx * out, const char *format, ...)
160 {
161 	char *buf;
162 	int len;
163 	va_list args;
164 
165 	va_start(args, format);
166 	len = vspprintf(&buf, 0, format, args);
167 	va_end(args);
168 	out->putBuf(out, buf, len);
169 	efree(buf);
170 }
171 /* }}} */
172 
173 /* {{{ gdImageXbmCtx */
gdImageXbmCtx(gdImagePtr image,char * file_name,int fg,gdIOCtx * out)174 void gdImageXbmCtx(gdImagePtr image, char* file_name, int fg, gdIOCtx * out)
175 {
176 	int x, y, c, b, sx, sy, p;
177 	char *name, *f;
178 	size_t i, l;
179 
180 	name = file_name;
181 	if ((f = strrchr(name, '/')) != NULL) name = f+1;
182 	if ((f = strrchr(name, '\\')) != NULL) name = f+1;
183 	name = estrdup(name);
184 	if ((f = strrchr(name, '.')) != NULL && !strcasecmp(f, ".XBM")) *f = '\0';
185 	if ((l = strlen(name)) == 0) {
186 		efree(name);
187 		name = estrdup("image");
188 	} else {
189 		for (i=0; i<l; i++) {
190 			/* only in C-locale isalnum() would work */
191 			if (!isupper(name[i]) && !islower(name[i]) && !isdigit(name[i])) {
192 				name[i] = '_';
193 			}
194 		}
195 	}
196 
197 	gdCtxPrintf(out, "#define %s_width %d\n", name, gdImageSX(image));
198 	gdCtxPrintf(out, "#define %s_height %d\n", name, gdImageSY(image));
199 	gdCtxPrintf(out, "static unsigned char %s_bits[] = {\n  ", name);
200 
201 	efree(name);
202 
203 	b = 1;
204 	p = 0;
205 	c = 0;
206 	sx = gdImageSX(image);
207 	sy = gdImageSY(image);
208 	for (y = 0; y < sy; y++) {
209 		for (x = 0; x < sx; x++) {
210 			if (gdImageGetPixel(image, x, y) == fg) {
211 				c |= b;
212 			}
213 			if ((b == 128) || (x == sx - 1)) {
214 				b = 1;
215 				if (p) {
216 					gdCtxPrintf(out, ", ");
217 					if (!(p%12)) {
218 						gdCtxPrintf(out, "\n  ");
219 						p = 12;
220 					}
221 				}
222 				p++;
223 				gdCtxPrintf(out, "0x%02X", c);
224 				c = 0;
225 			} else {
226 				b <<= 1;
227 			}
228 		}
229 	}
230 	gdCtxPrintf(out, "};\n");
231 }
232 /* }}} */
233 
234 /*
235  * Local variables:
236  * tab-width: 4
237  * c-basic-offset: 4
238  * End:
239  * vim600: sw=4 ts=4 fdm=marker
240  * vim<600: sw=4 ts=4
241  */
242