10 #include FT_FREETYPE_H
13 #include <X11/keysym.h>
14 #include <X11/Xutil.h>
18 //#define FONT_NAME "-adobe-courier-medium-r-normal--12-120-75-75-m-70-iso8859-1"
19 #define FONT_NAME "6x13"
20 #define FONT_HEIGHT 14
22 int font_height, font_width;
31 GC gc_norm, gc_rev, gc_xor;
32 unsigned long valuemask;
33 unsigned long foreground, background;
47 Bitmap bitmap[0x10000];
49 /* Unicode to glyph index mapping table. */
53 draw_bitmap (int index, int x, int y)
55 Bitmap *bmp = bitmap + index;
56 unsigned char *buf = bmp->buf;
63 for (i = 0; i < bmp->rows; i++, buf += bmp->pitch)
64 for (j = 0; j < bmp->width; j++)
65 if (buf[j / 8] & (1 << (7 - (j % 8))))
66 XDrawPoint (display, win, gc_norm, x + j, y + i);
73 fprintf (stderr, "Error by %s\n", msg);
79 read_unicode_seq (char *filename, int *code)
81 FILE *fp = fopen (filename, "r");
86 fprintf (stderr, "File \"%s\" can't be opened.\n", filename);
90 && fscanf (fp, "%x", code + i) == 1)
98 main (int argc, char **argv)
102 int i, j, max_glyph_idx;
105 #define UPDATE_RENDERING 1
106 #define UPDATE_BITMAP 2
107 OTF_GlyphString gstring;
109 int unicode_seq[256];
113 +-------------------------+
114 | +--- rendering area --+ |
119 | +---------------------+ |
120 | +--- bitmap area -----+ |
124 | +---------------------+ |
125 +-------------------------+
128 int win_width, win_height;
129 int cols = 16, rows = 8;
130 int max_glyph_width, max_glyph_height;
131 int inner_width, rendering_area_height, bitmap_area_height;
132 int x, y, x0, y0, x1, y1;
135 gstring.size = gstring.used = 256;
136 g = calloc (256, sizeof (OTF_Glyph));
139 if (argc != 2 && argc != 3)
141 fprintf (stderr, "Usage, otfview OTF-FILE [CODE-FILE]\n");
145 otf = OTF_open (argv[1]);
148 OTF_perror ("otfview");
152 err = FT_Init_FreeType (&library);
154 quit ("FT_Init_FreeType");
155 err = FT_New_Face (library, argv[1], 0, &face);
156 if (err == FT_Err_Unknown_File_Format)
157 quit ("FT_New_Face: unknown file format");
159 quit ("FT_New_Face: unknown error");
160 err = FT_Set_Pixel_Sizes (face, 0, PIXEL_SIZE);
162 quit ("FT_Set_Char_Size");
164 memset (utog, 0, sizeof (utog));
165 x0 = x1 = y0 = y1 = 0;
166 for (i = 0; i < 0x10000; i++)
168 err = FT_Load_Glyph (face, i, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
170 bitmap[i].buf = NULL;
173 Bitmap *bmp = bitmap + i;
177 bmp->advance = face->glyph->metrics.horiAdvance >> 6;
178 bmp->left = face->glyph->bitmap_left;
179 bmp->top = face->glyph->bitmap_top;
180 bmp->rows = face->glyph->bitmap.rows;
181 bmp->width = face->glyph->bitmap.width;
182 bmp->pitch = face->glyph->bitmap.pitch;
183 bmpsize = bmp->rows * bmp->pitch;
184 bmp->buf = malloc (bmpsize);
185 memcpy (bmp->buf, face->glyph->bitmap.buffer, bmpsize);
190 if (x1 < bmp->left + bmp->width)
191 x1 = bmp->left + bmp->width;
192 if (y1 < bmp->rows - bmp->top)
193 y1 = bmp->rows - bmp->top;
197 max_glyph_height = y1 - y0;
198 max_glyph_width = x1 - x0;
200 for (i = 0; i < 0x10000; i++)
202 gstring.glyphs[i & 0xFF].c = i;
203 if ((i & 0xFF) == 0xFF)
205 OTF_drive_cmap (otf, &gstring);
206 for (j = 0; j < 0x100; j++)
208 utog[(i & 0xFF00) + j] = gstring.glyphs[j].glyph_id;
209 if (gstring.glyphs[j].glyph_id > 0)
210 bitmap[gstring.glyphs[j].glyph_id].unicode = (i & 0xFF00) + j;
216 n_codes = read_unicode_seq (argv[2], unicode_seq);
218 display = XOpenDisplay (NULL);
219 screen = DefaultScreen (display);
220 font = XLoadQueryFont (display, FONT_NAME);
222 font = XLoadQueryFont (display, "fixed");
223 font_height = font->ascent + font->descent;
224 font_width = font->max_bounds.width;
226 inner_width = (max_glyph_width + 1) * cols + font_width * 4 + 2;
227 rendering_area_height= (max_glyph_height + 1) * 3 + font_height;
228 bitmap_area_height = (max_glyph_height + 1) * rows + font_height + 2;
229 win_width = inner_width + margin * 2;
230 win_height = rendering_area_height + bitmap_area_height + margin * 3;
232 win = XCreateSimpleWindow (display, RootWindow (display, screen),
233 0, 0, win_width, win_height, 1,
234 BlackPixel (display, screen),
235 WhitePixel (display, screen));
237 valuemask = GCForeground | GCBackground | GCFunction | GCFont;
239 values.foreground = BlackPixel (display, screen);
240 values.background = WhitePixel (display, screen);
241 values.function = GXcopy;
242 values.font = font->fid;
243 gc_norm = XCreateGC (display, win, valuemask, &values);
245 values.foreground = WhitePixel (display, screen);
246 values.background = BlackPixel (display, screen);
247 values.function = GXcopy;
248 gc_rev = XCreateGC (display, win, valuemask, &values);
250 values.foreground = BlackPixel (display, screen);
251 values.background = WhitePixel (display, screen);
252 values.function = values.foreground ? GXxor : GXequiv;
253 gc_xor = XCreateGC (display, win, valuemask, &values);
255 XMapWindow (display, win);
256 XSelectInput (display, win, ExposureMask | KeyPressMask | ButtonPressMask);
264 XNextEvent (display, &event);
270 int x = event.xbutton.x;
271 int y = event.xbutton.y;
273 if (margin <= x && x < margin + inner_width
274 && margin + 1 <= y && y < margin + 1 + font_height)
276 n_codes = read_unicode_seq (argv[2], unicode_seq);
277 update_mask = UPDATE_RENDERING;
289 n = XLookupString ((XKeyEvent *) &event, buf, 512, &keysym, NULL);
294 if (buf[0] == 'n' || buf[0] == ' ')
296 if (first_idx + cols * rows <= max_glyph_idx)
298 first_idx += cols * rows;
299 update_mask |= UPDATE_BITMAP;
303 else if (buf[0] == 'p'
304 || keysym == XK_BackSpace || keysym == XK_Delete)
308 first_idx -= cols * rows;
309 update_mask |= UPDATE_BITMAP;
317 update_mask = UPDATE_RENDERING | UPDATE_BITMAP;
323 if (update_mask == (UPDATE_RENDERING | UPDATE_BITMAP))
325 XClearWindow (display, win);
327 y = margin + font->ascent;
328 XDrawImageString (display, win, gc_norm, x, y, "Unicode: ", 9);
329 y += font_height + (max_glyph_height - font_height) / 2;
330 XDrawImageString (display, win, gc_norm, x, y, " cmap: ", 9);
331 y += max_glyph_height + 1;
332 XDrawImageString (display, win, gc_norm, x, y, " GSUB: ", 9);
333 y += max_glyph_height + 1;
334 XDrawImageString (display, win, gc_norm, x, y, " GPOS: ", 9);
336 y = margin * 2 + rendering_area_height;
337 XDrawLine (display, win, gc_norm, x, y, x + inner_width - 1, y);
338 y += font_height + 1;
339 for (i = 0; i <= rows; i++, y += max_glyph_height + 1)
340 XDrawLine (display, win, gc_norm, x, y, x + inner_width - 1, y);
341 y = margin * 2 + rendering_area_height;
342 XDrawLine (display, win, gc_norm, x, y,
343 x, y + bitmap_area_height - 1);
344 x += font_width * 4 + 1;
345 for (i = 0; i <= cols; i++, x += max_glyph_width + 1)
346 XDrawLine (display, win, gc_norm, x, y,
347 x, y + bitmap_area_height - 1);
348 y += font->ascent + 1;
349 x = (margin + font_width * 4 + 2
350 + (max_glyph_width - font_width * 4) / 2);
351 for (i = 0; i < cols; i++, x += max_glyph_width + 1)
353 sprintf (buf, "xxx%X", i);
354 XDrawImageString (display, win, gc_norm, x, y, buf, 4);
358 if (update_mask & UPDATE_RENDERING)
360 x = margin + font_width * 9;
361 y = margin + font->ascent;
362 for (i = 0; i < n_codes; i++)
364 sprintf (buf + i * 5, "%04X ", unicode_seq[i]);
365 gstring.glyphs[i].c = unicode_seq[i];
367 gstring.used = n_codes;
368 XDrawImageString (display, win, gc_norm, x, y, buf, n_codes * 5);
370 OTF_drive_cmap (otf, &gstring);
371 y = margin + font_height + 1;
372 for (i = 0; i < n_codes; i++, x += max_glyph_width)
373 draw_bitmap (gstring.glyphs[i].glyph_id, x - x0, y - y0);
375 OTF_drive_gsub (otf, &gstring, "deva", NULL, NULL);
376 x = margin + font_width * 9;
377 y += max_glyph_height;
378 for (i = 0; i < gstring.used; i++, x += max_glyph_width)
379 draw_bitmap (gstring.glyphs[i].glyph_id, x - x0, y - y0);
381 OTF_drive_gpos (otf, &gstring, "deva", NULL, NULL);
382 x = margin + font_width * 9 - x0;
383 y += max_glyph_height - y0;
384 for (i = 0; i < gstring.used; i++)
386 int xoff = 0, yoff = 0;
387 OTF_Glyph *g = gstring.glyphs + i;
389 switch (g->positioning_type)
392 if (g->f.f1.format & OTF_XPlacement)
393 xoff = PIXEL_SIZE * ((double) (g->f.f1.value->XPlacement)
394 * 100 / otf->head->unitsPerEm);
395 if (g->f.f1.format & OTF_YPlacement)
396 yoff = PIXEL_SIZE * ((double) (g->f.f1.value->YPlacement)
397 * 100 / otf->head->unitsPerEm);
402 * ((double) (g->f.f4.base_anchor->XCoordinate
403 - g->f.f4.mark_anchor->XCoordinate)
404 * 100 / otf->head->unitsPerEm));
406 * ((double) (g->f.f4.base_anchor->YCoordinate
407 - g->f.f4.mark_anchor->YCoordinate)
408 * 100 / otf->head->unitsPerEm));
412 draw_bitmap (gstring.glyphs[i].glyph_id, x + xoff, y + yoff);
413 x += bitmap[gstring.glyphs[i].glyph_id].advance;
417 if (update_mask & UPDATE_BITMAP)
420 y = (margin * 2 + rendering_area_height + font_height + 2
421 + (max_glyph_height - font_height) / 2 + font->ascent);
422 for (i = 0; i < rows; i++, y += max_glyph_height + 1)
424 sprintf (buf, "%03Xx", (first_idx + i * cols) / 16);
425 XDrawImageString (display, win, gc_norm, x, y, buf, 4);
427 x += font_width * 4 + 1;
428 y = margin * 2 + rendering_area_height + font_height + 2;
429 for (i = 0; i < rows; i++)
430 for (j = 0; j < cols; j++)
432 XClearArea (display, win, x + (max_glyph_width + 1) * j,
433 y + (max_glyph_height + 1) * i,
434 max_glyph_width, max_glyph_height, False);
435 draw_bitmap (first_idx + i * cols + j,
436 x + (max_glyph_width + 1) * j - x0,
437 y + (max_glyph_height + 1) * i - y0);