commit fed8a9c
Michael Forney
·
2014-01-18 03:15:55 +0000 UTC
parent 7f585a1
Add fonts from the xserver
5 files changed,
+534,
-2
+2,
-0
1@@ -12,4 +12,6 @@ protocol/xserver-server-protocol.h
2 /libswc/libswc.a
3 /libswc/libswc.so*
4 /launch/swc-launch
5+/cursor/convert_font
6+/cursor/cursor_data.h
7
M
Makefile
+2,
-2
1@@ -8,7 +8,7 @@ VERSION_MINOR := 0
2 VERSION := $(VERSION_MAJOR).$(VERSION_MINOR)
3
4 TARGETS := swc.pc
5-SUBDIRS := launch libswc protocol
6+SUBDIRS := launch libswc protocol cursor
7 CLEAN_FILES := $(TARGETS)
8
9 include config.mk
10@@ -27,7 +27,7 @@ define check_deps
11 @$(PKG_CONFIG) --exists --print-errors $2
12 endef
13
14-FINAL_CFLAGS = $(CFLAGS) -fvisibility=hidden
15+FINAL_CFLAGS = $(CFLAGS) -fvisibility=hidden -std=gnu99
16 FINAL_CPPFLAGS = $(CPPFLAGS)
17
18 # Warning/error flags
+514,
-0
1@@ -0,0 +1,514 @@
2+/*
3+ * Copyright © 2012 Philipp Brüschweiler
4+ *
5+ * Permission to use, copy, modify, distribute, and sell this software and its
6+ * documentation for any purpose is hereby granted without fee, provided that
7+ * the above copyright notice appear in all copies and that both that copyright
8+ * notice and this permission notice appear in supporting documentation, and
9+ * that the name of the copyright holders not be used in advertising or
10+ * publicity pertaining to distribution of the software without specific,
11+ * written prior permission. The copyright holders make no representations
12+ * about the suitability of this software for any purpose. It is provided "as
13+ * is" without express or implied warranty.
14+ *
15+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21+ * OF THIS SOFTWARE.
22+ */
23+
24+/*
25+ * This is a small, hacky tool to extract cursors from a .pcf file.
26+ * The information about the file format has been gathered from
27+ * http://fontforge.org/pcf-format.html
28+ */
29+
30+#include <assert.h>
31+#include <fcntl.h>
32+#include <stdint.h>
33+#include <stdio.h>
34+#include <stdlib.h>
35+#include <string.h>
36+#include <sys/mman.h>
37+#include <sys/types.h>
38+#include <sys/stat.h>
39+
40+#define min(a, b) ((a) < (b) ? (a) : (b))
41+#define max(a, b) ((a) > (b) ? (a) : (b))
42+
43+struct glyph {
44+ char *name;
45+ int16_t left_bearing, right_bearing, ascent, descent;
46+
47+ int16_t width, height;
48+ int16_t hotx, hoty;
49+
50+ int32_t data_format;
51+ char *data;
52+};
53+
54+static struct {
55+ int count;
56+ struct glyph *glyphs;
57+} extracted_font = {0, NULL};
58+
59+#define PCF_PROPERTIES (1<<0)
60+#define PCF_ACCELERATORS (1<<1)
61+#define PCF_METRICS (1<<2)
62+#define PCF_BITMAPS (1<<3)
63+#define PCF_INK_METRICS (1<<4)
64+#define PCF_BDF_ENCODINGS (1<<5)
65+#define PCF_SWIDTHS (1<<6)
66+#define PCF_GLYPH_NAMES (1<<7)
67+#define PCF_BDF_ACCELERATORS (1<<8)
68+
69+#define PCF_DEFAULT_FORMAT 0x00000000
70+#define PCF_INKBOUNDS 0x00000200
71+#define PCF_ACCEL_W_INKBOUNDS 0x00000100
72+#define PCF_COMPRESSED_METRICS 0x00000100
73+
74+#define PCF_FORMAT_MASK 0xffffff00
75+
76+struct pcf_header {
77+ char header[4];
78+ int32_t table_count;
79+ struct toc_entry {
80+ int32_t type;
81+ int32_t format;
82+ int32_t size;
83+ int32_t offset;
84+ } tables[0];
85+};
86+
87+struct compressed_metrics {
88+ uint8_t left_sided_bearing;
89+ uint8_t right_side_bearing;
90+ uint8_t character_width;
91+ uint8_t character_ascent;
92+ uint8_t character_descent;
93+};
94+
95+struct uncompressed_metrics {
96+ int16_t left_sided_bearing;
97+ int16_t right_side_bearing;
98+ int16_t character_width;
99+ int16_t character_ascent;
100+ int16_t character_descent;
101+ uint16_t character_attributes;
102+};
103+
104+struct metrics {
105+ int32_t format;
106+ union {
107+ struct {
108+ int16_t count;
109+ struct compressed_metrics compressed_metrics[0];
110+ } compressed;
111+ struct {
112+ int32_t count;
113+ struct uncompressed_metrics uncompressed_metrics[0];
114+ } uncompressed;
115+ };
116+};
117+
118+struct glyph_names {
119+ int32_t format;
120+ int32_t glyph_count;
121+ int32_t offsets[0];
122+};
123+
124+struct bitmaps {
125+ int32_t format;
126+ int32_t glyph_count;
127+ int32_t offsets[0];
128+};
129+
130+static void
131+handle_compressed_metrics(int32_t count, struct compressed_metrics *m)
132+{
133+ fprintf(stderr, "metrics count: %d\n", count);
134+ extracted_font.count = count;
135+ extracted_font.glyphs = calloc(count, sizeof(struct glyph));
136+
137+ int i;
138+ for (i = 0; i < count; ++i) {
139+ struct glyph *glyph = &extracted_font.glyphs[i];
140+ glyph->left_bearing =
141+ ((int16_t) m[i].left_sided_bearing) - 0x80;
142+ glyph->right_bearing =
143+ ((int16_t) m[i].right_side_bearing) - 0x80;
144+ glyph->width = ((int16_t) m[i].character_width) - 0x80;
145+ glyph->ascent = ((int16_t) m[i].character_ascent) - 0x80;
146+ glyph->descent = ((int16_t) m[i].character_descent) - 0x80;
147+
148+ /* computed stuff */
149+ glyph->height = glyph->ascent + glyph->descent;
150+
151+ glyph->hotx = -glyph->left_bearing;
152+ glyph->hoty = glyph->ascent;
153+ }
154+}
155+
156+static void
157+handle_metrics(void *metricbuf)
158+{
159+ struct metrics *metrics = metricbuf;
160+ fprintf(stderr, "metric format: %x\n", metrics->format);
161+
162+ if ((metrics->format & PCF_FORMAT_MASK) == PCF_DEFAULT_FORMAT) {
163+ fprintf(stderr, "todo...\n");
164+ } else if ((metrics->format & PCF_FORMAT_MASK) ==
165+ PCF_COMPRESSED_METRICS) {
166+ handle_compressed_metrics(
167+ metrics->compressed.count,
168+ &metrics->compressed.compressed_metrics[0]);
169+ } else {
170+ fprintf(stderr, "incompatible format\n");
171+ abort();
172+ }
173+}
174+
175+static void
176+handle_glyph_names(struct glyph_names *names)
177+{
178+ fprintf(stderr, "glyph count %d\n", names->glyph_count);
179+
180+ if (names->glyph_count != extracted_font.count) {
181+ abort();
182+ }
183+
184+ fprintf(stderr, "glyph names format %x\n", names->format);
185+
186+ char *names_start = ((char *) names) + sizeof(struct glyph_names)
187+ + (names->glyph_count + 1) * sizeof(int32_t);
188+
189+ int i;
190+ for (i = 0; i < names->glyph_count; ++i) {
191+ int32_t start = names->offsets[i];
192+ int32_t end = names->offsets[i+1];
193+ char *name = names_start + start;
194+ extracted_font.glyphs[i].name = calloc(1, end - start + 1);
195+ memcpy(extracted_font.glyphs[i].name, name, end - start);
196+ }
197+}
198+
199+static void
200+handle_bitmaps(struct bitmaps *bitmaps)
201+{
202+ fprintf(stderr, "bitmaps count %d\n", bitmaps->glyph_count);
203+
204+ if (bitmaps->glyph_count != extracted_font.count) {
205+ abort();
206+ }
207+
208+ fprintf(stderr, "format %x\n", bitmaps->format);
209+
210+ if (bitmaps->format != 2) {
211+ fprintf(stderr, "format not yet supported\n");
212+ abort();
213+ }
214+
215+ char *bitmaps_start = ((char*) bitmaps) + sizeof(struct bitmaps)
216+ + (bitmaps->glyph_count + 4) * sizeof(int32_t);
217+
218+ for (unsigned i = 0; i < bitmaps->glyph_count; ++i) {
219+ int32_t offset = bitmaps->offsets[i];
220+ struct glyph *glyph = &extracted_font.glyphs[i];
221+ glyph->data_format = bitmaps->format;
222+
223+ glyph->data = bitmaps_start + offset;
224+ }
225+}
226+
227+static void
228+handle_pcf(void *fontbuf)
229+{
230+ struct pcf_header *header = fontbuf;
231+ fprintf(stderr, "tablecount %d\n", header->table_count);
232+
233+ for (unsigned i = 0; i < header->table_count; ++i) {
234+ struct toc_entry *entry = &header->tables[i];
235+ fprintf(stderr, "type: %d\n", entry->type);
236+ if (entry->type == PCF_METRICS) {
237+ handle_metrics((void *)((uintptr_t) fontbuf + entry->offset));
238+ } else if (entry->type == PCF_GLYPH_NAMES) {
239+ handle_glyph_names((void *)((uintptr_t) fontbuf + entry->offset));
240+ } else if (entry->type == PCF_BITMAPS) {
241+ handle_bitmaps((void *)((uintptr_t) fontbuf + entry->offset));
242+ }
243+ }
244+}
245+
246+static char
247+get_glyph_pixel(struct glyph *glyph, int x, int y)
248+{
249+ int absx = glyph->hotx + x;
250+ int absy = glyph->hoty + y;
251+
252+ if (absx < 0 || absx >= glyph->width ||
253+ absy < 0 || absy >= glyph->height)
254+ return 0;
255+
256+ int stride = (glyph->width + 31) / 32 * 4;
257+ unsigned char block = glyph->data[absy * stride + (absx/8)];
258+ int idx = absx % 8;
259+ return (block >> idx) & 1;
260+}
261+
262+static struct {
263+ uint32_t *data;
264+ size_t capacity, size;
265+} data_buffer;
266+
267+static void
268+init_data_buffer()
269+{
270+ data_buffer.data = malloc(sizeof(uint32_t) * 10);
271+ data_buffer.capacity = 10;
272+ data_buffer.size = 0;
273+}
274+
275+static void
276+add_pixel(uint32_t pixel)
277+{
278+ if (data_buffer.size == data_buffer.capacity) {
279+ data_buffer.capacity *= 2;
280+ data_buffer.data =
281+ realloc(data_buffer.data,
282+ sizeof(uint32_t) * data_buffer.capacity);
283+ }
284+ data_buffer.data[data_buffer.size++] = pixel;
285+}
286+
287+struct reconstructed_glyph {
288+ int32_t width, height;
289+ int32_t hotspot_x, hotspot_y;
290+ size_t offset;
291+ char *name;
292+};
293+
294+static void
295+reconstruct_glyph(struct glyph *cursor, struct glyph *mask, char *name,
296+ struct reconstructed_glyph *glyph)
297+{
298+ int minx = min(-cursor->hotx, -mask->hotx);
299+ int maxx = max(cursor->right_bearing, mask->right_bearing);
300+
301+ int miny = min(-cursor->hoty, -mask->hoty);
302+ int maxy = max(cursor->height - cursor->hoty,
303+ mask->height - mask->hoty);
304+
305+ int width = maxx - minx;
306+ int height = maxy - miny;
307+
308+ glyph->name = strdup(name);
309+ glyph->width = width;
310+ glyph->height = height;
311+ glyph->hotspot_x = -minx;
312+ glyph->hotspot_y = -miny;
313+ glyph->offset = data_buffer.size;
314+
315+ int x, y;
316+ for (y = miny; y < maxy; ++y) {
317+ for (x = minx; x < maxx; ++x) {
318+ char alpha = get_glyph_pixel(mask, x, y);
319+ if (alpha) {
320+ char color = get_glyph_pixel(cursor, x, y);
321+ if (color)
322+ add_pixel(0xff000000);
323+ else
324+ add_pixel(0xffffffff);
325+ } else {
326+ add_pixel(0);
327+ }
328+ }
329+ }
330+}
331+
332+/* From http://cgit.freedesktop.org/xorg/lib/libXfont/tree/src/builtins/fonts.c */
333+static const char cursor_licence[] =
334+ "/*\n"
335+ "* Copyright 1999 SuSE, Inc.\n"
336+ "*\n"
337+ "* Permission to use, copy, modify, distribute, and sell this software and its\n"
338+ "* documentation for any purpose is hereby granted without fee, provided that\n"
339+ "* the above copyright notice appear in all copies and that both that\n"
340+ "* copyright notice and this permission notice appear in supporting\n"
341+ "* documentation, and that the name of SuSE not be used in advertising or\n"
342+ "* publicity pertaining to distribution of the software without specific,\n"
343+ "* written prior permission. SuSE makes no representations about the\n"
344+ "* suitability of this software for any purpose. It is provided \"as is\"\n"
345+ "* without express or implied warranty.\n"
346+ "*\n"
347+ "* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL\n"
348+ "* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE\n"
349+ "* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n"
350+ "* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION\n"
351+ "* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN\n"
352+ "* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n"
353+ "*\n"
354+ "* Author: Keith Packard, SuSE, Inc.\n"
355+ "*/\n";
356+
357+static void
358+write_output_file(FILE *file, struct reconstructed_glyph *glyphs, int n)
359+{
360+ int i, j, counter, size;
361+ uint32_t *data;
362+
363+ fprintf(file, "%s\n", cursor_licence);
364+
365+ fprintf(file, "static uint32_t cursor_data[] = {\n\t");
366+
367+ counter = 0;
368+ for (i = 0; i < n; ++i) {
369+ data = data_buffer.data + glyphs[i].offset;
370+ size = glyphs[i].width * glyphs[i].height;
371+
372+ for (j = 0; j < size; ++j) {
373+ fprintf(file, "0x%08x, ", data[j]);
374+ if (++counter % 6 == 0)
375+ fprintf(file, "\n\t");
376+ }
377+ }
378+ fprintf(file, "\n};\n\n");
379+
380+ fputs("enum cursor_type {\n", file);
381+
382+ for (i = 0; i < n; ++i)
383+ fprintf(file, "\tcursor_%s,\n", glyphs[i].name);
384+
385+ fputs("};\n\n", file);
386+
387+ fprintf(file,
388+ "static struct cursor {\n"
389+ "\tint width, height;\n"
390+ "\tint hotspot_x, hotspot_y;\n"
391+ "\tsize_t offset;\n"
392+ "} cursor_metadata[] = {\n");
393+
394+ for (i = 0; i < n; ++i)
395+ fprintf(file, "\t{ %d, %d, %d, %d, %zu }, /* %s */\n",
396+ glyphs[i].width, glyphs[i].height,
397+ glyphs[i].hotspot_x, glyphs[i].hotspot_y,
398+ glyphs[i].offset, glyphs[i].name);
399+
400+ fputs("};\n", file);
401+}
402+
403+struct glyph *
404+find_mask_glyph(char *name)
405+{
406+ const char mask[] = "_mask";
407+ const int masklen = strlen(mask);
408+
409+ int len = strlen(name);
410+ int i;
411+ for (i = 0; i < extracted_font.count; ++i) {
412+ struct glyph *g = &extracted_font.glyphs[i];
413+ int l2 = strlen(g->name);
414+ if ((l2 == len + masklen) &&
415+ (memcmp(g->name, name, len) == 0) &&
416+ (memcmp(g->name + len, mask, masklen) == 0)) {
417+ return g;
418+ }
419+ }
420+ return NULL;
421+}
422+
423+static void
424+find_cursor_and_mask(const char *name,
425+ struct glyph **cursor,
426+ struct glyph **mask)
427+{
428+ int i;
429+ char mask_name[100];
430+ sprintf(mask_name, "%s_mask", name);
431+
432+ *cursor = *mask = NULL;
433+
434+ for (i = 0; i < extracted_font.count && (!*mask || !*cursor); ++i) {
435+ struct glyph *g = &extracted_font.glyphs[i];
436+ if (!strcmp(name, g->name))
437+ *cursor = g;
438+ else if (!strcmp(mask_name, g->name))
439+ *mask = g;
440+ }
441+}
442+
443+static struct {
444+ char *target_name, *source_name;
445+} interesting_cursors[] = {
446+ { "bottom_left_corner", "bottom_left_corner" },
447+ { "bottom_right_corner", "bottom_right_corner" },
448+ { "bottom_side", "bottom_side" },
449+ { "grabbing", "fleur" },
450+ { "left_ptr", "left_ptr" },
451+ { "left_side", "left_side" },
452+ { "right_side", "right_side" },
453+ { "top_left_corner", "top_left_corner" },
454+ { "top_right_corner", "top_right_corner" },
455+ { "top_side", "top_side" },
456+ { "xterm", "xterm" },
457+ { "hand1", "hand1" },
458+ { "watch", "watch" }
459+};
460+
461+static void
462+output_interesting_cursors(FILE *file)
463+{
464+ int i;
465+ int n = sizeof(interesting_cursors) / sizeof(interesting_cursors[0]);
466+ struct reconstructed_glyph *glyphs =
467+ malloc(n * sizeof(*glyphs));
468+
469+ for (i = 0; i < n; ++i) {
470+ struct glyph *cursor, *mask;
471+ find_cursor_and_mask(interesting_cursors[i].source_name,
472+ &cursor, &mask);
473+ if (!cursor) {
474+ fprintf(stderr, "no cursor for %s\n",
475+ interesting_cursors[i].source_name);
476+ abort();
477+ }
478+ if (!mask) {
479+ fprintf(stderr, "no mask for %s\n",
480+ interesting_cursors[i].source_name);
481+ abort();
482+ }
483+ reconstruct_glyph(cursor, mask,
484+ interesting_cursors[i].target_name,
485+ &glyphs[i]);
486+ }
487+
488+ write_output_file(file, glyphs, n);
489+}
490+
491+int main(int argc, char *argv[])
492+{
493+ if (argc != 3) {
494+ fprintf(stderr, "Usage: %s input.pcf output.h\n", argv[0]);
495+ return EXIT_FAILURE;
496+ }
497+
498+ int fd = open(argv[1], O_RDONLY);
499+ struct stat filestat;
500+
501+ fstat(fd, &filestat);
502+
503+ void *fontbuf = mmap(NULL, filestat.st_size, PROT_READ,
504+ MAP_PRIVATE, fd, 0);
505+
506+ handle_pcf(fontbuf);
507+
508+ init_data_buffer();
509+
510+ FILE *file = fopen(argv[2], "w");
511+ output_interesting_cursors(file);
512+ fclose(file);
513+
514+ return EXIT_SUCCESS;
515+}
+0,
-0
+16,
-0
1@@ -0,0 +1,16 @@
2+# swc: cursor/local.mk
3+
4+dir := cursor
5+
6+$(dir)_TARGETS := $(dir)/convert_font $(dir)/cursor_data.h
7+
8+$(dir)/convert_font: $(dir)/convert_font.o
9+ $(link)
10+
11+$(dir)/cursor_data.h: $(dir)/cursor.pcf $(dir)/convert_font
12+ $(call quiet,GEN,$(dir)/convert_font) $< $@ 2> /dev/null
13+
14+CLEAN_FILES += $(dir)/convert_font.o
15+
16+include common.mk
17+