[PATCH 2/2] cursor: add cursor.pcf and extraction program

Philipp Brüschweiler blei42 at gmail.com
Thu Sep 6 07:20:16 PDT 2012


---
 cursor/convert_font.c | 450 ++++++++++++++++++++++++++++++++++++++++++++++++++
 cursor/cursor.pcf     | Bin 0 -> 14208 bytes
 2 Dateien geändert, 450 Zeilen hinzugefügt(+)
 create mode 100644 cursor/convert_font.c
 create mode 100644 cursor/cursor.pcf

diff --git a/cursor/convert_font.c b/cursor/convert_font.c
new file mode 100644
index 0000000..082a02f
--- /dev/null
+++ b/cursor/convert_font.c
@@ -0,0 +1,450 @@
+/*
+ * Copyright © 2012 Philipp Brüschweiler
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * 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 <assert.h>
+#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>
+
+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;
+}
+
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+/* From http://cgit.freedesktop.org/xorg/lib/libXfont/tree/src/builtins/fonts.c */
+static const char cursor_licence[] =
+	"/*\n"
+ 	"* Copyright 1999 SuSE, Inc.\n"
+ 	"*\n"
+ 	"* Permission to use, copy, modify, distribute, and sell this software and its\n"
+ 	"* documentation for any purpose is hereby granted without fee, provided that\n"
+ 	"* the above copyright notice appear in all copies and that both that\n"
+ 	"* copyright notice and this permission notice appear in supporting\n"
+ 	"* documentation, and that the name of SuSE not be used in advertising or\n"
+ 	"* publicity pertaining to distribution of the software without specific,\n"
+ 	"* written prior permission.  SuSE makes no representations about the\n"
+ 	"* suitability of this software for any purpose.  It is provided \"as is\"\n"
+ 	"* without express or implied warranty.\n"
+ 	"*\n"
+ 	"* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL\n"
+ 	"* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE\n"
+ 	"* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n"
+ 	"* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION\n"
+ 	"* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN\n"
+ 	"* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n"
+ 	"*\n"
+ 	"* Author:  Keith Packard, SuSE, Inc.\n"
+ 	"*/\n";
+
+static void
+save_xpm(struct glyph *cursor, struct glyph *mask, char *filename)
+{
+
+	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;
+
+	FILE *file = fopen(filename, "w");
+
+	fprintf(file, "%s\n", cursor_licence);
+	fprintf(file, "/* XPM */\nstatic char *%s[] = {\n",
+		cursor->name);
+	fprintf(file, "\"%d %d 3 1\",\n", width, height);
+	fprintf(file, "\"_ c None\",\n\"X c #000000\",\n\"O c #ffffff\",\n");
+
+	int x, y;
+	for (y = miny; y < maxy; ++y) {
+		fprintf(file, "\"");
+		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)
+					fprintf(file, "X");
+				else
+					fprintf(file, "O");
+			} else {
+				fprintf(file, "_");
+			}
+		}
+		fprintf(file, "\",\n");
+	}
+
+	fprintf(file, "};\n\n");
+
+	// also encode the hotspot
+	fprintf(file, "static struct hotspot %s_hotspot = { %d, %d };\n",
+		cursor->name, -minx, -miny);
+
+	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;
+	char buf[200];
+
+	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);
+
+		sprintf(buf, "cursors/%s.xpm", g->name);
+		save_xpm(g, mask, buf);
+	}
+}
+
+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 void
+output_interesting_cursors()
+{
+	const char *names[] = {
+		"bottom_left_corner",
+		"bottom_right_corner",
+		"bottom_side",
+		"fleur", // Used as grabbing cursor
+		"left_ptr",
+		"left_side",
+		"right_side",
+		"top_left_corner",
+		"top_right_corner",
+		"top_side",
+		"xterm",
+		"hand1",
+		"watch"
+	};
+
+	int i;
+	char buf[200];
+
+	for (i = 0; i < sizeof(names)/sizeof(names[0]); ++i) {
+		struct glyph *cursor, *mask;
+		find_cursor_and_mask(names[i], &cursor, &mask);
+		if (!cursor) {
+			printf("no cursor for %s\n", names[i]);
+			abort();
+		}
+		if (!mask) {
+			printf("no mask for %s\n", names[i]);
+			abort();
+		}
+		sprintf(buf, "%s.xpm", names[i]);
+		save_xpm(cursor, mask, buf);
+	}
+}
+
+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);
+
+	//output_all_cursors();
+	output_interesting_cursors();
+}
diff --git a/cursor/cursor.pcf b/cursor/cursor.pcf
new file mode 100644
index 0000000000000000000000000000000000000000..812fcc54fdf1ad92f7016e69fe6c2dd9f7437b62
GIT binary patch
literal 14208
zcmeI3dvILUeaC;o#u%`JjCqK}Sn{L95J=1;AizN~m||0c4VVB4Ag!gfts+_SO0s1m
ztkrYZFWD-zB at 8KU$aEOUbUc$x$7MWa6H;hWQka$uq+!Z>pv2QqB%W4^(Dw5^_nzIW
zMRr}<{Fj~i+;h(F{Lbrle&^hC at 0Ci{*0oGGvl2J~-h^}*SGpb=$($+~;q)nHFDVRl
zUR!APDw!2wdKq~?Jm0K3Ot(<U=mloUFn#!Bv-KB|K+o5|>WUyvmiv{QLO>a_%hCEO
zVaZiomP(?m<%-+~w<&Tn)cQ!1A~}AW6q%`uSvOp_a at Ae8uDD_OYFoWN-Wso%zpimh
z%lg*&6|qFTqJ2YrLtT5*ns_2!Z>v_WxOsKWZ7aTcz5U_Jn^#+1d!n^DVRu~bO5b|@
zZ7XlOef5f!H(McEb7wShm)%*jJkY-7_NB{e?pU#Gwd=CR>wl$0W`X+pZcgLMag|w0
zk)Ou(v;8zjkJ#4q&_H_2_Mz1F*6yL?V4`QJd(Q*?L)*JM2Zna^6k=rb_H*g$-<nd1
zG$oRQL%X}X_6!a7P<D4Wxr06A?(QacuxCq(S~}9y(vccUr-`N0RGJ*TKSdklrczEu
z4|;cR-Ohz#+f($#T~a}>)HN3?T(+z6Aou?Mq5l4 at 149D?T>4W~I*>+|N|8*b6O3q&
zE_?H_Jq5kO$P0a82tB(s)ZN<#DdsM1s=!^6d+2>~FTJO`=>d0fLvR<@I5F&!Mz3o-
zdRS;6g at sb-<PLh(wbL8InFQJPZe%-pHg^--)I*HM`**raP_s<expSy{cjqqZ+tfX@
zr at Os}3pUu*hjDiGVblJ8Y&tN|$;i|9YvfxrmmQi*W at aEoeW^5Uq*AmIPKE11!3Nl+
zYmg?Bdmrc<+LNRz*G6w24fXYR?;YyxW8{7P8<WH~b`wLdYcG1PL at MnX-=t)_E(M!z
zW#rr4Wi!?tqz65Nn!)YP>xd0#&Y7~*USjFJ*b3VZVl`*KFjnwRJS?dSoDU^;(C6-*
z^d%Ye1)C;!VAJlM^q^-Kxjlo7Jh_8*yLZy@?J0M8pl?Si)!Dxzoz_}=BwRw3gdMOS
zMxcx}vK(4qA7tQ7m_wnv;URb#X0X at Y1by%mcpK)h*WC?|!pm^RiRi#CcmZZiBMrOY
zA7J`PX3HQ62Vo2<**rU7AG`#{##ad~upi!r3)$$_!}s82m~krgKpz~0F{qqDJ#YX<
zp_2Ws1NOrREczTfBkY4Ll$~aFC+vlnU at DtTHFUrM7==nUrCQhv2jDO)I-S126L1(R
zW}^f9APW^|kcKoIfDhoZGr4cT_aO^&&N5pK55dcD#@W~jc0mTL%xnpC!ozS7UWG9z
zJBK{zfCKOWEdD(9g8gt97JY#}!V_>97R at 0IPrz$%#<|Qn^ua+GgUjZcwZZq{ZCF^&
z{SJ1)K^TK270BQrcmZb2qa4)3_ux&KGvDk7*zU{N>Tco(mYJPYX?EHYv+`@qu2Egs
zdz85!!H0z6k||F*(sgA<NROITjhS_gn~is&SA{-$Bj^joB~zYsq^mNgQPvg%bs0Jt
zkiOc<&|Vf=XuDE=Tw?Y)K;-VjmL)<RMtw=@&BAC^(2neo1=lupbyDaWC})k}R_<(&
zBh*h}SrOkPtu9HPqwQikkc)Bp<6%fnrZOt4Iuwr*ZBxT8u0v^2+ at 8`&<XOU5tWkI8
zRmH4l8AJJ5qME1QGEU{^DJL!&c{j{qO;W~_Bky{AKZ;~NU!lsp{y>4(@WWhJ0iPF@
zNyp0-(zIg%d&dImTtJ@}V7teW*TEaik=Id}s|rBO$--<HV+~gVeHmr~hZ)Z>io at u6
zq?aFaE{HqdqU_X*+1H>HDxeyYFa};np>Nl1x+AQeBlsOuLJMRe17i`STik9n)lP=&
zxty`DV(i&ahrncWp?!TaUSR)_O-C8z2xFHYNH1!0#WU1(Ed2N~Dt`=$$D_Jw&ORYL
zvD)mz8nZK3nf>Apv)fn0?Zn|s;vXVAk-SgPDM8ouF-Q1+U@>hAzdpu at 3%~X*Wh at tC
zSFh*85p={Tofl*1iE(Twa at f;z1i$k7KFq2ddfJcX&Smew|Fq{tkxY4hzf_qlWk$=9
zRnbmYfZy}9?|CHi`O;Mxl~rADG3T={HT&s8vn?=dKI;U39Y^P9tXa>0aIgBu%Yyyb
z&#!cjTxs^J&1V1E#9TD9FRV3tzm at UQ&Tqb2;NvTZx0}7#NnTfg{7m=SX|<g5?=*Yw
z2G(bFzzKxn5#--s&R>CV-4)0rcjKV^7=0Me1r*QyvE(XWjSVNGi~96aI9a}AS{ua_
zx36 at uj!$1ZkNxl#vm4Ln{(mO-WX>(CI43>BeMa>wR9bT7OHcYLx0d;8`jy%J*n1Op
zZREaQ^9lDm$|UKxLZu~FzVxK8a>_p%8t>8aB+t;V$%u}7vV1SArhF}S)3}y%mRmL}
z7*AIhmGe`m at ky?H=}BMZvV_``<TKi%{t3T(ej|QFpVe=LN=rW39 at atqejOLz_q<#>
zTECO6Tfcr4`h4jsUBdk)N{qCK$`p5XR1t>w_5Ex59L3AMp2EfSP5omj+uzWx_9Drm
zNTxjLNLP6y;P<5By-0bYcx>9cR7QF32D6xO36wMc;LlD;=A#-a&@YAQl$i=_kw(De
zfjY7czhVqJD~-aqYzSG(YEBPO_E8w5Pzs0!<*SJlwe1d8oZ*vGX&Wj~DFw`HBtPBu
zHRy(ItNkSHX4E$48 at +?6q|6-9d5x~Pwq=hYD*QG+IFt2v5}AHZ6_-qT(uvOL`>ZeR
zb5*qWI_(aBEkJR}lqVfOukSL at k7=}=XOxqv>m1rgt?*OgJjS(<GXiytQhsCs`!i*Z
z&_{PaN2iKG<gil?b>Sm3#u*#VFotjxMur*p^Nb&rEOyp8PVt}6_H$(vs|rwDGUZ7}
zx{7C{Pup3L4;((5wRSaSs5^>e%9D<CT{+6yT)=)MFL0k=4rRM8#$E-}Gzp}2AJlwC
z=^*V4L;t2k+Y0;Z`>k-ioI0onlQ<Z at TMr85pR<|sJJ?rd<1GI|SiU5%QR$ns341>P
zh2*EPK_4CIq)wIpnDR#$ht9c2gxc>4#;&v4h{%QEuY-P!QC8*M0iE$DDJOe)`)j=a
z71sF)aoKx>cFw2B0^pI*Fi+s5)Z=_N)Kgilqv-neXYd?#bWyAdWOnUwC5(L=<C at O6
z^m5aM+~cRuXPGUf?h4iv&#_7J4BKcishry{X-n-m`_d1M%RL9ti1RJNY!!7N*BUeQ
zRbFF%?qajvTH3Fk$P{GL at Y@;qTN#5~Jk8vGpP@~a8>c?)>AmPp3ArxD9?^muF~M`@
zFvs}QgtKbS?5QU?EB+z~PkhPj)O`%+D52L=81>=L8kc=^uKMj4gSD=G{Y89Cz9|%!
zO#6Uzr0dF%=g(-z+qT!&Sq76CuH(!u^Opl+=L5Mg&2hk(3b&=!5{hG$kq`NMWf!`*
zx4jSYU6CQK@}d{6g9R`fKBjSnN=x1gQ$o}~2ZBBDB6STTi;i1q$(4Va2+I)7*AtEV
zenw@{xG!HEPFOo+7U%nPNrw4(CSd+|&Ay9|MUl+s7l*Da_Q+wx&w|!LbS#s_{rG)<
zj}{h>_kXI`*LzgMgbfwfn_=!c$g3voX3l<mi1$eU%)OrVx{rOK0+gpvd#%oUi+G<m
zm-SIT#-4Igur|iZ&7NJ#nt22J=8(M}?5kPwvlzmk38lBK3ZLhmCyM9m0_H2q?|Qzn
zjG3*?Y9Rw!<0TblKW{8hQi}|xv6q#x_hqq%_Wlkdge<6>_KoP;h{nf;16%p~H0E{R
zPqfZ&g?ph7(xCfaDJ;h3&i>dvi5*SQzLBP>{GNdsZ47-eDqDy4&Z3`XZrxr_|J-IX
zmv9bpbfu^Hdx1S&DDL}rXr9 at j82(U-I-QmN=nbs9&cHsttlt;i-bh=j<K13(gFT2%
zXqY`z&%-J|{(N8`)ghZl@%|f?DLzs}vHuq5Q?*_J+Viy63p%Gh2U%pAFQ(8Ig}g(^
zG&@--;V8(4<Jd*_=RNQk{2TbQwsfL;&gRHkAPE`Bg8Jq32-Tlln0}RT7hrBTm6}ei
z?IdI%3(mHL?%f2Tw~glZAS?k*qfkBGkkyN+2i(o$63SgcoKR`Wm2aLA;*b&VlCK*E
zH;$;!DlNJ4rRN5vkoG6T_j9s5C&ND`+n<W(bTS>uN;25;nE>qzPZsgJ-Yc}eOXe5I
zEePJj=v|EGU36wu6e!*kPQvMO!v!{z7DsRp&*tpJc}N=b0Q>Mwv0pF;dL9${E+hU<
zV5f3IXK%tJWRQuhC}$c&bS`vfL&C8fc7<FyA!Rsj9yeX+UIT0^?)gq@@OW_N7Ol5X
zzml+2b#SiLSyT7Z(>j7sX~}i|)Ok{Q(R;Mgk}DrIw=Q(<V#w~irgb9uVo*Ez@#e?}
zr6pIsQ=~o3oi+^@lFnC5J8oXP2r1|KAzkEZSnVh(o1k*sc9hLEe)XdhWEXEErH_aI
zP21{Qbl#4)UEinZyczc-_i$d0&)tuo!d^%hv5WK|JOgF3C^Hu{IZ=b<%xa+pI*RBd
zy$!k)b}?VuD7yqZ5#UOB^vpi%gu=QkWsT~Y+!n$jV4^cslta&>WuxbH$8fMN-P$Cs
zXL3C=YE#b;dZuFV>5N^J(w;bUD0pA1d!cxX7Y35~e6O#v)9|Yq@)^qOY at vIn?wcQ7
zjZe}SeQ*7!Jdi1`jQXXgGAe7tlLQwM{srM#gbd5(!585VibBbhC!{Cam+_3>8L~~!
z`-qR1B)Zil1uE#D=TYW#N^P(%{n>Hh>8uAFUF%uzl#_-nDKBc73!&%BO8nw69DYic
z{ftm`>AQ#Cjb45^ZnGqKwp2NtE%kh<I;SzOy|p~c#DY+1$^G-E^s}_#&!bCdN6)Bw
zR(<vm-=E$HLjUZle7&bonQEJyT>0d3>8riTi0)mJ<x57BZvVQ5a2#|VkWY*f7mLwZ
zEPGD{Eqv^06~Qr)F1fwOy)(r=diE6B at 7);@*$6hvV%IF=&oX|?LWa3VN2q;|zRA^*
zejFCiuKQ+3yZVObb)shn#VL~i9_PNxq3FKV(XRV;N4xr#Cq3cY&7V=o(>FPNo2!Nj
z&^J4MyVEy3uUFiz&MDDva{5M>g%;4aJAK2`w>*EI(fkShsv!%j7^A+;=^LG7lM$Um
z#WR%2GDh!PdcQ57m3%V%cr(<0EQ-gMp^al9SJ02C&EJDI6Q_$4_WOHC-v=vTX#}Qa
z(tD8hefeQ0JPrOnpzxItoxA;h>iyzqVez at o`@zw|wEUcB&!2LpeUIl*{hi8nWs}cM
zHT at 7t`gwR0?>S!QyH{0kuXlFO@!n#~B=f?$$V5oec|RUI+CV~i at p$r%eUt(D`-4KQ
z>jB2ni_dpw&3<$!U>@<=$h6nHwU4eZ=k5=bQ#f8uKN(-KujJDjJ37%a@(KBf{N;F%
zuF4E+jzi=N-d~OuO2_M~EX#`Dx7}5j5+qY>s-0-l>?C?}GJj2YDmSK?94PdcgtP2)
z-cg-lXY!WyY+lfwW1qJ#(DQRSJd|4n_p<rCzgoz>?mX^!i+Cq{fqls?w2SP^_7ygX
zi+KpT)Gp&MF)z0(=<Stum0iuD;cKjhDpvMVyOwuf%Zxvmv>W*A%oTQ{{gK^dU*~T#
zSK2DOg(vjeY_;8P->^IEPP>c0=J=M~ZTIlhUSqWuvo-9E^%l3aw$9dDgZ(k<s?nNk
zgEjMHxX}{UYHikTo3LMpZLzI(Kda~gKDcz at q21QQd$&I8w*gD>24K7Gu$??5?zTbO
zV|#7L{=^=%hwM-7&+O0bVP`qn at DW%@<oEpE22=3^@&D}$*Ro!P_cyIqwqDkuvHpUi
z^p%7w;a*69_K0rS0T07d at GQIn+?w4tnwivD28-ZQxDIZHdm#=RVKel=Zuky74u1^?
zLGPS at 35Ve$IGGO4gtOpWI3F$t-NRQy95zA^?1t~aU%?OIY505iIs7YR;WzLujKK-)
z?=xXG%!LJT5mdr*xCLsU0Xm=?^gjF%coKd9KZ2jZtMD59JG=)|xu=~1XM+AVa}j(6
zu7+y35$=K}*bD<O1b+!n!PD>@yaHKx2adpr`gR8AK_#q&d!Pln;6Zo{_QQ|imv9K)
zfe)dCd+T&K1I~pnfzIVu!BY4-tcF@>hF*9Oo`AoF7vWWS3*Lc`fz91cf!Qz*E`Ul{
z3M=7usD-t#5$>!B|90I+YMNrL_gO5FXx<!L1HqbDYrMY3iEHYcH*c_F!Kc;QTP7&A
zw}dLqu{K-7#V6M_w>GqGK@>#1xUH?ZsirZ$wymbFIk6$0K%rPPK{e5^Zhf(CR5n4m
zwV^)lD^z?!W?MX;N7QF^)U>uVBw~#e^U)xyF212Ho~UVQOIRTqW;G=08sk>yf>6}h
zTz8+<=^6@}*REA7?dz;A9}Tk-&8 at 9gr)xw|lZbDMCt9i2WrV4S!unVPT~VfDK}LN;
ztf_fJeT@^_gjA@|+-CL7;iM2 at luB!`&LirZ+t)P40}mjhkO;FAF=nbUmRJ|J`a(RK
z+1eCqYz#A9JfGQuYq|Cku`n8B#XIWO$2L%-j|Aeijq&z`xoaR;*Sv<lB`gd>A^)tg
z#n$N>2&k(5VsqDm;1VaeBoxGBi8foWYanQ-Yu;eGgvkW4z=93=XprR`RW9Ho5wUYN
zCoi~~OUluFq at cg19Y5dTGJ<HB)mVcq at TSHv5{eUE97Y0hQ*47lm}sc4Z;XfaHboL)
zc5^%4)TC=5XyIR78X7GKLJ_Xt7B{VcHm}v#-fAse0*#IB at z%Bm3>54g6O(~TupDKj
zd at P#b>=fh_3>BnhseCL_CLEK?iW)1?)>zZXhGISvlxdAMG-~TH9|^^4+ at 2QpyfvE2
zE38MQ;Pi&lL`h!JO=w^PlnSZ5LNJcJMkJY6VXw^R`*=Qc)2DheQ4%Vy$Bpoo)*uXp
z4O<&Ftg}`ZgrXL<KhDlB at S;R)OC1i>+7d)Uaa#;ME<uvWx_FxfK`08=Mw<&lQFBYg
z2G%wqS)>x~^Ld>hT~G=v714?c3Tn=cR7t^!l#&aDVW^vk-)C)Hf at Hg2Up^9wo7N=a
yjg2v5BXN;X?3Z2pgk`rm)>gOP+%?ea;MUM&?ivWVMRVNA|4NC?f at A%U*M9>8^juE>

literal 0
HcmV?d00001

-- 
1.7.12



More information about the wayland-devel mailing list