| 
									
										
										
										
											2012-09-06 18:54:02 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright © 2012 Philipp Brüschweiler | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-06-10 11:03:00 -07:00
										 |  |  |  * Permission is hereby granted, free of charge, to any person obtaining | 
					
						
							|  |  |  |  * a copy of this software and associated documentation files (the | 
					
						
							|  |  |  |  * "Software"), to deal in the Software without restriction, including | 
					
						
							|  |  |  |  * without limitation the rights to use, copy, modify, merge, publish, | 
					
						
							|  |  |  |  * distribute, sublicense, and/or sell copies of the Software, and to | 
					
						
							|  |  |  |  * permit persons to whom the Software is furnished to do so, subject to | 
					
						
							|  |  |  |  * the following conditions: | 
					
						
							| 
									
										
										
										
											2012-09-06 18:54:02 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-06-10 11:03:00 -07:00
										 |  |  |  * The above copyright notice and this permission notice (including the | 
					
						
							|  |  |  |  * next paragraph) shall be included in all copies or substantial | 
					
						
							|  |  |  |  * portions of the Software. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 
					
						
							|  |  |  |  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 
					
						
							|  |  |  |  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 
					
						
							|  |  |  |  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | 
					
						
							|  |  |  |  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | 
					
						
							|  |  |  |  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | 
					
						
							|  |  |  |  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 
					
						
							|  |  |  |  * SOFTWARE. | 
					
						
							| 
									
										
										
										
											2012-09-06 18:54:02 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * This is a small, hacky tool to extract cursors from a .pcf file. | 
					
						
							|  |  |  |  * The information about the file format has been gathered from | 
					
						
							|  |  |  |  * http://fontforge.org/pcf-format.html
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <fcntl.h>
 | 
					
						
							|  |  |  | #include <stdint.h>
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <sys/mman.h>
 | 
					
						
							|  |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <sys/stat.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define min(a, b) ((a) < (b) ? (a) : (b))
 | 
					
						
							|  |  |  | #define max(a, b) ((a) > (b) ? (a) : (b))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct glyph { | 
					
						
							|  |  |  | 	char *name; | 
					
						
							|  |  |  | 	int16_t left_bearing, right_bearing, ascent, descent; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int16_t width, height; | 
					
						
							|  |  |  | 	int16_t hotx, hoty; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int32_t data_format; | 
					
						
							|  |  |  | 	char *data; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct { | 
					
						
							|  |  |  | 	int count; | 
					
						
							|  |  |  | 	struct glyph *glyphs; | 
					
						
							|  |  |  | } extracted_font = {0, NULL}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define PCF_PROPERTIES		    (1<<0)
 | 
					
						
							|  |  |  | #define PCF_ACCELERATORS	    (1<<1)
 | 
					
						
							|  |  |  | #define PCF_METRICS		    (1<<2)
 | 
					
						
							|  |  |  | #define PCF_BITMAPS		    (1<<3)
 | 
					
						
							|  |  |  | #define PCF_INK_METRICS		    (1<<4)
 | 
					
						
							|  |  |  | #define	PCF_BDF_ENCODINGS	    (1<<5)
 | 
					
						
							|  |  |  | #define PCF_SWIDTHS		    (1<<6)
 | 
					
						
							|  |  |  | #define PCF_GLYPH_NAMES		    (1<<7)
 | 
					
						
							|  |  |  | #define PCF_BDF_ACCELERATORS	    (1<<8)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define PCF_DEFAULT_FORMAT	0x00000000
 | 
					
						
							|  |  |  | #define PCF_INKBOUNDS		0x00000200
 | 
					
						
							|  |  |  | #define PCF_ACCEL_W_INKBOUNDS	0x00000100
 | 
					
						
							|  |  |  | #define PCF_COMPRESSED_METRICS	0x00000100
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define	PCF_FORMAT_MASK		0xffffff00
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct pcf_header { | 
					
						
							|  |  |  | 	char header[4]; | 
					
						
							|  |  |  | 	int32_t table_count; | 
					
						
							|  |  |  | 	struct toc_entry { | 
					
						
							|  |  |  | 		int32_t type; | 
					
						
							|  |  |  | 		int32_t format; | 
					
						
							|  |  |  | 		int32_t size; | 
					
						
							|  |  |  | 		int32_t offset; | 
					
						
							|  |  |  | 	} tables[0]; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct compressed_metrics { | 
					
						
							|  |  |  | 	uint8_t left_sided_bearing; | 
					
						
							|  |  |  | 	uint8_t right_side_bearing; | 
					
						
							|  |  |  | 	uint8_t character_width; | 
					
						
							|  |  |  | 	uint8_t character_ascent; | 
					
						
							|  |  |  | 	uint8_t character_descent; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct uncompressed_metrics { | 
					
						
							|  |  |  | 	int16_t left_sided_bearing; | 
					
						
							|  |  |  | 	int16_t right_side_bearing; | 
					
						
							|  |  |  | 	int16_t character_width; | 
					
						
							|  |  |  | 	int16_t character_ascent; | 
					
						
							|  |  |  | 	int16_t character_descent; | 
					
						
							|  |  |  | 	uint16_t character_attributes; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct metrics { | 
					
						
							|  |  |  | 	int32_t format; | 
					
						
							|  |  |  | 	union { | 
					
						
							|  |  |  | 		struct { | 
					
						
							|  |  |  | 			int16_t count; | 
					
						
							|  |  |  | 			struct compressed_metrics compressed_metrics[0]; | 
					
						
							|  |  |  | 		} compressed; | 
					
						
							|  |  |  | 		struct { | 
					
						
							|  |  |  | 			int32_t count; | 
					
						
							|  |  |  | 			struct uncompressed_metrics uncompressed_metrics[0]; | 
					
						
							|  |  |  | 		} uncompressed; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct glyph_names { | 
					
						
							|  |  |  | 	int32_t format; | 
					
						
							|  |  |  | 	int32_t glyph_count; | 
					
						
							|  |  |  | 	int32_t offsets[0]; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct bitmaps { | 
					
						
							|  |  |  | 	int32_t format; | 
					
						
							|  |  |  | 	int32_t glyph_count; | 
					
						
							|  |  |  | 	int32_t offsets[0]; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | handle_compressed_metrics(int32_t count, struct compressed_metrics *m) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	printf("metrics count: %d\n", count); | 
					
						
							|  |  |  | 	extracted_font.count = count; | 
					
						
							|  |  |  | 	extracted_font.glyphs = calloc(count, sizeof(struct glyph)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	for (i = 0; i < count; ++i) { | 
					
						
							|  |  |  | 		struct glyph *glyph = &extracted_font.glyphs[i]; | 
					
						
							|  |  |  | 		glyph->left_bearing = | 
					
						
							|  |  |  | 			((int16_t) m[i].left_sided_bearing) - 0x80; | 
					
						
							|  |  |  | 		glyph->right_bearing = | 
					
						
							|  |  |  | 			((int16_t) m[i].right_side_bearing) - 0x80; | 
					
						
							|  |  |  | 		glyph->width = ((int16_t) m[i].character_width) - 0x80; | 
					
						
							|  |  |  | 		glyph->ascent = ((int16_t) m[i].character_ascent) - 0x80; | 
					
						
							|  |  |  | 		glyph->descent = ((int16_t) m[i].character_descent) - 0x80; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* computed stuff */ | 
					
						
							|  |  |  | 		glyph->height = glyph->ascent + glyph->descent; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		glyph->hotx = -glyph->left_bearing; | 
					
						
							|  |  |  | 		glyph->hoty = glyph->ascent; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | handle_metrics(void *metricbuf) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct metrics *metrics = metricbuf; | 
					
						
							|  |  |  | 	printf("metric format: %x\n", metrics->format); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((metrics->format & PCF_FORMAT_MASK) == PCF_DEFAULT_FORMAT) { | 
					
						
							|  |  |  | 		printf("todo...\n"); | 
					
						
							|  |  |  | 	} else if ((metrics->format & PCF_FORMAT_MASK) == | 
					
						
							|  |  |  | 		   PCF_COMPRESSED_METRICS) { | 
					
						
							|  |  |  | 		handle_compressed_metrics( | 
					
						
							|  |  |  | 		    metrics->compressed.count, | 
					
						
							|  |  |  | 		    &metrics->compressed.compressed_metrics[0]); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		printf("incompatible format\n"); | 
					
						
							|  |  |  | 		abort(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | handle_glyph_names(struct glyph_names *names) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	printf("glyph count %d\n", names->glyph_count); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (names->glyph_count != extracted_font.count) { | 
					
						
							|  |  |  | 		abort(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	printf("glyph names format %x\n", names->format); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void *names_start = ((void*) names) + sizeof(struct glyph_names) | 
					
						
							|  |  |  | 		+ (names->glyph_count + 1) * sizeof(int32_t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	for (i = 0; i < names->glyph_count; ++i) { | 
					
						
							|  |  |  | 		int32_t start = names->offsets[i]; | 
					
						
							|  |  |  | 		int32_t end = names->offsets[i+1]; | 
					
						
							|  |  |  | 		char *name = names_start + start; | 
					
						
							|  |  |  | 		extracted_font.glyphs[i].name = calloc(1, end - start + 1); | 
					
						
							|  |  |  | 		memcpy(extracted_font.glyphs[i].name, name, end - start); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | handle_bitmaps(struct bitmaps *bitmaps) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	printf("bitmaps count %d\n", bitmaps->glyph_count); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (bitmaps->glyph_count != extracted_font.count) { | 
					
						
							|  |  |  | 		abort(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	printf("format %x\n", bitmaps->format); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (bitmaps->format != 2) { | 
					
						
							|  |  |  | 		printf("format not yet supported\n"); | 
					
						
							|  |  |  | 		abort(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void *bitmaps_start = ((void*) bitmaps) + sizeof(struct bitmaps) | 
					
						
							|  |  |  | 		+ (bitmaps->glyph_count + 4) * sizeof(int32_t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	for (i = 0; i < bitmaps->glyph_count; ++i) { | 
					
						
							|  |  |  | 		int32_t offset = bitmaps->offsets[i]; | 
					
						
							|  |  |  | 		struct glyph *glyph = &extracted_font.glyphs[i]; | 
					
						
							|  |  |  | 		glyph->data_format = bitmaps->format; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		glyph->data = bitmaps_start + offset; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | handle_pcf(void *fontbuf) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct pcf_header *header = fontbuf; | 
					
						
							|  |  |  | 	printf("tablecount %d\n", header->table_count); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	for (i = 0; i < header->table_count; ++i) { | 
					
						
							|  |  |  | 		struct toc_entry *entry = &header->tables[i]; | 
					
						
							|  |  |  | 		printf("type: %d\n", entry->type); | 
					
						
							|  |  |  | 		if (entry->type == PCF_METRICS) { | 
					
						
							|  |  |  | 			handle_metrics(fontbuf + entry->offset); | 
					
						
							|  |  |  | 		} else if (entry->type == PCF_GLYPH_NAMES) { | 
					
						
							|  |  |  | 			handle_glyph_names(fontbuf + entry->offset); | 
					
						
							|  |  |  | 		} else if (entry->type == PCF_BITMAPS) { | 
					
						
							|  |  |  | 			handle_bitmaps(fontbuf + entry->offset); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char | 
					
						
							|  |  |  | get_glyph_pixel(struct glyph *glyph, int x, int y) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int absx = glyph->hotx + x; | 
					
						
							|  |  |  | 	int absy = glyph->hoty + y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (absx < 0 || absx >= glyph->width || | 
					
						
							|  |  |  | 	    absy < 0 || absy >= glyph->height) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int stride = (glyph->width + 31) / 32 * 4; | 
					
						
							|  |  |  | 	unsigned char block = glyph->data[absy * stride + (absx/8)]; | 
					
						
							|  |  |  | 	int idx = absx % 8; | 
					
						
							|  |  |  | 	return (block >> idx) & 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct { | 
					
						
							|  |  |  | 	uint32_t *data; | 
					
						
							|  |  |  | 	size_t capacity, size; | 
					
						
							|  |  |  | } data_buffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | init_data_buffer() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	data_buffer.data = malloc(sizeof(uint32_t) * 10); | 
					
						
							|  |  |  | 	data_buffer.capacity = 10; | 
					
						
							|  |  |  | 	data_buffer.size = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | add_pixel(uint32_t pixel) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (data_buffer.size == data_buffer.capacity) { | 
					
						
							|  |  |  | 		data_buffer.capacity *= 2; | 
					
						
							|  |  |  | 		data_buffer.data = | 
					
						
							|  |  |  | 			realloc(data_buffer.data, | 
					
						
							|  |  |  | 				sizeof(uint32_t) * data_buffer.capacity); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	data_buffer.data[data_buffer.size++] = pixel; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct reconstructed_glyph { | 
					
						
							|  |  |  | 	int32_t width, height; | 
					
						
							|  |  |  | 	int32_t hotspot_x, hotspot_y; | 
					
						
							|  |  |  | 	size_t offset; | 
					
						
							|  |  |  | 	char *name; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | reconstruct_glyph(struct glyph *cursor, struct glyph *mask, char *name, | 
					
						
							|  |  |  | 		  struct reconstructed_glyph *glyph) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int minx = min(-cursor->hotx, -mask->hotx); | 
					
						
							|  |  |  | 	int maxx = max(cursor->right_bearing, mask->right_bearing); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int miny = min(-cursor->hoty, -mask->hoty); | 
					
						
							|  |  |  | 	int maxy = max(cursor->height - cursor->hoty, | 
					
						
							|  |  |  | 		       mask->height - mask->hoty); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int width = maxx - minx; | 
					
						
							|  |  |  | 	int height = maxy - miny; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	glyph->name = strdup(name); | 
					
						
							|  |  |  | 	glyph->width = width; | 
					
						
							|  |  |  | 	glyph->height = height; | 
					
						
							|  |  |  | 	glyph->hotspot_x = -minx; | 
					
						
							|  |  |  | 	glyph->hotspot_y = -miny; | 
					
						
							|  |  |  | 	glyph->offset = data_buffer.size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int x, y; | 
					
						
							|  |  |  | 	for (y = miny; y < maxy; ++y) { | 
					
						
							|  |  |  | 		for (x = minx; x < maxx; ++x) { | 
					
						
							|  |  |  | 			char alpha = get_glyph_pixel(mask, x, y); | 
					
						
							|  |  |  | 			if (alpha) { | 
					
						
							|  |  |  | 				char color = get_glyph_pixel(cursor, x, y); | 
					
						
							|  |  |  | 				if (color) | 
					
						
							|  |  |  | 					add_pixel(0xff000000); | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					add_pixel(0xffffffff); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				add_pixel(0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-12 16:44:16 -07:00
										 |  |  | /* 
 | 
					
						
							|  |  |  |  * Originally from | 
					
						
							|  |  |  |  * http://cgit.freedesktop.org/xorg/lib/libXfont/tree/src/builtins/fonts.c
 | 
					
						
							|  |  |  |  * Changed to the MIT "Expat" style license for Wayland.. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-09-06 18:54:02 +02:00
										 |  |  | static const char cursor_licence[] = | 
					
						
							|  |  |  | 	"/*\n" | 
					
						
							| 
									
										
										
										
											2015-06-12 16:44:16 -07:00
										 |  |  | 	"* Copyright 1999 SuSE, Inc.\n" | 
					
						
							|  |  |  | 	"*\n" | 
					
						
							|  |  |  | 	"* Permission is hereby granted, free of charge, to any person obtaining\n" | 
					
						
							|  |  |  | 	"* a copy of this software and associated documentation files (the\n" | 
					
						
							|  |  |  | 	"* \"Software\"), to deal in the Software without restriction, including\n" | 
					
						
							|  |  |  | 	"* without limitation the rights to use, copy, modify, merge, publish,\n" | 
					
						
							|  |  |  | 	"* distribute, sublicense, and/or sell copies of the Software, and to\n" | 
					
						
							|  |  |  | 	"* permit persons to whom the Software is furnished to do so, subject to\n" | 
					
						
							|  |  |  | 	"* the following conditions:\n" | 
					
						
							|  |  |  | 	"*\n" | 
					
						
							|  |  |  | 	"* The above copyright notice and this permission notice (including the\n" | 
					
						
							|  |  |  | 	"* next paragraph) shall be included in all copies or substantial\n" | 
					
						
							|  |  |  | 	"* portions of the Software.\n" | 
					
						
							|  |  |  | 	"*\n" | 
					
						
							|  |  |  | 	"* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n" | 
					
						
							|  |  |  | 	"* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n" | 
					
						
							|  |  |  | 	"* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n" | 
					
						
							|  |  |  | 	"* NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n" | 
					
						
							|  |  |  | 	"* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n" | 
					
						
							|  |  |  | 	"* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n" | 
					
						
							|  |  |  | 	"* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n" | 
					
						
							|  |  |  | 	"* SOFTWARE.\n" | 
					
						
							|  |  |  | 	"*\n" | 
					
						
							|  |  |  | 	"* Author:  Keith Packard, SuSE, Inc.\n" | 
					
						
							|  |  |  | 	"*/\n"; | 
					
						
							| 
									
										
										
										
											2012-09-06 18:54:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | write_output_file(struct reconstructed_glyph *glyphs, int n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i, j, counter, size; | 
					
						
							| 
									
										
										
										
											2012-10-04 14:27:39 -07:00
										 |  |  | 	FILE *file = fopen("cursor-data.h", "w"); | 
					
						
							| 
									
										
										
										
											2012-09-06 18:54:02 +02:00
										 |  |  | 	uint32_t *data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fprintf(file, "%s\n", cursor_licence); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fprintf(file, "static uint32_t cursor_data[] = {\n\t"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	counter = 0; | 
					
						
							|  |  |  | 	for (i = 0; i < n; ++i) { | 
					
						
							|  |  |  | 		data = data_buffer.data + glyphs[i].offset; | 
					
						
							|  |  |  | 		size = glyphs[i].width * glyphs[i].height; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (j = 0; j < size; ++j) { | 
					
						
							|  |  |  | 			fprintf(file, "0x%08x, ", data[j]); | 
					
						
							|  |  |  | 			if (++counter % 6 == 0) | 
					
						
							|  |  |  | 				fprintf(file, "\n\t"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	fprintf(file, "\n};\n\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fprintf(file, | 
					
						
							|  |  |  | 		"static struct {\n" | 
					
						
							|  |  |  | 		"\tchar *name;\n" | 
					
						
							|  |  |  | 		"\tint width, height;\n" | 
					
						
							|  |  |  | 		"\tint hotspot_x, hotspot_y;\n" | 
					
						
							|  |  |  | 		"\tsize_t offset;\n" | 
					
						
							|  |  |  | 		"} cursor_metadata[] = {\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < n; ++i) | 
					
						
							|  |  |  | 		fprintf(file, "\t{ \"%s\", %d, %d, %d, %d, %zu },\n", | 
					
						
							|  |  |  | 			glyphs[i].name, | 
					
						
							|  |  |  | 			glyphs[i].width, glyphs[i].height, | 
					
						
							|  |  |  | 			glyphs[i].hotspot_x, glyphs[i].hotspot_y, | 
					
						
							|  |  |  | 			glyphs[i].offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fprintf(file, "};"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fclose(file); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct glyph * | 
					
						
							|  |  |  | find_mask_glyph(char *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const char mask[] = "_mask"; | 
					
						
							|  |  |  | 	const int masklen = strlen(mask); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int len = strlen(name); | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	for (i = 0; i < extracted_font.count; ++i) { | 
					
						
							|  |  |  | 		struct glyph *g = &extracted_font.glyphs[i]; | 
					
						
							|  |  |  | 		int l2 = strlen(g->name); | 
					
						
							|  |  |  | 		if ((l2 == len + masklen) && | 
					
						
							|  |  |  | 		    (memcmp(g->name, name, len) == 0) && | 
					
						
							|  |  |  | 		    (memcmp(g->name + len, mask, masklen) == 0)) { | 
					
						
							|  |  |  | 			return g; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | output_all_cursors() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i, j; | 
					
						
							|  |  |  | 	struct reconstructed_glyph *glyphs = | 
					
						
							|  |  |  | 		malloc(sizeof(struct reconstructed_glyph) * | 
					
						
							|  |  |  | 		       extracted_font.count/2); | 
					
						
							|  |  |  | 	j = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < extracted_font.count; ++i) { | 
					
						
							|  |  |  | 		struct glyph *g = &extracted_font.glyphs[i]; | 
					
						
							|  |  |  | 		if (strstr(g->name, "_mask")) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		struct glyph *mask = find_mask_glyph(g->name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		reconstruct_glyph(g, mask, g->name, &glyphs[j]); | 
					
						
							|  |  |  | 		j++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	write_output_file(glyphs, extracted_font.count/2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | find_cursor_and_mask(const char *name, | 
					
						
							|  |  |  | 		     struct glyph **cursor, | 
					
						
							|  |  |  | 		     struct glyph **mask) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	char mask_name[100]; | 
					
						
							|  |  |  | 	sprintf(mask_name, "%s_mask", name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*cursor = *mask = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < extracted_font.count && (!*mask || !*cursor); ++i) { | 
					
						
							|  |  |  | 		struct glyph *g = &extracted_font.glyphs[i]; | 
					
						
							|  |  |  | 		if (!strcmp(name, g->name)) | 
					
						
							|  |  |  | 			*cursor = g; | 
					
						
							|  |  |  | 		else if (!strcmp(mask_name, g->name)) | 
					
						
							|  |  |  | 			*mask = g; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct { | 
					
						
							|  |  |  | 	char *target_name, *source_name; | 
					
						
							|  |  |  | } interesting_cursors[] = { | 
					
						
							|  |  |  | 	{ "bottom_left_corner", "bottom_left_corner" }, | 
					
						
							|  |  |  | 	{ "bottom_right_corner", "bottom_right_corner" }, | 
					
						
							|  |  |  | 	{ "bottom_side", "bottom_side" }, | 
					
						
							|  |  |  | 	{ "grabbing", "fleur" }, | 
					
						
							|  |  |  | 	{ "left_ptr", "left_ptr" }, | 
					
						
							|  |  |  | 	{ "left_side", "left_side" }, | 
					
						
							|  |  |  | 	{ "right_side", "right_side" }, | 
					
						
							|  |  |  | 	{ "top_left_corner", "top_left_corner" }, | 
					
						
							|  |  |  | 	{ "top_right_corner", "top_right_corner" }, | 
					
						
							|  |  |  | 	{ "top_side", "top_side" }, | 
					
						
							|  |  |  | 	{ "xterm", "xterm" }, | 
					
						
							|  |  |  | 	{ "hand1", "hand1" }, | 
					
						
							|  |  |  | 	{ "watch", "watch" } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | output_interesting_cursors() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	int n = sizeof(interesting_cursors) / sizeof(interesting_cursors[0]); | 
					
						
							|  |  |  | 	struct reconstructed_glyph *glyphs = | 
					
						
							|  |  |  | 		malloc(n * sizeof(*glyphs)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-27 11:22:40 +08:00
										 |  |  | 	if (!glyphs) { | 
					
						
							|  |  |  | 		printf("reconstructed_glyph malloc failed\n"); | 
					
						
							|  |  |  | 		abort(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-06 18:54:02 +02:00
										 |  |  | 	for (i = 0; i < n; ++i) { | 
					
						
							|  |  |  | 		struct glyph *cursor, *mask; | 
					
						
							|  |  |  | 		find_cursor_and_mask(interesting_cursors[i].source_name, | 
					
						
							|  |  |  | 				     &cursor, &mask); | 
					
						
							|  |  |  | 		if (!cursor) { | 
					
						
							|  |  |  | 			printf("no cursor for %s\n", | 
					
						
							|  |  |  | 			       interesting_cursors[i].source_name); | 
					
						
							|  |  |  | 			abort(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!mask) { | 
					
						
							|  |  |  | 			printf("no mask for %s\n", | 
					
						
							|  |  |  | 			       interesting_cursors[i].source_name); | 
					
						
							|  |  |  | 			abort(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		reconstruct_glyph(cursor, mask, | 
					
						
							|  |  |  | 				  interesting_cursors[i].target_name, | 
					
						
							|  |  |  | 				  &glyphs[i]); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	write_output_file(glyphs, n); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int main() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const char filename[] = "cursor.pcf"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int fd = open(filename, O_RDONLY); | 
					
						
							|  |  |  | 	struct stat filestat; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fstat(fd, &filestat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void *fontbuf = mmap(NULL, filestat.st_size, PROT_READ, | 
					
						
							|  |  |  | 			     MAP_PRIVATE, fd, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	handle_pcf(fontbuf); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	init_data_buffer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//output_all_cursors();
 | 
					
						
							|  |  |  | 	output_interesting_cursors(); | 
					
						
							|  |  |  | } |