10 #include FT_FREETYPE_H
16 #include <X11/keysym.h>
17 #include <X11/Xutil.h>
21 //#define FONT_NAME "-adobe-courier-medium-r-normal--12-120-75-75-m-70-iso8859-1"
22 #define FONT_NAME "6x13"
23 #define FONT_HEIGHT 14
24 int font_height, font_width;
30 GC gc_norm, gc_rev, gc_xor;
31 unsigned long valuemask;
32 unsigned long foreground, background;
45 Bitmap bitmap[0x10000];
47 /* Unicode to glyph index mapping table. */
51 draw_bitmap (int index, int x, int xoff, int width,
52 int y, int yoff, int height, int clear)
54 Bitmap *bmp = bitmap + index;
55 unsigned char *buf = bmp->buf;
59 XClearArea (display, win, x, y, width, height, False);
62 x += xoff + bmp->left;
64 for (i = 0; i < bmp->rows; i++, buf += bmp->pitch)
65 for (j = 0; j < bmp->width; j++)
66 if (buf[j / 8] & (1 << (7 - (j % 8))))
67 XDrawPoint (display, win, gc_norm, x + j, y + i);
72 draw_big_bitmat (int index,
73 int x, int xoff, int width,
74 int y, int yoff, int height)
80 FT_Set_Pixel_Sizes (face, 0, PIXEL_SIZE * 4);
81 if (FT_Load_Glyph (face, index, FT_LOAD_RENDER | FT_LOAD_MONOCHROME))
84 bmp = &face->glyph->bitmap;
86 XFillRectangle (display, win, gc_rev, x, y, width, height);
87 XDrawRectangle (display, win, gc_norm, x - 1, y - 1, width + 1, height + 1);
88 x += xoff + face->glyph->bitmap_left;
89 y += yoff - face->glyph->bitmap_top;
90 for (i = 0; i < bmp->rows; i++, buf += bmp->pitch)
91 for (j = 0; j < bmp->width; j++)
92 if (buf[j / 8] & (1 << (7 - (j % 8))))
93 XDrawPoint (display, win, gc_norm, x + j, y + i);
99 fprintf (stderr, "Error by %s\n", msg);
105 read_unicode_seq (char *filename, int *code)
107 FILE *fp = fopen (filename, "r");
112 fprintf (stderr, "File \"%s\" can't be opened.\n", filename);
116 && fscanf (fp, "%x", code + i) == 1)
124 main (int argc, char **argv)
128 int i, j, max_glyph_idx;
130 int left_idx = -1, right_idx = -1;
132 #define UPDATE_RENDERING 1
133 #define UPDATE_BITMAP 2
134 OTF_GlyphString gstring;
136 int unicode_seq[256];
140 +-------------------------+
141 | +--- rendering area --+ |
146 | +---------------------+ |
147 | +--- bitmap area -----+ |
151 | +---------------------+ |
152 +-------------------------+
155 int win_width, win_height;
156 int cols = 16, rows = 8;
157 int max_glyph_width, max_glyph_height;
158 int inner_width, rendering_area_height, bitmap_area_height;
159 int x, y, x0, y0, x1, y1;
162 gstring.size = gstring.used = 256;
163 g = calloc (256, sizeof (OTF_Glyph));
166 if (argc != 2 && argc != 3)
168 fprintf (stderr, "Usage, otfview OTF-FILE [CODE-FILE]\n");
172 otf = OTF_open (argv[1]);
175 OTF_perror ("otfview");
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");
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;
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 gstring.glyphs[i & 0xFF].c = i;
229 if ((i & 0xFF) == 0xFF)
231 OTF_drive_cmap (otf, &gstring);
232 for (j = 0; j < 0x100; j++)
234 utog[(i & 0xFF00) + j] = gstring.glyphs[j].glyph_id;
235 if (gstring.glyphs[j].glyph_id > 0)
236 bitmap[gstring.glyphs[j].glyph_id].unicode = (i & 0xFF00) + j;
242 n_codes = read_unicode_seq (argv[2], unicode_seq);
244 display = XOpenDisplay (NULL);
245 screen = DefaultScreen (display);
246 font = XLoadQueryFont (display, FONT_NAME);
248 font = XLoadQueryFont (display, "fixed");
249 font_height = font->ascent + font->descent;
250 font_width = font->max_bounds.width;
252 inner_width = (max_glyph_width + 1) * cols + font_width * 4 + 2;
253 rendering_area_height= (max_glyph_height + 1) * 3 + font_height;
254 bitmap_area_height = (max_glyph_height + 1) * rows + font_height + 2;
255 win_width = inner_width + margin * 2;
256 win_height = rendering_area_height + bitmap_area_height + margin * 3;
258 win = XCreateSimpleWindow (display, RootWindow (display, screen),
259 0, 0, win_width, win_height, 1,
260 BlackPixel (display, screen),
261 WhitePixel (display, screen));
263 valuemask = GCForeground | GCBackground | GCFunction | GCFont;
265 values.foreground = BlackPixel (display, screen);
266 values.background = WhitePixel (display, screen);
267 values.function = GXcopy;
268 values.font = font->fid;
269 gc_norm = XCreateGC (display, win, valuemask, &values);
271 values.foreground = WhitePixel (display, screen);
272 values.background = BlackPixel (display, screen);
273 values.function = GXcopy;
274 gc_rev = XCreateGC (display, win, valuemask, &values);
276 values.foreground = BlackPixel (display, screen);
277 values.background = WhitePixel (display, screen);
278 values.function = values.foreground ? GXxor : GXequiv;
279 gc_xor = XCreateGC (display, win, valuemask, &values);
281 XMapWindow (display, win);
282 XSelectInput (display, win, ExposureMask | KeyPressMask | ButtonPressMask);
290 XNextEvent (display, &event);
296 int x = event.xbutton.x;
297 int y = event.xbutton.y;
299 if (margin <= x && x < margin + inner_width
300 && margin + 1 <= y && y < margin + 1 + font_height)
302 n_codes = read_unicode_seq (argv[2], unicode_seq);
303 update_mask = UPDATE_RENDERING;
315 n = XLookupString ((XKeyEvent *) &event, buf, 512, &keysym, NULL);
320 if (buf[0] == 'n' || buf[0] == ' ')
322 if (first_idx + cols * rows <= max_glyph_idx)
324 first_idx += cols * rows;
325 update_mask |= UPDATE_BITMAP;
329 else if (buf[0] == 'p'
330 || keysym == XK_BackSpace || keysym == XK_Delete)
334 first_idx -= cols * rows;
335 update_mask |= UPDATE_BITMAP;
343 update_mask = UPDATE_RENDERING | UPDATE_BITMAP;
349 if (update_mask == (UPDATE_RENDERING | UPDATE_BITMAP))
351 XClearWindow (display, win);
353 y = margin + font->ascent;
354 XDrawImageString (display, win, gc_norm, x, y, "Unicode: ", 9);
355 y += font_height + (max_glyph_height - font_height) / 2;
356 XDrawImageString (display, win, gc_norm, x, y, " cmap: ", 9);
357 y += max_glyph_height + 1;
358 XDrawImageString (display, win, gc_norm, x, y, " GSUB: ", 9);
359 y += max_glyph_height + 1;
360 XDrawImageString (display, win, gc_norm, x, y, " GPOS: ", 9);
362 y = margin * 2 + rendering_area_height;
363 XDrawLine (display, win, gc_norm, x, y, x + inner_width - 1, y);
364 y += font_height + 1;
365 for (i = 0; i <= rows; i++, y += max_glyph_height + 1)
366 XDrawLine (display, win, gc_norm, x, y, x + inner_width - 1, y);
367 y = margin * 2 + rendering_area_height;
368 XDrawLine (display, win, gc_norm, x, y,
369 x, y + bitmap_area_height - 1);
370 x += font_width * 4 + 1;
371 for (i = 0; i <= cols; i++, x += max_glyph_width + 1)
372 XDrawLine (display, win, gc_norm, x, y,
373 x, y + bitmap_area_height - 1);
374 y += font->ascent + 1;
375 x = (margin + font_width * 4 + 2
376 + (max_glyph_width - font_width * 4) / 2);
377 for (i = 0; i < cols; i++, x += max_glyph_width + 1)
379 sprintf (buf, "xxx%X", i);
380 XDrawImageString (display, win, gc_norm, x, y, buf, 4);
384 if (update_mask & UPDATE_RENDERING)
386 x = margin + font_width * 9;
387 y = margin + font->ascent;
388 for (i = 0; i < n_codes; i++)
390 sprintf (buf + i * 5, "%04X ", unicode_seq[i]);
391 gstring.glyphs[i].c = unicode_seq[i];
393 gstring.used = n_codes;
394 XDrawImageString (display, win, gc_norm, x, y, buf, n_codes * 5);
396 OTF_drive_cmap (otf, &gstring);
397 y = margin + font_height + 1;
398 for (i = 0; i < n_codes; i++, x+= max_glyph_width)
399 draw_bitmap (gstring.glyphs[i].glyph_id, x, -x0, max_glyph_width,
400 y, -y0, max_glyph_height, 1);
402 OTF_drive_gsub (otf, &gstring, "deva", NULL, NULL);
403 x = margin + font_width * 9;
404 y += max_glyph_height;
405 for (i = 0; i < gstring.used; i++)
407 draw_bitmap (gstring.glyphs[i].glyph_id, x, -x0, max_glyph_width,
408 y, -y0, max_glyph_height, 0);
409 x += bitmap[gstring.glyphs[i].glyph_id].width;
412 draw_big_bitmat (left_idx, max_glyph_width * 2, -x0 * 5, max_glyph_width * 5,
413 5, -y0 * 5, max_glyph_height * 5);
416 if (update_mask & UPDATE_BITMAP)
419 y = (margin * 2 + rendering_area_height + font_height + 2
420 + (max_glyph_height - font_height) / 2 + font->ascent);
421 for (i = 0; i < rows; i++, y += max_glyph_height + 1)
423 sprintf (buf, "%03Xx", (first_idx + i * cols) / 16);
424 XDrawImageString (display, win, gc_norm, x, y, buf, 4);
426 x += font_width * 4 + 1;
427 y = margin * 2 + rendering_area_height + font_height + 2;
428 for (i = 0; i < rows; i++)
429 for (j = 0; j < cols; j++)
430 draw_bitmap (first_idx + i * cols + j,
431 x + (max_glyph_width + 1) * j, -x0, max_glyph_width,
432 y + (max_glyph_height + 1) * i,
433 -y0, max_glyph_height, 1);