xref: /aosp_15_r20/external/wayland/cursor/convert_font.c (revision 84e872a0dc482bffdb63672969dd03a827d67c73)
1*84e872a0SLloyd Pique /*
2*84e872a0SLloyd Pique  * Copyright © 2012 Philipp Brüschweiler
3*84e872a0SLloyd Pique  *
4*84e872a0SLloyd Pique  * Permission is hereby granted, free of charge, to any person obtaining
5*84e872a0SLloyd Pique  * a copy of this software and associated documentation files (the
6*84e872a0SLloyd Pique  * "Software"), to deal in the Software without restriction, including
7*84e872a0SLloyd Pique  * without limitation the rights to use, copy, modify, merge, publish,
8*84e872a0SLloyd Pique  * distribute, sublicense, and/or sell copies of the Software, and to
9*84e872a0SLloyd Pique  * permit persons to whom the Software is furnished to do so, subject to
10*84e872a0SLloyd Pique  * the following conditions:
11*84e872a0SLloyd Pique  *
12*84e872a0SLloyd Pique  * The above copyright notice and this permission notice (including the
13*84e872a0SLloyd Pique  * next paragraph) shall be included in all copies or substantial
14*84e872a0SLloyd Pique  * portions of the Software.
15*84e872a0SLloyd Pique  *
16*84e872a0SLloyd Pique  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17*84e872a0SLloyd Pique  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*84e872a0SLloyd Pique  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19*84e872a0SLloyd Pique  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20*84e872a0SLloyd Pique  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21*84e872a0SLloyd Pique  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22*84e872a0SLloyd Pique  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23*84e872a0SLloyd Pique  * SOFTWARE.
24*84e872a0SLloyd Pique  */
25*84e872a0SLloyd Pique 
26*84e872a0SLloyd Pique /*
27*84e872a0SLloyd Pique  * This is a small, hacky tool to extract cursors from a .pcf file.
28*84e872a0SLloyd Pique  * The information about the file format has been gathered from
29*84e872a0SLloyd Pique  * http://fontforge.org/pcf-format.html
30*84e872a0SLloyd Pique  */
31*84e872a0SLloyd Pique 
32*84e872a0SLloyd Pique #include <assert.h>
33*84e872a0SLloyd Pique #include <fcntl.h>
34*84e872a0SLloyd Pique #include <stdint.h>
35*84e872a0SLloyd Pique #include <stdio.h>
36*84e872a0SLloyd Pique #include <stdlib.h>
37*84e872a0SLloyd Pique #include <string.h>
38*84e872a0SLloyd Pique #include <sys/mman.h>
39*84e872a0SLloyd Pique #include <sys/types.h>
40*84e872a0SLloyd Pique #include <sys/stat.h>
41*84e872a0SLloyd Pique 
42*84e872a0SLloyd Pique #define min(a, b) ((a) < (b) ? (a) : (b))
43*84e872a0SLloyd Pique #define max(a, b) ((a) > (b) ? (a) : (b))
44*84e872a0SLloyd Pique 
45*84e872a0SLloyd Pique struct glyph {
46*84e872a0SLloyd Pique 	char *name;
47*84e872a0SLloyd Pique 	int16_t left_bearing, right_bearing, ascent, descent;
48*84e872a0SLloyd Pique 
49*84e872a0SLloyd Pique 	int16_t width, height;
50*84e872a0SLloyd Pique 	int16_t hotx, hoty;
51*84e872a0SLloyd Pique 
52*84e872a0SLloyd Pique 	int32_t data_format;
53*84e872a0SLloyd Pique 	char *data;
54*84e872a0SLloyd Pique };
55*84e872a0SLloyd Pique 
56*84e872a0SLloyd Pique static struct {
57*84e872a0SLloyd Pique 	int count;
58*84e872a0SLloyd Pique 	struct glyph *glyphs;
59*84e872a0SLloyd Pique } extracted_font = {0, NULL};
60*84e872a0SLloyd Pique 
61*84e872a0SLloyd Pique #define PCF_PROPERTIES		    (1<<0)
62*84e872a0SLloyd Pique #define PCF_ACCELERATORS	    (1<<1)
63*84e872a0SLloyd Pique #define PCF_METRICS		    (1<<2)
64*84e872a0SLloyd Pique #define PCF_BITMAPS		    (1<<3)
65*84e872a0SLloyd Pique #define PCF_INK_METRICS		    (1<<4)
66*84e872a0SLloyd Pique #define	PCF_BDF_ENCODINGS	    (1<<5)
67*84e872a0SLloyd Pique #define PCF_SWIDTHS		    (1<<6)
68*84e872a0SLloyd Pique #define PCF_GLYPH_NAMES		    (1<<7)
69*84e872a0SLloyd Pique #define PCF_BDF_ACCELERATORS	    (1<<8)
70*84e872a0SLloyd Pique 
71*84e872a0SLloyd Pique #define PCF_DEFAULT_FORMAT	0x00000000
72*84e872a0SLloyd Pique #define PCF_INKBOUNDS		0x00000200
73*84e872a0SLloyd Pique #define PCF_ACCEL_W_INKBOUNDS	0x00000100
74*84e872a0SLloyd Pique #define PCF_COMPRESSED_METRICS	0x00000100
75*84e872a0SLloyd Pique 
76*84e872a0SLloyd Pique #define	PCF_FORMAT_MASK		0xffffff00
77*84e872a0SLloyd Pique 
78*84e872a0SLloyd Pique struct pcf_header {
79*84e872a0SLloyd Pique 	char header[4];
80*84e872a0SLloyd Pique 	int32_t table_count;
81*84e872a0SLloyd Pique 	struct toc_entry {
82*84e872a0SLloyd Pique 		int32_t type;
83*84e872a0SLloyd Pique 		int32_t format;
84*84e872a0SLloyd Pique 		int32_t size;
85*84e872a0SLloyd Pique 		int32_t offset;
86*84e872a0SLloyd Pique 	} tables[0];
87*84e872a0SLloyd Pique };
88*84e872a0SLloyd Pique 
89*84e872a0SLloyd Pique struct compressed_metrics {
90*84e872a0SLloyd Pique 	uint8_t left_sided_bearing;
91*84e872a0SLloyd Pique 	uint8_t right_side_bearing;
92*84e872a0SLloyd Pique 	uint8_t character_width;
93*84e872a0SLloyd Pique 	uint8_t character_ascent;
94*84e872a0SLloyd Pique 	uint8_t character_descent;
95*84e872a0SLloyd Pique };
96*84e872a0SLloyd Pique 
97*84e872a0SLloyd Pique struct uncompressed_metrics {
98*84e872a0SLloyd Pique 	int16_t left_sided_bearing;
99*84e872a0SLloyd Pique 	int16_t right_side_bearing;
100*84e872a0SLloyd Pique 	int16_t character_width;
101*84e872a0SLloyd Pique 	int16_t character_ascent;
102*84e872a0SLloyd Pique 	int16_t character_descent;
103*84e872a0SLloyd Pique 	uint16_t character_attributes;
104*84e872a0SLloyd Pique };
105*84e872a0SLloyd Pique 
106*84e872a0SLloyd Pique struct metrics {
107*84e872a0SLloyd Pique 	int32_t format;
108*84e872a0SLloyd Pique 	union {
109*84e872a0SLloyd Pique 		struct {
110*84e872a0SLloyd Pique 			int16_t count;
111*84e872a0SLloyd Pique 			struct compressed_metrics compressed_metrics[0];
112*84e872a0SLloyd Pique 		} compressed;
113*84e872a0SLloyd Pique 		struct {
114*84e872a0SLloyd Pique 			int32_t count;
115*84e872a0SLloyd Pique 			struct uncompressed_metrics uncompressed_metrics[0];
116*84e872a0SLloyd Pique 		} uncompressed;
117*84e872a0SLloyd Pique 	};
118*84e872a0SLloyd Pique };
119*84e872a0SLloyd Pique 
120*84e872a0SLloyd Pique struct glyph_names {
121*84e872a0SLloyd Pique 	int32_t format;
122*84e872a0SLloyd Pique 	int32_t glyph_count;
123*84e872a0SLloyd Pique 	int32_t offsets[0];
124*84e872a0SLloyd Pique };
125*84e872a0SLloyd Pique 
126*84e872a0SLloyd Pique struct bitmaps {
127*84e872a0SLloyd Pique 	int32_t format;
128*84e872a0SLloyd Pique 	int32_t glyph_count;
129*84e872a0SLloyd Pique 	int32_t offsets[0];
130*84e872a0SLloyd Pique };
131*84e872a0SLloyd Pique 
132*84e872a0SLloyd Pique static void
handle_compressed_metrics(int32_t count,struct compressed_metrics * m)133*84e872a0SLloyd Pique handle_compressed_metrics(int32_t count, struct compressed_metrics *m)
134*84e872a0SLloyd Pique {
135*84e872a0SLloyd Pique 	printf("metrics count: %d\n", count);
136*84e872a0SLloyd Pique 	extracted_font.count = count;
137*84e872a0SLloyd Pique 	extracted_font.glyphs = calloc(count, sizeof(struct glyph));
138*84e872a0SLloyd Pique 
139*84e872a0SLloyd Pique 	int i;
140*84e872a0SLloyd Pique 	for (i = 0; i < count; ++i) {
141*84e872a0SLloyd Pique 		struct glyph *glyph = &extracted_font.glyphs[i];
142*84e872a0SLloyd Pique 		glyph->left_bearing =
143*84e872a0SLloyd Pique 			((int16_t) m[i].left_sided_bearing) - 0x80;
144*84e872a0SLloyd Pique 		glyph->right_bearing =
145*84e872a0SLloyd Pique 			((int16_t) m[i].right_side_bearing) - 0x80;
146*84e872a0SLloyd Pique 		glyph->width = ((int16_t) m[i].character_width) - 0x80;
147*84e872a0SLloyd Pique 		glyph->ascent = ((int16_t) m[i].character_ascent) - 0x80;
148*84e872a0SLloyd Pique 		glyph->descent = ((int16_t) m[i].character_descent) - 0x80;
149*84e872a0SLloyd Pique 
150*84e872a0SLloyd Pique 		/* computed stuff */
151*84e872a0SLloyd Pique 		glyph->height = glyph->ascent + glyph->descent;
152*84e872a0SLloyd Pique 
153*84e872a0SLloyd Pique 		glyph->hotx = -glyph->left_bearing;
154*84e872a0SLloyd Pique 		glyph->hoty = glyph->ascent;
155*84e872a0SLloyd Pique 	}
156*84e872a0SLloyd Pique }
157*84e872a0SLloyd Pique 
158*84e872a0SLloyd Pique static void
handle_metrics(void * metricbuf)159*84e872a0SLloyd Pique handle_metrics(void *metricbuf)
160*84e872a0SLloyd Pique {
161*84e872a0SLloyd Pique 	struct metrics *metrics = metricbuf;
162*84e872a0SLloyd Pique 	printf("metric format: %x\n", metrics->format);
163*84e872a0SLloyd Pique 
164*84e872a0SLloyd Pique 	if ((metrics->format & PCF_FORMAT_MASK) == PCF_DEFAULT_FORMAT) {
165*84e872a0SLloyd Pique 		printf("todo...\n");
166*84e872a0SLloyd Pique 	} else if ((metrics->format & PCF_FORMAT_MASK) ==
167*84e872a0SLloyd Pique 		   PCF_COMPRESSED_METRICS) {
168*84e872a0SLloyd Pique 		handle_compressed_metrics(
169*84e872a0SLloyd Pique 		    metrics->compressed.count,
170*84e872a0SLloyd Pique 		    &metrics->compressed.compressed_metrics[0]);
171*84e872a0SLloyd Pique 	} else {
172*84e872a0SLloyd Pique 		printf("incompatible format\n");
173*84e872a0SLloyd Pique 		abort();
174*84e872a0SLloyd Pique 	}
175*84e872a0SLloyd Pique }
176*84e872a0SLloyd Pique 
177*84e872a0SLloyd Pique static void
handle_glyph_names(struct glyph_names * names)178*84e872a0SLloyd Pique handle_glyph_names(struct glyph_names *names)
179*84e872a0SLloyd Pique {
180*84e872a0SLloyd Pique 	printf("glyph count %d\n", names->glyph_count);
181*84e872a0SLloyd Pique 
182*84e872a0SLloyd Pique 	if (names->glyph_count != extracted_font.count) {
183*84e872a0SLloyd Pique 		abort();
184*84e872a0SLloyd Pique 	}
185*84e872a0SLloyd Pique 
186*84e872a0SLloyd Pique 	printf("glyph names format %x\n", names->format);
187*84e872a0SLloyd Pique 
188*84e872a0SLloyd Pique 	void *names_start = ((void*) names) + sizeof(struct glyph_names)
189*84e872a0SLloyd Pique 		+ (names->glyph_count + 1) * sizeof(int32_t);
190*84e872a0SLloyd Pique 
191*84e872a0SLloyd Pique 	int i;
192*84e872a0SLloyd Pique 	for (i = 0; i < names->glyph_count; ++i) {
193*84e872a0SLloyd Pique 		int32_t start = names->offsets[i];
194*84e872a0SLloyd Pique 		int32_t end = names->offsets[i+1];
195*84e872a0SLloyd Pique 		char *name = names_start + start;
196*84e872a0SLloyd Pique 		extracted_font.glyphs[i].name = calloc(1, end - start + 1);
197*84e872a0SLloyd Pique 		memcpy(extracted_font.glyphs[i].name, name, end - start);
198*84e872a0SLloyd Pique 	}
199*84e872a0SLloyd Pique }
200*84e872a0SLloyd Pique 
201*84e872a0SLloyd Pique static void
handle_bitmaps(struct bitmaps * bitmaps)202*84e872a0SLloyd Pique handle_bitmaps(struct bitmaps *bitmaps)
203*84e872a0SLloyd Pique {
204*84e872a0SLloyd Pique 	printf("bitmaps count %d\n", bitmaps->glyph_count);
205*84e872a0SLloyd Pique 
206*84e872a0SLloyd Pique 	if (bitmaps->glyph_count != extracted_font.count) {
207*84e872a0SLloyd Pique 		abort();
208*84e872a0SLloyd Pique 	}
209*84e872a0SLloyd Pique 
210*84e872a0SLloyd Pique 	printf("format %x\n", bitmaps->format);
211*84e872a0SLloyd Pique 
212*84e872a0SLloyd Pique 	if (bitmaps->format != 2) {
213*84e872a0SLloyd Pique 		printf("format not yet supported\n");
214*84e872a0SLloyd Pique 		abort();
215*84e872a0SLloyd Pique 	}
216*84e872a0SLloyd Pique 
217*84e872a0SLloyd Pique 	void *bitmaps_start = ((void*) bitmaps) + sizeof(struct bitmaps)
218*84e872a0SLloyd Pique 		+ (bitmaps->glyph_count + 4) * sizeof(int32_t);
219*84e872a0SLloyd Pique 
220*84e872a0SLloyd Pique 	int i;
221*84e872a0SLloyd Pique 	for (i = 0; i < bitmaps->glyph_count; ++i) {
222*84e872a0SLloyd Pique 		int32_t offset = bitmaps->offsets[i];
223*84e872a0SLloyd Pique 		struct glyph *glyph = &extracted_font.glyphs[i];
224*84e872a0SLloyd Pique 		glyph->data_format = bitmaps->format;
225*84e872a0SLloyd Pique 
226*84e872a0SLloyd Pique 		glyph->data = bitmaps_start + offset;
227*84e872a0SLloyd Pique 	}
228*84e872a0SLloyd Pique }
229*84e872a0SLloyd Pique 
230*84e872a0SLloyd Pique static void
handle_pcf(void * fontbuf)231*84e872a0SLloyd Pique handle_pcf(void *fontbuf)
232*84e872a0SLloyd Pique {
233*84e872a0SLloyd Pique 	struct pcf_header *header = fontbuf;
234*84e872a0SLloyd Pique 	printf("tablecount %d\n", header->table_count);
235*84e872a0SLloyd Pique 
236*84e872a0SLloyd Pique 	int i;
237*84e872a0SLloyd Pique 	for (i = 0; i < header->table_count; ++i) {
238*84e872a0SLloyd Pique 		struct toc_entry *entry = &header->tables[i];
239*84e872a0SLloyd Pique 		printf("type: %d\n", entry->type);
240*84e872a0SLloyd Pique 		if (entry->type == PCF_METRICS) {
241*84e872a0SLloyd Pique 			handle_metrics(fontbuf + entry->offset);
242*84e872a0SLloyd Pique 		} else if (entry->type == PCF_GLYPH_NAMES) {
243*84e872a0SLloyd Pique 			handle_glyph_names(fontbuf + entry->offset);
244*84e872a0SLloyd Pique 		} else if (entry->type == PCF_BITMAPS) {
245*84e872a0SLloyd Pique 			handle_bitmaps(fontbuf + entry->offset);
246*84e872a0SLloyd Pique 		}
247*84e872a0SLloyd Pique 	}
248*84e872a0SLloyd Pique }
249*84e872a0SLloyd Pique 
250*84e872a0SLloyd Pique static char
get_glyph_pixel(struct glyph * glyph,int x,int y)251*84e872a0SLloyd Pique get_glyph_pixel(struct glyph *glyph, int x, int y)
252*84e872a0SLloyd Pique {
253*84e872a0SLloyd Pique 	int absx = glyph->hotx + x;
254*84e872a0SLloyd Pique 	int absy = glyph->hoty + y;
255*84e872a0SLloyd Pique 
256*84e872a0SLloyd Pique 	if (absx < 0 || absx >= glyph->width ||
257*84e872a0SLloyd Pique 	    absy < 0 || absy >= glyph->height)
258*84e872a0SLloyd Pique 		return 0;
259*84e872a0SLloyd Pique 
260*84e872a0SLloyd Pique 	int stride = (glyph->width + 31) / 32 * 4;
261*84e872a0SLloyd Pique 	unsigned char block = glyph->data[absy * stride + (absx/8)];
262*84e872a0SLloyd Pique 	int idx = absx % 8;
263*84e872a0SLloyd Pique 	return (block >> idx) & 1;
264*84e872a0SLloyd Pique }
265*84e872a0SLloyd Pique 
266*84e872a0SLloyd Pique static struct {
267*84e872a0SLloyd Pique 	uint32_t *data;
268*84e872a0SLloyd Pique 	size_t capacity, size;
269*84e872a0SLloyd Pique } data_buffer;
270*84e872a0SLloyd Pique 
271*84e872a0SLloyd Pique static void
init_data_buffer()272*84e872a0SLloyd Pique init_data_buffer()
273*84e872a0SLloyd Pique {
274*84e872a0SLloyd Pique 	data_buffer.data = malloc(sizeof(uint32_t) * 10);
275*84e872a0SLloyd Pique 	data_buffer.capacity = 10;
276*84e872a0SLloyd Pique 	data_buffer.size = 0;
277*84e872a0SLloyd Pique }
278*84e872a0SLloyd Pique 
279*84e872a0SLloyd Pique static void
add_pixel(uint32_t pixel)280*84e872a0SLloyd Pique add_pixel(uint32_t pixel)
281*84e872a0SLloyd Pique {
282*84e872a0SLloyd Pique 	if (data_buffer.size == data_buffer.capacity) {
283*84e872a0SLloyd Pique 		data_buffer.capacity *= 2;
284*84e872a0SLloyd Pique 		data_buffer.data =
285*84e872a0SLloyd Pique 			realloc(data_buffer.data,
286*84e872a0SLloyd Pique 				sizeof(uint32_t) * data_buffer.capacity);
287*84e872a0SLloyd Pique 	}
288*84e872a0SLloyd Pique 	data_buffer.data[data_buffer.size++] = pixel;
289*84e872a0SLloyd Pique }
290*84e872a0SLloyd Pique 
291*84e872a0SLloyd Pique struct reconstructed_glyph {
292*84e872a0SLloyd Pique 	int32_t width, height;
293*84e872a0SLloyd Pique 	int32_t hotspot_x, hotspot_y;
294*84e872a0SLloyd Pique 	size_t offset;
295*84e872a0SLloyd Pique 	char *name;
296*84e872a0SLloyd Pique };
297*84e872a0SLloyd Pique 
298*84e872a0SLloyd Pique static void
reconstruct_glyph(struct glyph * cursor,struct glyph * mask,char * name,struct reconstructed_glyph * glyph)299*84e872a0SLloyd Pique reconstruct_glyph(struct glyph *cursor, struct glyph *mask, char *name,
300*84e872a0SLloyd Pique 		  struct reconstructed_glyph *glyph)
301*84e872a0SLloyd Pique {
302*84e872a0SLloyd Pique 	int minx = min(-cursor->hotx, -mask->hotx);
303*84e872a0SLloyd Pique 	int maxx = max(cursor->right_bearing, mask->right_bearing);
304*84e872a0SLloyd Pique 
305*84e872a0SLloyd Pique 	int miny = min(-cursor->hoty, -mask->hoty);
306*84e872a0SLloyd Pique 	int maxy = max(cursor->height - cursor->hoty,
307*84e872a0SLloyd Pique 		       mask->height - mask->hoty);
308*84e872a0SLloyd Pique 
309*84e872a0SLloyd Pique 	int width = maxx - minx;
310*84e872a0SLloyd Pique 	int height = maxy - miny;
311*84e872a0SLloyd Pique 
312*84e872a0SLloyd Pique 	glyph->name = strdup(name);
313*84e872a0SLloyd Pique 	glyph->width = width;
314*84e872a0SLloyd Pique 	glyph->height = height;
315*84e872a0SLloyd Pique 	glyph->hotspot_x = -minx;
316*84e872a0SLloyd Pique 	glyph->hotspot_y = -miny;
317*84e872a0SLloyd Pique 	glyph->offset = data_buffer.size;
318*84e872a0SLloyd Pique 
319*84e872a0SLloyd Pique 	int x, y;
320*84e872a0SLloyd Pique 	for (y = miny; y < maxy; ++y) {
321*84e872a0SLloyd Pique 		for (x = minx; x < maxx; ++x) {
322*84e872a0SLloyd Pique 			char alpha = get_glyph_pixel(mask, x, y);
323*84e872a0SLloyd Pique 			if (alpha) {
324*84e872a0SLloyd Pique 				char color = get_glyph_pixel(cursor, x, y);
325*84e872a0SLloyd Pique 				if (color)
326*84e872a0SLloyd Pique 					add_pixel(0xff000000);
327*84e872a0SLloyd Pique 				else
328*84e872a0SLloyd Pique 					add_pixel(0xffffffff);
329*84e872a0SLloyd Pique 			} else {
330*84e872a0SLloyd Pique 				add_pixel(0);
331*84e872a0SLloyd Pique 			}
332*84e872a0SLloyd Pique 		}
333*84e872a0SLloyd Pique 	}
334*84e872a0SLloyd Pique }
335*84e872a0SLloyd Pique 
336*84e872a0SLloyd Pique /*
337*84e872a0SLloyd Pique  * Originally from
338*84e872a0SLloyd Pique  * http://cgit.freedesktop.org/xorg/lib/libXfont/tree/src/builtins/fonts.c
339*84e872a0SLloyd Pique  * Changed to the MIT "Expat" style license for Wayland..
340*84e872a0SLloyd Pique  */
341*84e872a0SLloyd Pique static const char cursor_licence[] =
342*84e872a0SLloyd Pique 	"/*\n"
343*84e872a0SLloyd Pique 	"* Copyright 1999 SuSE, Inc.\n"
344*84e872a0SLloyd Pique 	"*\n"
345*84e872a0SLloyd Pique 	"* Permission is hereby granted, free of charge, to any person obtaining\n"
346*84e872a0SLloyd Pique 	"* a copy of this software and associated documentation files (the\n"
347*84e872a0SLloyd Pique 	"* \"Software\"), to deal in the Software without restriction, including\n"
348*84e872a0SLloyd Pique 	"* without limitation the rights to use, copy, modify, merge, publish,\n"
349*84e872a0SLloyd Pique 	"* distribute, sublicense, and/or sell copies of the Software, and to\n"
350*84e872a0SLloyd Pique 	"* permit persons to whom the Software is furnished to do so, subject to\n"
351*84e872a0SLloyd Pique 	"* the following conditions:\n"
352*84e872a0SLloyd Pique 	"*\n"
353*84e872a0SLloyd Pique 	"* The above copyright notice and this permission notice (including the\n"
354*84e872a0SLloyd Pique 	"* next paragraph) shall be included in all copies or substantial\n"
355*84e872a0SLloyd Pique 	"* portions of the Software.\n"
356*84e872a0SLloyd Pique 	"*\n"
357*84e872a0SLloyd Pique 	"* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n"
358*84e872a0SLloyd Pique 	"* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n"
359*84e872a0SLloyd Pique 	"* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n"
360*84e872a0SLloyd Pique 	"* NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n"
361*84e872a0SLloyd Pique 	"* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n"
362*84e872a0SLloyd Pique 	"* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n"
363*84e872a0SLloyd Pique 	"* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n"
364*84e872a0SLloyd Pique 	"* SOFTWARE.\n"
365*84e872a0SLloyd Pique 	"*\n"
366*84e872a0SLloyd Pique 	"* Author:  Keith Packard, SuSE, Inc.\n"
367*84e872a0SLloyd Pique 	"*/\n";
368*84e872a0SLloyd Pique 
369*84e872a0SLloyd Pique static void
write_output_file(struct reconstructed_glyph * glyphs,int n)370*84e872a0SLloyd Pique write_output_file(struct reconstructed_glyph *glyphs, int n)
371*84e872a0SLloyd Pique {
372*84e872a0SLloyd Pique 	int i, j, counter, size;
373*84e872a0SLloyd Pique 	FILE *file = fopen("cursor-data.h", "w");
374*84e872a0SLloyd Pique 	uint32_t *data;
375*84e872a0SLloyd Pique 
376*84e872a0SLloyd Pique 	fprintf(file, "%s\n", cursor_licence);
377*84e872a0SLloyd Pique 
378*84e872a0SLloyd Pique 	fprintf(file, "static uint32_t cursor_data[] = {\n\t");
379*84e872a0SLloyd Pique 
380*84e872a0SLloyd Pique 	counter = 0;
381*84e872a0SLloyd Pique 	for (i = 0; i < n; ++i) {
382*84e872a0SLloyd Pique 		data = data_buffer.data + glyphs[i].offset;
383*84e872a0SLloyd Pique 		size = glyphs[i].width * glyphs[i].height;
384*84e872a0SLloyd Pique 
385*84e872a0SLloyd Pique 		for (j = 0; j < size; ++j) {
386*84e872a0SLloyd Pique 			fprintf(file, "0x%08x, ", data[j]);
387*84e872a0SLloyd Pique 			if (++counter % 6 == 0)
388*84e872a0SLloyd Pique 				fprintf(file, "\n\t");
389*84e872a0SLloyd Pique 		}
390*84e872a0SLloyd Pique 	}
391*84e872a0SLloyd Pique 	fprintf(file, "\n};\n\n");
392*84e872a0SLloyd Pique 
393*84e872a0SLloyd Pique 	fprintf(file,
394*84e872a0SLloyd Pique 		"static struct {\n"
395*84e872a0SLloyd Pique 		"\tchar *name;\n"
396*84e872a0SLloyd Pique 		"\tint width, height;\n"
397*84e872a0SLloyd Pique 		"\tint hotspot_x, hotspot_y;\n"
398*84e872a0SLloyd Pique 		"\tsize_t offset;\n"
399*84e872a0SLloyd Pique 		"} cursor_metadata[] = {\n");
400*84e872a0SLloyd Pique 
401*84e872a0SLloyd Pique 	for (i = 0; i < n; ++i)
402*84e872a0SLloyd Pique 		fprintf(file, "\t{ \"%s\", %d, %d, %d, %d, %zu },\n",
403*84e872a0SLloyd Pique 			glyphs[i].name,
404*84e872a0SLloyd Pique 			glyphs[i].width, glyphs[i].height,
405*84e872a0SLloyd Pique 			glyphs[i].hotspot_x, glyphs[i].hotspot_y,
406*84e872a0SLloyd Pique 			glyphs[i].offset);
407*84e872a0SLloyd Pique 
408*84e872a0SLloyd Pique 	fprintf(file, "};");
409*84e872a0SLloyd Pique 
410*84e872a0SLloyd Pique 	fclose(file);
411*84e872a0SLloyd Pique }
412*84e872a0SLloyd Pique 
413*84e872a0SLloyd Pique struct glyph *
find_mask_glyph(char * name)414*84e872a0SLloyd Pique find_mask_glyph(char *name)
415*84e872a0SLloyd Pique {
416*84e872a0SLloyd Pique 	const char mask[] = "_mask";
417*84e872a0SLloyd Pique 	const int masklen = strlen(mask);
418*84e872a0SLloyd Pique 
419*84e872a0SLloyd Pique 	int len = strlen(name);
420*84e872a0SLloyd Pique 	int i;
421*84e872a0SLloyd Pique 	for (i = 0; i < extracted_font.count; ++i) {
422*84e872a0SLloyd Pique 		struct glyph *g = &extracted_font.glyphs[i];
423*84e872a0SLloyd Pique 		int l2 = strlen(g->name);
424*84e872a0SLloyd Pique 		if ((l2 == len + masklen) &&
425*84e872a0SLloyd Pique 		    (memcmp(g->name, name, len) == 0) &&
426*84e872a0SLloyd Pique 		    (memcmp(g->name + len, mask, masklen) == 0)) {
427*84e872a0SLloyd Pique 			return g;
428*84e872a0SLloyd Pique 		}
429*84e872a0SLloyd Pique 	}
430*84e872a0SLloyd Pique 	return NULL;
431*84e872a0SLloyd Pique }
432*84e872a0SLloyd Pique 
433*84e872a0SLloyd Pique static void
output_all_cursors()434*84e872a0SLloyd Pique output_all_cursors()
435*84e872a0SLloyd Pique {
436*84e872a0SLloyd Pique 	int i, j;
437*84e872a0SLloyd Pique 	struct reconstructed_glyph *glyphs =
438*84e872a0SLloyd Pique 		malloc(sizeof(struct reconstructed_glyph) *
439*84e872a0SLloyd Pique 		       extracted_font.count/2);
440*84e872a0SLloyd Pique 	j = 0;
441*84e872a0SLloyd Pique 
442*84e872a0SLloyd Pique 	for (i = 0; i < extracted_font.count; ++i) {
443*84e872a0SLloyd Pique 		struct glyph *g = &extracted_font.glyphs[i];
444*84e872a0SLloyd Pique 		if (strstr(g->name, "_mask"))
445*84e872a0SLloyd Pique 			continue;
446*84e872a0SLloyd Pique 
447*84e872a0SLloyd Pique 		struct glyph *mask = find_mask_glyph(g->name);
448*84e872a0SLloyd Pique 
449*84e872a0SLloyd Pique 		reconstruct_glyph(g, mask, g->name, &glyphs[j]);
450*84e872a0SLloyd Pique 		j++;
451*84e872a0SLloyd Pique 	}
452*84e872a0SLloyd Pique 
453*84e872a0SLloyd Pique 	write_output_file(glyphs, extracted_font.count/2);
454*84e872a0SLloyd Pique }
455*84e872a0SLloyd Pique 
456*84e872a0SLloyd Pique static void
find_cursor_and_mask(const char * name,struct glyph ** cursor,struct glyph ** mask)457*84e872a0SLloyd Pique find_cursor_and_mask(const char *name,
458*84e872a0SLloyd Pique 		     struct glyph **cursor,
459*84e872a0SLloyd Pique 		     struct glyph **mask)
460*84e872a0SLloyd Pique {
461*84e872a0SLloyd Pique 	int i;
462*84e872a0SLloyd Pique 	char mask_name[100];
463*84e872a0SLloyd Pique 	sprintf(mask_name, "%s_mask", name);
464*84e872a0SLloyd Pique 
465*84e872a0SLloyd Pique 	*cursor = *mask = NULL;
466*84e872a0SLloyd Pique 
467*84e872a0SLloyd Pique 	for (i = 0; i < extracted_font.count && (!*mask || !*cursor); ++i) {
468*84e872a0SLloyd Pique 		struct glyph *g = &extracted_font.glyphs[i];
469*84e872a0SLloyd Pique 		if (!strcmp(name, g->name))
470*84e872a0SLloyd Pique 			*cursor = g;
471*84e872a0SLloyd Pique 		else if (!strcmp(mask_name, g->name))
472*84e872a0SLloyd Pique 			*mask = g;
473*84e872a0SLloyd Pique 	}
474*84e872a0SLloyd Pique }
475*84e872a0SLloyd Pique 
476*84e872a0SLloyd Pique static struct {
477*84e872a0SLloyd Pique 	char *target_name, *source_name;
478*84e872a0SLloyd Pique } interesting_cursors[] = {
479*84e872a0SLloyd Pique 	{ "bottom_left_corner", "bottom_left_corner" },
480*84e872a0SLloyd Pique 	{ "bottom_right_corner", "bottom_right_corner" },
481*84e872a0SLloyd Pique 	{ "bottom_side", "bottom_side" },
482*84e872a0SLloyd Pique 	{ "grabbing", "fleur" },
483*84e872a0SLloyd Pique 	{ "left_ptr", "left_ptr" },
484*84e872a0SLloyd Pique 	{ "left_side", "left_side" },
485*84e872a0SLloyd Pique 	{ "right_side", "right_side" },
486*84e872a0SLloyd Pique 	{ "top_left_corner", "top_left_corner" },
487*84e872a0SLloyd Pique 	{ "top_right_corner", "top_right_corner" },
488*84e872a0SLloyd Pique 	{ "top_side", "top_side" },
489*84e872a0SLloyd Pique 	{ "xterm", "xterm" },
490*84e872a0SLloyd Pique 	{ "hand1", "hand1" },
491*84e872a0SLloyd Pique 	{ "watch", "watch" }
492*84e872a0SLloyd Pique };
493*84e872a0SLloyd Pique 
494*84e872a0SLloyd Pique static void
output_interesting_cursors()495*84e872a0SLloyd Pique output_interesting_cursors()
496*84e872a0SLloyd Pique {
497*84e872a0SLloyd Pique 	int i;
498*84e872a0SLloyd Pique 	int n = sizeof(interesting_cursors) / sizeof(interesting_cursors[0]);
499*84e872a0SLloyd Pique 	struct reconstructed_glyph *glyphs =
500*84e872a0SLloyd Pique 		malloc(n * sizeof(*glyphs));
501*84e872a0SLloyd Pique 
502*84e872a0SLloyd Pique 	if (!glyphs) {
503*84e872a0SLloyd Pique 		printf("reconstructed_glyph malloc failed\n");
504*84e872a0SLloyd Pique 		abort();
505*84e872a0SLloyd Pique 	}
506*84e872a0SLloyd Pique 
507*84e872a0SLloyd Pique 	for (i = 0; i < n; ++i) {
508*84e872a0SLloyd Pique 		struct glyph *cursor, *mask;
509*84e872a0SLloyd Pique 		find_cursor_and_mask(interesting_cursors[i].source_name,
510*84e872a0SLloyd Pique 				     &cursor, &mask);
511*84e872a0SLloyd Pique 		if (!cursor) {
512*84e872a0SLloyd Pique 			printf("no cursor for %s\n",
513*84e872a0SLloyd Pique 			       interesting_cursors[i].source_name);
514*84e872a0SLloyd Pique 			abort();
515*84e872a0SLloyd Pique 		}
516*84e872a0SLloyd Pique 		if (!mask) {
517*84e872a0SLloyd Pique 			printf("no mask for %s\n",
518*84e872a0SLloyd Pique 			       interesting_cursors[i].source_name);
519*84e872a0SLloyd Pique 			abort();
520*84e872a0SLloyd Pique 		}
521*84e872a0SLloyd Pique 		reconstruct_glyph(cursor, mask,
522*84e872a0SLloyd Pique 				  interesting_cursors[i].target_name,
523*84e872a0SLloyd Pique 				  &glyphs[i]);
524*84e872a0SLloyd Pique 	}
525*84e872a0SLloyd Pique 
526*84e872a0SLloyd Pique 	write_output_file(glyphs, n);
527*84e872a0SLloyd Pique }
528*84e872a0SLloyd Pique 
main()529*84e872a0SLloyd Pique int main()
530*84e872a0SLloyd Pique {
531*84e872a0SLloyd Pique 	const char filename[] = "cursor.pcf";
532*84e872a0SLloyd Pique 
533*84e872a0SLloyd Pique 	int fd = open(filename, O_RDONLY);
534*84e872a0SLloyd Pique 	struct stat filestat;
535*84e872a0SLloyd Pique 
536*84e872a0SLloyd Pique 	fstat(fd, &filestat);
537*84e872a0SLloyd Pique 
538*84e872a0SLloyd Pique 	void *fontbuf = mmap(NULL, filestat.st_size, PROT_READ,
539*84e872a0SLloyd Pique 			     MAP_PRIVATE, fd, 0);
540*84e872a0SLloyd Pique 
541*84e872a0SLloyd Pique 	handle_pcf(fontbuf);
542*84e872a0SLloyd Pique 
543*84e872a0SLloyd Pique 	init_data_buffer();
544*84e872a0SLloyd Pique 
545*84e872a0SLloyd Pique 	//output_all_cursors();
546*84e872a0SLloyd Pique 	output_interesting_cursors();
547*84e872a0SLloyd Pique }
548