10 #include FT_FREETYPE_H
13 #include <X11/keysym.h>
14 #include <X11/Xutil.h>
18 #define FONT_NAME "6x13"
19 #define FONT_HEIGHT 14
21 int font_height, font_width;
30 GC gc_norm, gc_rev, gc_xor;
31 unsigned long valuemask;
32 unsigned long foreground, background;
46 Bitmap bitmap[0x10000];
48 /* Unicode to glyph index mapping table. */
52 draw_bitmap (int index, int x, int y)
57 unsigned code = FT_Get_Char_Index (face, (FT_ULong) index);
58 //unsigned code = index;
67 for (i = 0; i < bmp->rows; i++, buf += bmp->pitch)
68 for (j = 0; j < bmp->width; j++)
69 if (buf[j / 8] & (1 << (7 - (j % 8))))
70 XDrawPoint (display, win, gc_norm, x + j, y + i);
77 fprintf (stderr, "Error by %s\n", msg);
83 read_unicode_seq (char *filename, int *code)
85 FILE *fp = fopen (filename, "r");
90 fprintf (stderr, "File \"%s\" can't be opened.\n", filename);
94 && fscanf (fp, "%x", code + i) == 1)
102 main (int argc, char **argv)
109 #define UPDATE_RENDERING 1
110 #define UPDATE_BITMAP 2
111 OTF_GlyphString gstring;
113 int unicode_seq[256];
115 int pixel_size = PIXEL_SIZE;
120 +-------------------------+
121 | +--- rendering area --+ |
126 | +---------------------+ |
127 | +--- bitmap area -----+ |
131 | +---------------------+ |
132 +-------------------------+
135 int win_width, win_height;
136 int cols = 16, rows = 8;
137 int max_glyph_width, max_glyph_height;
138 int inner_width, rendering_area_height, bitmap_area_height;
139 int x, y, x0, y0, x1, y1;
142 gstring.size = gstring.used = 256;
143 g = calloc (256, sizeof (OTF_Glyph));
146 if (argc != 2 && argc != 3)
148 fprintf (stderr, "Usage, otfview OTF-FILE [CODE-FILE]\n");
152 if (strstr (argv[1], ".ttf")
153 || strstr (argv[1], ".TTF")
154 || strstr (argv[1], ".otf")
155 || strstr (argv[1], ".OTF"))
157 otf = OTF_open (argv[1]);
159 || OTF_get_table (otf, "head") < 0
160 || OTF_get_table (otf, "cmap") < 0)
162 OTF_perror ("otfview");
168 char *p = getenv ("PIXEL_SIZE");
171 if (p && sscanf (p, "%d", &n) == 1)
174 p = getenv ("RAW_MODE");
179 err = FT_Init_FreeType (&library);
181 quit ("FT_Init_FreeType");
182 err = FT_New_Face (library, argv[1], 0, &face);
183 if (err == FT_Err_Unknown_File_Format)
184 quit ("FT_New_Face: unknown file format");
186 quit ("FT_New_Face: unknown error");
187 err = FT_Set_Pixel_Sizes (face, 0, pixel_size);
189 quit ("FT_Set_Char_Size");
190 err = FT_Select_Charmap (face, FT_ENCODING_APPLE_ROMAN);
191 memset (utog, 0, sizeof (utog));
192 x0 = x1 = y0 = y1 = 0;
193 for (i = 0; i < 0x10000; i++)
195 err = FT_Load_Glyph (face, i, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
197 bitmap[i].buf = NULL;
200 Bitmap *bmp = bitmap + i;
203 bmp->advance = face->glyph->metrics.horiAdvance >> 6;
204 bmp->left = face->glyph->bitmap_left;
205 bmp->top = face->glyph->bitmap_top;
206 bmp->rows = face->glyph->bitmap.rows;
207 bmp->width = face->glyph->bitmap.width;
208 bmp->pitch = face->glyph->bitmap.pitch;
209 bmpsize = bmp->rows * bmp->pitch;
210 bmp->buf = malloc (bmpsize);
211 memcpy (bmp->buf, face->glyph->bitmap.buffer, bmpsize);
216 if (x1 < bmp->left + bmp->width)
217 x1 = bmp->left + bmp->width;
218 if (y1 < bmp->rows - bmp->top)
219 y1 = bmp->rows - bmp->top;
223 max_glyph_height = y1 - y0;
224 max_glyph_width = x1 - x0;
226 for (i = 0; i < 0x10000; i++)
228 if (i >= 0xD800 && i < 0xE000)
230 gstring.glyphs[i & 0xFF].c = i;
231 if ((i & 0xFF) == 0xFF)
233 OTF_drive_cmap (otf, &gstring);
234 for (j = 0; j < 0x100; j++)
236 utog[(i & 0xFF00) + j] = gstring.glyphs[j].glyph_id;
237 if (gstring.glyphs[j].glyph_id > 0
238 && gstring.glyphs[j].glyph_id < 0x10000)
239 bitmap[gstring.glyphs[j].glyph_id].unicode = (i & 0xFF00) + j;
245 n_codes = read_unicode_seq (argv[2], unicode_seq);
247 display = XOpenDisplay (NULL);
248 screen = DefaultScreen (display);
249 font = XLoadQueryFont (display, FONT_NAME);
251 font = XLoadQueryFont (display, "fixed");
252 font_height = font->ascent + font->descent;
253 font_width = font->max_bounds.width;
255 inner_width = (max_glyph_width + 1) * cols + font_width * 4 + 2;
256 rendering_area_height= (max_glyph_height + 1) * 3 + font_height;
257 bitmap_area_height = (max_glyph_height + 1) * rows + font_height + 2;
258 win_width = inner_width + margin * 2;
259 win_height = rendering_area_height + bitmap_area_height + margin * 3;
261 win = XCreateSimpleWindow (display, RootWindow (display, screen),
262 0, 0, win_width, win_height, 1,
263 BlackPixel (display, screen),
264 WhitePixel (display, screen));
266 valuemask = GCForeground | GCBackground | GCFunction | GCFont;
268 values.foreground = BlackPixel (display, screen);
269 values.background = WhitePixel (display, screen);
270 values.function = GXcopy;
271 values.font = font->fid;
272 gc_norm = XCreateGC (display, win, valuemask, &values);
274 values.foreground = WhitePixel (display, screen);
275 values.background = BlackPixel (display, screen);
276 values.function = GXcopy;
277 gc_rev = XCreateGC (display, win, valuemask, &values);
279 values.foreground = BlackPixel (display, screen);
280 values.background = WhitePixel (display, screen);
281 values.function = values.foreground ? GXxor : GXequiv;
282 gc_xor = XCreateGC (display, win, valuemask, &values);
284 XMapWindow (display, win);
285 XSelectInput (display, win, ExposureMask | KeyPressMask | ButtonPressMask);
293 XNextEvent (display, &event);
299 int x = event.xbutton.x;
300 int y = event.xbutton.y;
302 if (margin <= x && x < margin + inner_width
303 && margin + 1 <= y && y < margin + 1 + font_height)
305 n_codes = read_unicode_seq (argv[2], unicode_seq);
306 update_mask = UPDATE_RENDERING;
318 n = XLookupString ((XKeyEvent *) &event, buf, 512, &keysym, NULL);
323 if (buf[0] == 'n' || buf[0] == ' ')
325 if (first_idx + cols * rows < 0x10000)
327 first_idx += cols * rows;
328 update_mask |= UPDATE_BITMAP;
332 else if (buf[0] == 'p'
333 || keysym == XK_BackSpace || keysym == XK_Delete)
337 first_idx -= cols * rows;
338 update_mask |= UPDATE_BITMAP;
346 update_mask = UPDATE_RENDERING | UPDATE_BITMAP;
352 if (update_mask == (UPDATE_RENDERING | UPDATE_BITMAP))
354 XClearWindow (display, win);
356 y = margin + font->ascent;
357 XDrawImageString (display, win, gc_norm, x, y, "Unicode: ", 9);
358 y += font_height + (max_glyph_height - font_height) / 2;
359 XDrawImageString (display, win, gc_norm, x, y, " cmap: ", 9);
360 y += max_glyph_height + 1;
361 XDrawImageString (display, win, gc_norm, x, y, " GSUB: ", 9);
362 y += max_glyph_height + 1;
363 XDrawImageString (display, win, gc_norm, x, y, " GPOS: ", 9);
365 y = margin * 2 + rendering_area_height;
366 XDrawLine (display, win, gc_norm, x, y, x + inner_width - 1, y);
367 y += font_height + 1;
368 for (i = 0; i <= rows; i++, y += max_glyph_height + 1)
369 XDrawLine (display, win, gc_norm, x, y, x + inner_width - 1, y);
370 y = margin * 2 + rendering_area_height;
371 XDrawLine (display, win, gc_norm, x, y,
372 x, y + bitmap_area_height - 1);
373 x += font_width * 4 + 1;
374 for (i = 0; i <= cols; i++, x += max_glyph_width + 1)
375 XDrawLine (display, win, gc_norm, x, y,
376 x, y + bitmap_area_height - 1);
377 y += font->ascent + 1;
378 x = (margin + font_width * 4 + 2
379 + (max_glyph_width - font_width * 4) / 2);
380 for (i = 0; i < cols; i++, x += max_glyph_width + 1)
382 sprintf (buf, "xxx%X", i);
383 XDrawImageString (display, win, gc_norm, x, y, buf, 4);
387 if (otf && update_mask & UPDATE_RENDERING)
389 x = margin + font_width * 9;
390 y = margin + font->ascent;
391 for (i = 0; i < n_codes; i++)
393 sprintf (buf + i * 5, "%04X ", unicode_seq[i]);
394 gstring.glyphs[i].c = unicode_seq[i];
396 gstring.used = n_codes;
397 XDrawImageString (display, win, gc_norm, x, y, buf, n_codes * 5);
399 OTF_drive_cmap (otf, &gstring);
400 y = margin + font_height + 1;
401 for (i = 0; i < n_codes; i++, x += max_glyph_width)
402 draw_bitmap (gstring.glyphs[i].glyph_id, x - x0, y - y0);
404 OTF_drive_gsub (otf, &gstring, "deva", NULL, NULL);
405 x = margin + font_width * 9;
406 y += max_glyph_height;
407 for (i = 0; i < gstring.used; i++, x += max_glyph_width)
408 draw_bitmap (gstring.glyphs[i].glyph_id, x - x0, y - y0);
410 OTF_drive_gpos (otf, &gstring, "deva", NULL, NULL);
411 x = margin + font_width * 9 - x0;
412 y += max_glyph_height - y0;
413 for (i = 0; i < gstring.used; i++)
415 int xoff = 0, yoff = 0;
416 OTF_Glyph *g = gstring.glyphs + i;
418 switch (g->positioning_type)
421 if (g->f.f1.format & OTF_XPlacement)
422 xoff = pixel_size * ((double) (g->f.f1.value->XPlacement)
423 * 100 / otf->head->unitsPerEm);
424 if (g->f.f1.format & OTF_YPlacement)
425 yoff = pixel_size * ((double) (g->f.f1.value->YPlacement)
426 * 100 / otf->head->unitsPerEm);
431 * ((double) (g->f.f4.base_anchor->XCoordinate
432 - g->f.f4.mark_anchor->XCoordinate)
433 * 100 / otf->head->unitsPerEm));
435 * ((double) (g->f.f4.base_anchor->YCoordinate
436 - g->f.f4.mark_anchor->YCoordinate)
437 * 100 / otf->head->unitsPerEm));
441 draw_bitmap (gstring.glyphs[i].glyph_id, x + xoff, y + yoff);
442 x += bitmap[gstring.glyphs[i].glyph_id].advance;
446 if (update_mask & UPDATE_BITMAP)
449 y = (margin * 2 + rendering_area_height + font_height + 2
450 + (max_glyph_height - font_height) / 2 + font->ascent);
451 for (i = 0; i < rows; i++, y += max_glyph_height + 1)
453 sprintf (buf, "%03Xx", (first_idx + i * cols) / 16);
454 XDrawImageString (display, win, gc_norm, x, y, buf, 4);
456 x += font_width * 4 + 1;
457 y = margin * 2 + rendering_area_height + font_height + 2;
458 for (i = 0; i < rows; i++)
459 for (j = 0; j < cols; j++)
461 unsigned index = first_idx + i * cols + j;
463 XClearArea (display, win, x + (max_glyph_width + 1) * j,
464 y + (max_glyph_height + 1) * i,
465 max_glyph_width, max_glyph_height, False);
467 index = FT_Get_Char_Index (face, (FT_ULong) index);
470 x + (max_glyph_width + 1) * j - x0,
471 y + (max_glyph_height + 1) * i - y0);