1 /* otfview.c -- View glyphs of OpenType fonts.
3 Copyright (C) 2003, 2004, 2005
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H15PRO167
7 This file is part of libotf.
9 Libotf is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 Libotf is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library, in a file named COPYING; if not,
21 write to the Free Software Foundation, Inc., 59 Temple Place, Suite
22 330, Boston, MA 02111-1307, USA. */
33 #ifdef HAVE_X11_XAW_COMMAND_H
35 #include <X11/Xatom.h>
36 #include <X11/Intrinsic.h>
37 #include <X11/StringDefs.h>
38 #include <X11/Shell.h>
39 #include <X11/Xaw/Command.h>
40 #include <X11/Xaw/Toggle.h>
41 #include <X11/Xaw/Box.h>
42 #include <X11/Xaw/Form.h>
43 #include <X11/Xaw/Viewport.h>
46 #include FT_FREETYPE_H
50 #define DEFAULT_PIXEL_SIZE 30
53 #define DEFAULT_FONT_NAME "6x13"
55 #define FONT_HEIGHT (font->ascent + font->descent)
56 #define FONT_ASCENT (font->ascent)
57 #define FONT_DESCENT (font->descent)
58 #define FONT_WIDTH (font->max_bounds.width)
62 +--- frame (form) -------------------------+
63 | +--- command_area (box) ---------------+ |
64 | | quit dump charmap ... | |
65 | +--------------------------------------+ |
66 | +---- navi_area (box) -----------------+ |
67 | | FIRST PREV prev range next NEXT LAST | |
68 | +--------------------------------------+ |
69 | +--- glyph_area (form) ----------------+ |
70 | | idxh[0] glyph[0] ... glyph[15] | |
72 | | idxh[7] glyph[112] ... glyph[127]| |
73 | | idxl[0] ... idxl[15] | |
74 | +--------------------------------------+ |
75 | +--- render_area (form) ---------------+ |
76 | | clear del bidi alt_subst | |
77 | | +--- raw (box) --------------------+ | |
78 | | | raw_label raw_image | | |
79 | | +----------------------------------+ | |
80 | | GSUB all none features... | |
81 | | GPOS all none features... | |
82 | | +--- seq (box) --------------------+ | |
83 | | | seq_label seq_image | | |
84 | | +----------------------------------+ | |
85 | +--------------------------------------+ |
86 +------------------------------------------+ */
88 Widget command_area, quit, dump, *charmap;
89 Widget navi_area, FIRST, PREV, prev, range, next, NEXT, LAST;
90 Widget glyph_area, glyph[128], index_label[8];
91 Widget render_area, clear, del, bidi, alt_subst, raw, seq;
92 Widget raw_label, raw_image, seq_label, seq_image;
93 unsigned long foreground, background;
105 OTF_GSUB_GPOS *gsub_gpos;
106 OTF_LangSys *langsys;
108 FeatureElement *features;
112 FeatureRec gsub, gpos;
114 /* Currently selected script and langsys. */
115 OTF_Tag script_tag, langsys_tag;
120 GC gc, gc_set, gc_or, gc_inv;
124 unsigned width, height;
129 BitmapRec bitmap[0x10000];
131 int render_width, render_height;
132 Pixmap raw_pixmap, seq_pixmap, gsub_pixmap, gpos_pixmap;
146 int do_alternate_subst;
147 unsigned glyph_width, glyph_height;
148 int glyph_x, glyph_y;
161 create_pixmap (int index)
163 int err = FT_Load_Glyph (face, index, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
169 bitmap[index].pixmap = none_pixmap;
172 ximage.height = face->glyph->bitmap.rows;
173 ximage.width = face->glyph->bitmap.width;
175 ximage.bits_per_pixel = 1;
177 ximage.format = XYPixmap;
178 ximage.data = (char *) face->glyph->bitmap.buffer;
179 ximage.byte_order = MSBFirst;
180 ximage.bitmap_unit = 8;
181 ximage.bitmap_bit_order = MSBFirst;
182 ximage.bitmap_pad = 8;
183 ximage.bytes_per_line = face->glyph->bitmap.pitch;
184 XInitImage (&ximage);
185 pixmap = XCreatePixmap (display, DefaultRootWindow (display),
186 glyph_width, glyph_height, 1);
187 XFillRectangle (display, pixmap, gc, 0, 0, glyph_width, glyph_height);
188 XPutImage (display, pixmap, gc, &ximage, 0, 0,
189 glyph_x + face->glyph->bitmap_left,
190 glyph_y - face->glyph->bitmap_top,
191 ximage.width, ximage.height);
192 bitmap[index].pixmap = pixmap;
193 bitmap[index].width = ximage.width;
194 bitmap[index].height = ximage.height;
195 bitmap[index].x = face->glyph->bitmap_left;
196 bitmap[index].y = - face->glyph->bitmap_top;
197 bitmap[index].advance = face->glyph->metrics.horiAdvance >> 6;
208 for (i = 0; i < 128; i++)
210 int index = glyph_index + i;
212 if (charmap_index >= 0)
213 index = FT_Get_Char_Index (face, (FT_ULong) index);
215 XtSetArg (arg[0], XtNbitmap, none_pixmap);
218 if (! bitmap[index].pixmap)
219 create_pixmap (index);
220 XtSetArg (arg[0], XtNbitmap, bitmap[index].pixmap);
222 XtSetValues (glyph[i], arg, 1);
225 msb = (glyph_index >> 7) % 2 ? 8 : 0;
226 for (i = 0; i < 8; i++)
230 sprintf (str, "%XX", i | msb );
231 XtSetArg (arg[0], XtNheight, glyph_height + 5);
232 XtSetArg (arg[1], XtNlabel, str);
233 XtSetValues (index_label[i], arg, 2);
236 sprintf (buf, " %04X-%04X ", glyph_index, glyph_index + 0x7F);
237 XtSetArg (arg[0], XtNlabel, buf);
238 XtSetValues (range, arg, 1);
242 get_features (OTF_FeatureList *list, FeatureRec *rec)
247 if (! rec->langsys || ! rec->features || ! rec->features[0].on)
249 for (i = n = 0; i < rec->langsys->FeatureCount; i++)
251 if (rec->features[i].on)
256 str = malloc (n * 5);
257 for (i = 0, p = str; i < n; i++, p += 5)
259 OTF_tag_name (rec->features[i].tag, p);
267 #define DEVICE_DELTA(table, size) \
268 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
269 ? (table).DeltaValue[(size) >= (table).StartSize] \
273 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
274 OTF_Glyph *g, int *x, int *y)
276 if (anchor->AnchorFormat == 2)
279 int ap = anchor->f.f1.AnchorPoint;
281 FT_Load_Glyph (ft_face, (FT_UInt) g->glyph_id, FT_LOAD_MONOCHROME);
282 outline = &ft_face->glyph->outline;
283 if (ap < outline->n_points)
285 *x = outline->points[ap].x;
286 *y = outline->points[ap].y;
289 else if (anchor->AnchorFormat == 3)
291 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, pixel_size);
292 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, pixel_size);
300 OTF_GlyphString gstring;
301 OTF_Glyph *g, *prev, *base, *mark;
303 int len = glyph_rec.n_glyphs;
305 int unitsPerEm = face->units_per_EM;
307 gstring.size = gstring.used = len;
308 gstring.glyphs = malloc (sizeof (OTF_Glyph) * len);
309 memset (gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
310 for (i = 0; i < len; i++)
311 gstring.glyphs[i].c = gstring.glyphs[i].glyph_id = glyph_rec.glyphs[i];
313 XFillRectangle (display, seq_pixmap, gc, 0, 0, render_width, render_height);
314 XDrawLine (display, seq_pixmap, gc_set, 0, glyph_y, render_width, glyph_y);
319 OTF_drive_gdef (otf, &gstring);
322 str = get_features (&otf->gsub->FeatureList, &gsub);
325 if (do_alternate_subst)
326 OTF_drive_gsub_alternate (otf, &gstring, NULL, NULL, str);
328 OTF_drive_gsub (otf, &gstring, NULL, NULL, str);
334 str = get_features (&otf->gpos->FeatureList, &gpos);
337 OTF_drive_gpos (otf, &gstring, NULL, NULL, str);
348 for (prev = gstring.glyphs, g = gstring.glyphs + gstring.used - 1;
349 prev < g; prev++, g--)
350 temp = *prev, *prev = *g, *g = temp;
351 for (g = gstring.glyphs; g < gstring.glyphs + gstring.used; g++)
352 if (g->GlyphClass == 3)
356 while (g < gstring.glyphs + gstring.used && g->GlyphClass == 3)
358 for (g0 = g; prev < g0; prev++, g0--)
359 temp = *prev, *prev = *g, *g = temp;
365 for (i = 0, x = glyph_x, prev = NULL, g = gstring.glyphs;
366 i < gstring.used; i++, prev = g++)
368 BitmapRec *bmp = bitmap + gstring.glyphs[i].glyph_id;
369 int xoff = 0, yoff = 0;
371 int advance = bmp->advance;
375 create_pixmap (gstring.glyphs[i].glyph_id);
378 advance = bmp->advance;
380 switch (g->positioning_type)
387 int format = g->f.f1.format;
389 if (format & OTF_XPlacement)
390 xoff = g->f.f1.value->XPlacement * pixel_size / unitsPerEm;
391 if (format & OTF_XPlaDevice)
392 xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, pixel_size);
393 if (format & OTF_YPlacement)
394 yoff = g->f.f1.value->YPlacement * pixel_size / unitsPerEm;
395 if (format & OTF_YPlaDevice)
396 yoff += DEVICE_DELTA (g->f.f1.value->YPlaDevice, pixel_size);
397 if (format & OTF_XAdvance)
398 advance += g->f.f1.value->XAdvance * pixel_size / unitsPerEm;
399 if (format & OTF_XAdvDevice)
400 advance += DEVICE_DELTA (g->f.f1.value->XAdvDevice, pixel_size);
405 /* Not yet supported. */
411 prev_width = base_width;
412 goto label_adjust_anchor;
413 default: /* i.e. case 6 */
420 int base_x, base_y, mark_x, mark_y;
422 base_x = g->f.f4.base_anchor->XCoordinate * pixel_size / unitsPerEm;
423 base_y = g->f.f4.base_anchor->YCoordinate * pixel_size / unitsPerEm;
424 mark_x = g->f.f4.mark_anchor->XCoordinate * pixel_size / unitsPerEm;
425 mark_y = g->f.f4.mark_anchor->YCoordinate * pixel_size / unitsPerEm;
427 if (g->f.f4.base_anchor->AnchorFormat != 1)
428 adjust_anchor (g->f.f4.base_anchor, face, prev, &base_x, &base_y);
429 if (g->f.f4.mark_anchor->AnchorFormat != 1)
430 adjust_anchor (g->f.f4.mark_anchor, face, g, &mark_x, &mark_y);
431 xoff = (base_x - prev_width) - mark_x;
432 yoff = base_y - mark_y;
436 XCopyArea (display, bmp->pixmap, seq_pixmap, gc_or,
437 glyph_x + bmp->x, glyph_y + bmp->y, bmp->width, bmp->height,
438 x + bmp->x + xoff, glyph_y + bmp->y - yoff);
441 if (g->GlyphClass == OTF_GlyphClass0)
442 base = mark = g, base_width = advance;
443 else if (g->GlyphClass == OTF_GlyphClassMark)
446 base = g, base_width = advance;
448 free (gstring.glyphs);
450 XtSetArg (arg[0], XtNbitmap, seq_pixmap);
451 XtSetValues (seq_image, arg, 1);
456 update_render_area ()
462 XFillRectangle (display, raw_pixmap, gc, 0, 0, render_width, render_height);
463 for (i = 0, x = glyph_x; i < glyph_rec.n_glyphs; i++)
465 BitmapRec *bmp = bitmap + glyph_rec.glyphs[i];
468 XCopyArea (display, bmp->pixmap, raw_pixmap, gc,
469 0, 0, glyph_width, glyph_height,
470 (glyph_width + 4) * i + 1, 1);
471 XDrawRectangle (display, raw_pixmap, gc_set,
472 (glyph_width + 4) * i, 0,
473 glyph_width + 1, glyph_height + 1);
474 XDrawLine (display, raw_pixmap, gc_set,
475 (glyph_width + 4) * i + 1 + glyph_x, 1,
476 (glyph_width + 4) * i + 1 + glyph_x, glyph_height + 1);
477 XDrawLine (display, raw_pixmap, gc_set,
478 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance, 1,
479 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance,
482 sprintf (buf, "%04X", glyph_rec.codes[i]);
483 XDrawString (display, raw_pixmap, gc_inv,
484 (glyph_width + 1) * i + 1
485 + (glyph_width - XTextWidth (font, buf, 4)) / 2,
486 glyph_height + 2 + FONT_HEIGHT, buf, 4);
488 XtSetArg (arg[0], XtNbitmap, raw_pixmap);
489 XtSetValues (raw_image, arg, 1);
494 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
496 XtAppSetExitFlag (XtWidgetToApplicationContext (w));
500 DumpProc (Widget w, XtPointer client_data, XtPointer call_data)
502 int g_width, g_height;
504 /* unit in points (1/72 inch); to fit in both US-letter and A4 */
505 static int xoff = 30, yoff = 30;
506 static int unit = 30;
507 static int margin = 2;
508 static int title_height = 20, label_height = 10;
509 int total_width = (unit + margin * 2) * 16;
510 int total_height = (unit + margin * 2 + label_height) * 16 + title_height;
511 /* pixel size (dots) */
514 char *name = alloca (strlen (filename) + 10);
516 int index = (glyph_index / 0x100) * 0x100;
519 sprintf (name, "%s-%04X.ps", face->family_name, index);
520 printf ("Writing %s ... ", name);
522 fp = fopen (name, "w");
524 fprintf (fp, "%s\n", "%!PS-Adobe-2.0 EPSF-2.0");
525 fprintf (fp, "%s\n", "%%Creater: otfview");
526 fprintf (fp, "%s %s(%s)-%04X\n", "%%Title:",
527 face->family_name, face->style_name, index);
528 fprintf (fp, "%s\n", "%%Pages: 1");
529 fprintf (fp, "%s %d %d %d %d\n", "%%BoundingBox:",
530 xoff, yoff, xoff + total_width, yoff + total_height);
531 fprintf (fp, "%s\n", "%%EndComments");
532 fprintf (fp, "%s\n", "%%BeginProlog");
533 fprintf (fp, "/W %d def\n", unit + margin * 2);
534 fprintf (fp, "/H %d def\n", unit + margin * 2 + label_height);
535 fprintf (fp, "/STR 10 string def\n");
536 fprintf (fp, "/DrawIndex {\n");
537 fprintf (fp, " I 16 lt { (000) show } { I 256 lt { (00) show } { I 4096 lt { (0) show} if } ifelse } ifelse I 16 STR cvrs show\n");
538 fprintf (fp, "} def\n");
539 fprintf (fp, "/DrawTitle {\n");
540 fprintf (fp, " /Courier findfont 20 scalefont setfont\n");
541 fprintf (fp, " %d %d 4 add moveto\n", xoff + total_width / 2,
542 yoff + total_height - title_height + 2);
543 fprintf (fp, " (%s(%s)-%04X) dup stringwidth pop 2 div neg 0 rmoveto show\n",
544 face->family_name, face->style_name, index);
545 fprintf (fp, "} def\n");
546 fprintf (fp, "/DrawFrame { gsave %d %d translate 0 setlinewidth\n",
548 fprintf (fp, " /Courier findfont 10 scalefont setfont\n");
549 fprintf (fp, " /I %d def\n", index);
550 fprintf (fp, " 0 1 16 { W mul 0 moveto 0 H 16 mul rlineto stroke } for\n");
551 fprintf (fp, " 0 1 16 { H mul 0 exch moveto W 16 mul 0 rlineto stroke } for\n");
552 fprintf (fp, " 0 1 15 { H mul %d add 0 exch moveto W 16 mul 0 rlineto stroke } for\n", label_height);
553 fprintf (fp, " 15 -1 0 { gsave H mul 0 exch translate 0 0 moveto\n");
554 fprintf (fp, " 0 1 15 { gsave W mul 0 moveto\n");
555 fprintf (fp, " 4 2 rmoveto DrawIndex /I I 1 add def grestore} for\n");
556 fprintf (fp, " grestore } for grestore } def\n");
557 fprintf (fp, "%s\n", "%%EndProlog");
558 fprintf (fp, "DrawTitle DrawFrame\n");
560 g_width = face->bbox.xMax - face->bbox.xMin;
561 g_height = face->bbox.yMax - face->bbox.yMin;
562 scale = ((g_width > g_height) ? g_width : g_height) * size;
563 scale /= face->units_per_EM;
564 g_x = face->bbox.xMin * scale / unit / face->units_per_EM;
565 g_y = face->bbox.yMin * scale / unit / face->units_per_EM;
567 FT_Set_Pixel_Sizes (face, 0, size);
568 for (i = 0; i < 16; i++)
569 for (j = 0; j < 16; j++, index++)
573 if (charmap_index >= 0)
574 idx = FT_Get_Char_Index (face, (FT_ULong) index);
577 if (FT_Load_Glyph (face, idx, FT_LOAD_RENDER | FT_LOAD_MONOCHROME) == 0
578 && face->glyph->bitmap.rows > 0
579 && face->glyph->bitmap.width > 0)
581 unsigned char *p = face->glyph->bitmap.buffer;
582 int width = (face->glyph->bitmap.width - 1) / 8 + 1;
584 fprintf (fp, "gsave %f %f translate %d %d scale 0 0 moveto\n",
585 xoff + (unit + margin * 2) * j + margin - g_x,
586 yoff + (unit + label_height + margin * 2) * (15 - i) + label_height + margin - g_y,
588 fprintf (fp, "%d %d true [%f 0 0 %f %d %d]\n",
589 width * 8, face->glyph->bitmap.rows,
590 scale, -scale, face->glyph->bitmap_left,
591 face->glyph->bitmap_top);
593 for (k = 0; k < face->glyph->bitmap.rows;
594 k++, p += face->glyph->bitmap.pitch)
596 for (l = 0; l < width; l++)
597 fprintf (fp, "%02X", p[l]);
600 fprintf (fp, ">} imagemask grestore\n");
603 fprintf (fp, "showpage\n");
607 FT_Set_Pixel_Sizes (face, 0, (int) pixel_size);
612 GlyphProc (Widget w, XtPointer client_data, XtPointer call_data)
614 int old_glyph_index = glyph_index;
616 if ((int) client_data == -3 && glyph_index > 0)
618 else if ((int) client_data == -2 && glyph_index > 0)
619 glyph_index = (glyph_index - 1) & 0xF000;
620 else if ((int) client_data == -1 && glyph_index > 0)
622 else if ((int) client_data == 1 && glyph_index < 0xFF80)
624 else if ((int) client_data == 2 && glyph_index < 0xF000)
625 glyph_index = (glyph_index + 0x1000) & 0xF000;
626 else if ((int) client_data == 3 && glyph_index < 0xF000)
627 glyph_index = 0xFF80;
628 if (glyph_index != old_glyph_index)
629 update_glyph_area ();
633 CharmapProc (Widget w, XtPointer client_data, XtPointer call_data)
635 if (charmap_index == (int) client_data)
637 charmap_index = (int) client_data;
638 if (charmap_index >= 0)
639 FT_Set_Charmap (face, face->charmaps[charmap_index]);
640 update_glyph_area ();
644 RenderProc (Widget w, XtPointer client_data, XtPointer call_data)
646 if ((int) client_data < 0)
648 if (glyph_rec.n_glyphs > 0)
650 if ((int) client_data == -2)
651 glyph_rec.n_glyphs--;
653 glyph_rec.n_glyphs = 0;
654 update_render_area ();
657 else if (glyph_rec.n_glyphs < 64)
659 int index = glyph_index + (int) client_data;
661 if (charmap_index >= 0)
662 index = FT_Get_Char_Index (face, (FT_ULong) index);
663 if (bitmap[index].pixmap)
665 glyph_rec.codes[glyph_rec.n_glyphs] = glyph_index + (int) client_data;
666 glyph_rec.glyphs[glyph_rec.n_glyphs++] = index;
667 update_render_area ();
673 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
677 reversed = ! reversed;
679 XtSetArg (arg[0], XtNlabel, "L<-R");
681 XtSetArg (arg[0], XtNlabel, "L->R");
682 XtSetValues (w, arg, 1);
687 AltSubstProc (Widget w, XtPointer client_data, XtPointer call_data)
689 do_alternate_subst = ! do_alternate_subst;
694 FeatureProc (Widget w, XtPointer client_data, XtPointer call_data)
696 FeatureRec *rec = (FeatureRec *) client_data;
703 XtSetArg (arg[0], XtNlabel, &label);
704 XtGetValues (w, arg, 1);
705 if (! strcmp (label, "all"))
707 else if (! strcmp (label, "none"))
711 for (idx = 0; idx < rec->langsys->FeatureCount; idx++)
712 if (rec->features[idx].w == w)
714 if (idx == rec->langsys->FeatureCount)
721 for (i = j = 0; j < rec->langsys->FeatureCount; j++)
723 int index = rec->langsys->FeatureIndex[j];
726 = rec->gsub_gpos->FeatureList.Feature[index].FeatureTag;
727 rec->features[j].on = on;
732 OTF_Tag tag = rec->features[idx].tag;
735 if (rec->features[i].on)
738 j < rec->langsys->FeatureCount && rec->features[j].on; j++)
739 rec->features[j - 1].tag = rec->features[j].tag;
740 rec->features[j - 1].tag = tag;
741 rec->features[j - 1].on = 0;
745 for (j = i + 1; i > 0 && ! rec->features[i - 1].on; i--)
746 rec->features[i].tag = rec->features[i - 1].tag;
747 rec->features[i].tag = tag;
748 rec->features[i].on = 1;
756 if (rec->features[i].on)
758 XtSetArg (arg[0], XtNborderWidth, 3);
759 XtSetArg (arg[1], XtNinternalHeight, 2);
760 XtSetArg (arg[2], XtNinternalWidth, 2);
764 XtSetArg (arg[0], XtNborderWidth, 1);
765 XtSetArg (arg[1], XtNinternalHeight, 4);
766 XtSetArg (arg[2], XtNinternalWidth, 4);
768 OTF_tag_name (rec->features[i].tag, str);
769 XtSetArg (arg[3], XtNlabel, str);
770 XtSetValues (rec->features[i].w, arg, 4);
776 setup_feature_rec (FeatureRec *rec)
782 if (! rec->gsub_gpos)
784 for (i = 0; i < rec->gsub_gpos->ScriptList.ScriptCount; i++)
785 if (rec->gsub_gpos->ScriptList.Script[i].ScriptTag == script_tag)
787 OTF_Script *script = rec->gsub_gpos->ScriptList.Script + i;
791 for (j = 0; j < script->LangSysCount; j++)
792 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
794 rec->langsys = script->LangSys + j;
799 rec->langsys = &rec->gsub_gpos->ScriptList.Script[i].DefaultLangSys;
807 XtSetArg (arg[0], XtNborderWidth, 1);
808 XtSetArg (arg[1], XtNinternalHeight, 4);
809 XtSetArg (arg[2], XtNinternalWidth, 4);
810 XtSetArg (arg[3], XtNborderColor, foreground);
811 XtSetArg (arg[4], XtNsensitive, True);
812 for (i = 0; i < rec->langsys->FeatureCount; i++)
814 OTF_Feature *feature = rec->gsub_gpos->FeatureList.Feature;
815 int index = rec->langsys->FeatureIndex[i];
818 if (! rec->features[i].w)
820 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
821 rec->parent, arg, 0);
822 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
823 rec->features[i].w = w;
826 rec->features[i].tag = feature[index].FeatureTag;
827 rec->features[i].on = 0;
828 OTF_tag_name (rec->features[i].tag, label);
829 XtSetArg (arg[5], XtNlabel, label);
830 XtSetValues (rec->features[i].w, arg, 6);
833 XtSetArg (arg[0], XtNborderColor, background);
834 XtSetArg (arg[1], XtNsensitive, False);
835 XtSetArg (arg[2], XtNlabel, " ");
836 for (; i < rec->num_features; i++)
838 if (! rec->features[i].w)
840 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
841 rec->parent, arg, 0);
842 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
843 rec->features[i].w = w;
845 XtSetValues (rec->features[i].w, arg, 3);
850 compose_script_langsys (OTF_Tag script, OTF_Tag langsys, char *name)
852 OTF_tag_name (script, name);
856 OTF_tag_name (langsys, name + 5);
863 decompose_script_langsys (OTF_Tag *script, OTF_Tag *langsys, char *name)
865 *script = OTF_tag (name);
867 *langsys = OTF_tag (name + 5);
873 ScriptProc (Widget w, XtPointer client_data, XtPointer call_data)
876 OTF_Tag script, langsys;
879 XtSetArg (arg[0], XtNlabel, &name);
880 XtGetValues (w, arg, 1);
881 decompose_script_langsys (&script, &langsys, name);
882 if (script_tag == script && langsys_tag == langsys)
885 langsys_tag = langsys;
886 setup_feature_rec (&gsub);
887 setup_feature_rec (&gpos);
892 create_otf_script_widgets (Widget prev)
904 XtSetArg (arg[0], XtNborderWidth, 0);
905 XtSetArg (arg[1], XtNleft, XawChainLeft);
906 XtSetArg (arg[2], XtNright, XawChainLeft);
907 XtSetArg (arg[3], XtNtop, XawChainTop);
908 XtSetArg (arg[4], XtNbottom, XawChainTop);
909 XtSetArg (arg[5], XtNfromVert, prev);
910 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
911 prev = XtCreateManagedWidget ("Script", boxWidgetClass, render_area, arg, 7);
912 XtCreateManagedWidget ("script(langsys)", labelWidgetClass, prev, arg, 1);
916 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
917 n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
919 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
920 n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
921 script_langsys = alloca ((sizeof script_langsys[0]) * n);
925 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
927 OTF_Tag tag = otf->gsub->ScriptList.Script[i].ScriptTag;
929 script_langsys[n].script = tag;
930 script_langsys[n++].langsys = 0;
932 < otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount)
934 = otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount;
935 for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
937 script_langsys[n].script = tag;
938 script_langsys[n++].langsys
939 = otf->gsub->ScriptList.Script[i].LangSysRecord[j].LangSysTag;
941 < otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount)
943 = otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount;
946 gsub.num_features = nfeatures;
949 gsub.num_features = nfeatures;
950 gsub.features = malloc ((sizeof (FeatureElement)) * nfeatures);
951 memset (gsub.features, 0, (sizeof (FeatureElement)) * nfeatures);
956 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
958 OTF_Tag tag = otf->gpos->ScriptList.Script[i].ScriptTag;
962 < otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount)
964 = otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount;
965 for (k = 0; k < prev_n; k++)
966 if (tag == script_langsys[k].script)
970 script_langsys[n].script = tag;
971 script_langsys[n++].langsys = 0;
973 for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
979 OTF_Script *script = otf->gsub->ScriptList.Script + i;
981 for (l = k; l < prev_n && tag == script_langsys[l].script; l++)
982 if (script->LangSysRecord[j].LangSysTag
983 == script_langsys[l].langsys)
990 script_langsys[n].script = tag;
991 script_langsys[n++].langsys = 0;
994 < otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount)
996 = otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount;
1002 gpos.num_features = nfeatures;
1003 gpos.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1004 memset (gpos.features, 0, (sizeof (FeatureElement)) * nfeatures);
1010 script_tag = script_langsys[0].script;
1011 langsys_tag = script_langsys[0].langsys;
1012 compose_script_langsys (script_tag, langsys_tag, name);
1016 XtSetArg (arg[0], XtNforeground, background);
1017 XtSetArg (arg[1], XtNbackground, foreground);
1018 XtCreateManagedWidget (name, labelWidgetClass, prev, arg, 2);
1022 XtSetArg (arg[0], XtNstate, True);
1023 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1024 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1025 XtSetArg (arg[0], XtNradioGroup, w);
1026 for (i = 1; i < n; i++)
1028 compose_script_langsys (script_langsys[i].script,
1029 script_langsys[i].langsys, name);
1030 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1031 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1039 create_otf_widgets (Widget prev, FeatureRec *rec)
1044 XtSetArg (arg[0], XtNborderWidth, 0);
1045 XtSetArg (arg[1], XtNleft, XawChainLeft);
1046 XtSetArg (arg[2], XtNright, XawChainLeft);
1047 XtSetArg (arg[3], XtNtop, XawChainTop);
1048 XtSetArg (arg[4], XtNbottom, XawChainTop);
1049 XtSetArg (arg[5], XtNfromVert, prev);
1050 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1051 prev = XtCreateManagedWidget (rec->label, boxWidgetClass, render_area,
1053 XtCreateManagedWidget (rec->label, labelWidgetClass, prev, arg, 1);
1054 XtSetArg (arg[0], XtNborderWidth, 1);
1055 XtSetArg (arg[1], XtNinternalHeight, 4);
1056 XtSetArg (arg[2], XtNinternalWidth, 4);
1057 w = XtCreateManagedWidget ("all", commandWidgetClass, prev, arg, 3);
1058 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1059 w = XtCreateManagedWidget ("none", commandWidgetClass, prev, arg, 3);
1060 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1063 setup_feature_rec (rec);
1070 String quit_action = "<KeyPress>q: set() notify() unset()";
1071 String FIRST_action = "<KeyPress>f: set() notify() unset()\n\
1072 <KeyPress>Home: set() notify() unset()";
1073 String PREV_action = "Shift<KeyPress>p: set() notify() unset()\n\
1074 <KeyPress>Up: set() notify() unset()";
1075 String prev_action = "~Shift<KeyPress>p: set() notify() unset()\n\
1076 <KeyPress>Left: set() notify() unset()";
1077 String next_action = "~Shift<KeyPress>n: set() notify() unset()\n\
1078 <KeyPress>Right: set() notify() unset()";
1079 String NEXT_action = "Shift<KeyPress>n: set() notify() unset()\n\
1080 <KeyPress>Down: set() notify() unset()";
1081 String LAST_action = "<KeyPress>l: set() notify() unset()\n\
1082 <KeyPress>End: set() notify() unset()";
1086 String trans = "<Expose>: Expose()";
1088 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans));
1089 frame = XtCreateManagedWidget ("frame", formWidgetClass, shell, arg, 1);
1091 XtSetArg (arg[0], XtNleft, XawChainLeft);
1092 XtSetArg (arg[1], XtNright, XawChainLeft);
1093 XtSetArg (arg[2], XtNtop, XawChainTop);
1094 XtSetArg (arg[3], XtNbottom, XawChainTop);
1095 XtSetArg (arg[4], XtNborderWidth, 0);
1096 XtSetArg (arg[5], XtNorientation, XtorientHorizontal);
1097 command_area = XtCreateManagedWidget ("command-area", boxWidgetClass,
1099 XtSetArg (arg[6], XtNfromVert, command_area);
1100 navi_area = XtCreateManagedWidget ("navi-area", boxWidgetClass,
1102 XtSetArg (arg[4], XtNborderWidth, 0);
1103 XtSetArg (arg[5], XtNfromVert, navi_area);
1104 XtSetArg (arg[6], XtNdefaultDistance, 0);
1105 glyph_area = XtCreateManagedWidget ("glyph-area", formWidgetClass,
1107 XtSetArg (arg[5], XtNfromVert, glyph_area);
1108 render_area = XtCreateManagedWidget ("render-area", formWidgetClass,
1111 XtSetArg (arg[0], XtNaccelerators, XtParseAcceleratorTable (quit_action));
1112 quit = XtCreateManagedWidget ("Quit", commandWidgetClass,
1113 command_area, arg, 1);
1114 XtAddCallback (quit, XtNcallback, QuitProc, NULL);
1116 dump = XtCreateManagedWidget ("DumpImage", commandWidgetClass,
1117 command_area, arg, 1);
1118 XtAddCallback (dump, XtNcallback, DumpProc, NULL);
1120 XtSetArg (arg[0], XtNborderWidth, 0);
1121 XtSetArg (arg[1], XtNwidth, 10);
1122 XtCreateManagedWidget ("spacer", boxWidgetClass, command_area, arg, 2);
1124 charmap = alloca (sizeof (Widget) * (face->num_charmaps + 1));
1125 XtSetArg (arg[0], XtNstate, True);
1126 charmap[0] = XtCreateManagedWidget (charmap_rec[0].name, toggleWidgetClass,
1127 command_area, arg, 1);
1128 XtAddCallback (charmap[0], XtNcallback, CharmapProc, (XtPointer) -1);
1129 XtSetArg (arg[0], XtNradioGroup, charmap[0]);
1130 for (i = 0; i < face->num_charmaps; i++)
1132 charmap[i + 1] = XtCreateManagedWidget (charmap_rec[i + 1].name,
1134 command_area, arg, 1);
1135 XtAddCallback (charmap[i + 1], XtNcallback, CharmapProc, (XtPointer) i);
1138 XtSetArg (arg[0], XtNlabel, " |< (f)");
1139 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (FIRST_action));
1140 FIRST = XtCreateManagedWidget ("FIRST", commandWidgetClass,
1142 XtAddCallback (FIRST, XtNcallback, GlyphProc, (XtPointer) -3);
1143 XtSetArg (arg[0], XtNlabel, "<< (P)");
1144 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (PREV_action));
1145 PREV = XtCreateManagedWidget ("PREV", commandWidgetClass,
1147 XtAddCallback (PREV, XtNcallback, GlyphProc, (XtPointer) -2);
1148 XtSetArg (arg[0], XtNlabel, "< (p)");
1149 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (prev_action));
1150 prev = XtCreateManagedWidget ("prev", commandWidgetClass,
1152 XtAddCallback (prev, XtNcallback, GlyphProc, (XtPointer) -1);
1153 XtSetArg (arg[0], XtNlabel, " 0000 ");
1154 range = XtCreateManagedWidget ("range", labelWidgetClass,
1156 XtSetArg (arg[0], XtNforeground, &foreground);
1157 XtSetArg (arg[1], XtNbackground, &background);
1158 XtGetValues (range, arg, 2);
1160 XtSetArg (arg[0], XtNlabel, "> (n)");
1161 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (next_action));
1162 next = XtCreateManagedWidget ("next", commandWidgetClass,
1164 XtAddCallback (next, XtNcallback, GlyphProc, (XtPointer) 1);
1165 XtSetArg (arg[0], XtNlabel, ">> (N)");
1166 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (NEXT_action));
1167 NEXT = XtCreateManagedWidget ("NEXT", commandWidgetClass,
1169 XtAddCallback (NEXT, XtNcallback, GlyphProc, (XtPointer) 2);
1170 XtSetArg (arg[0], XtNlabel, ">| (l)");
1171 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (LAST_action));
1172 LAST = XtCreateManagedWidget ("LAST", commandWidgetClass,
1174 XtAddCallback (LAST, XtNcallback, GlyphProc, (XtPointer) 3);
1176 XtSetArg (arg[0], XtNleft, XawChainLeft);
1177 XtSetArg (arg[1], XtNright, XawChainLeft);
1178 XtSetArg (arg[2], XtNtop, XawChainTop);
1179 XtSetArg (arg[3], XtNbottom, XawChainTop);
1181 for (i = 0; i < 8; i++)
1187 sprintf (str, "%XX", i);
1188 XtSetArg (arg[n], XtNheight, glyph_height + 5), n++;
1189 XtSetArg (arg[n], XtNlabel, str), n++;
1190 XtSetArg (arg[n], XtNborderWidth, 0), n++;
1192 XtSetArg (arg[n], XtNfromVert, w), n++;
1193 head = XtCreateManagedWidget (str, labelWidgetClass, glyph_area, arg, n);
1194 index_label[i] = head;
1195 for (j = 0; j < 16; j++)
1201 XtSetArg (arg[n], XtNfromVert, w), n++;
1203 XtSetArg (arg[n], XtNfromHoriz, head), n++;
1205 XtSetArg (arg[n], XtNfromHoriz, glyph[k - 1]), n++;
1206 XtSetArg (arg[n], XtNbitmap, none_pixmap), n++;
1207 glyph[k] = XtCreateManagedWidget ("glyph", commandWidgetClass,
1208 glyph_area, arg, n);
1209 XtAddCallback (glyph[k], XtNcallback, RenderProc, (XtPointer) k);
1213 /* 10 = (1 (border_width) + 4 (inner_width)) * 2 */
1214 XtSetArg(arg[4], XtNwidth, glyph_width + 10);
1215 XtSetArg (arg[5], XtNfromVert, glyph[112]);
1216 XtSetArg (arg[6], XtNfromHoriz, w);
1217 XtSetArg (arg[7], XtNborderWidth, 0);
1219 for (j = 0; j < 16; j++)
1223 sprintf (str, "X%X", j);
1224 XtSetArg (arg[8], XtNlabel, str);
1225 w = XtCreateManagedWidget ("idx", labelWidgetClass, glyph_area, arg, 9);
1226 XtSetArg (arg[6], XtNfromHoriz, w);
1229 XtSetArg (arg[0], XtNleft, XawChainLeft);
1230 XtSetArg (arg[1], XtNright, XawChainLeft);
1231 XtSetArg (arg[2], XtNtop, XawChainTop);
1232 XtSetArg (arg[3], XtNbottom, XawChainTop);
1233 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1234 XtSetArg (arg[5], XtNborderWidth, 0);
1235 w = XtCreateManagedWidget ("clear-box", boxWidgetClass, render_area, arg, 6);
1236 clear = XtCreateManagedWidget ("clear", commandWidgetClass, w, arg, 0);
1237 XtAddCallback (clear, XtNcallback, RenderProc, (XtPointer) -1);
1238 del = XtCreateManagedWidget ("delete", commandWidgetClass, w, arg, 0);
1239 XtAddCallback (del, XtNcallback, RenderProc, (XtPointer) -2);
1240 bidi = XtCreateManagedWidget ("L->R", toggleWidgetClass, w, arg, 0);
1241 XtAddCallback (bidi, XtNcallback, BidiProc, NULL);
1242 alt_subst = XtCreateManagedWidget ("AltSubst", toggleWidgetClass, w, arg, 0);
1243 XtAddCallback (alt_subst, XtNcallback, AltSubstProc, NULL);
1245 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1246 XtSetArg (arg[5], XtNborderWidth, 0);
1247 XtSetArg (arg[6], XtNfromVert, w);
1248 raw = XtCreateManagedWidget ("raw", boxWidgetClass, render_area, arg, 7);
1250 XtSetArg (arg[0], XtNborderWidth, 0);
1251 XtSetArg (arg[1], XtNlabel, "raw: ");
1252 raw_label = XtCreateManagedWidget ("raw-label", labelWidgetClass,
1254 XtSetArg (arg[1], XtNbitmap, raw_pixmap);
1255 raw_image = XtCreateManagedWidget ("raw-image", labelWidgetClass,
1260 OTF_get_table (otf, "GSUB");
1261 OTF_get_table (otf, "GPOS");
1262 w = create_otf_script_widgets (w);
1265 gsub.label = "GSUB";
1266 gsub.gsub_gpos = otf->gsub;
1267 w = create_otf_widgets (w, &gsub);
1271 gpos.label = "GPOS";
1272 gpos.gsub_gpos = otf->gpos;
1273 w = create_otf_widgets (w, &gpos);
1277 XtSetArg (arg[6], XtNfromVert, w);
1278 seq = XtCreateManagedWidget ("seq", boxWidgetClass, render_area, arg, 7);
1279 XtSetArg (arg[0], XtNborderWidth, 0);
1280 XtSetArg (arg[1], XtNlabel, "seq: ");
1281 seq_label = XtCreateManagedWidget ("seq-label", labelWidgetClass,
1283 XtSetArg (arg[1], XtNbitmap, seq_pixmap);
1284 seq_image = XtCreateManagedWidget ("seq-image", labelWidgetClass,
1286 XtInstallAllAccelerators (shell, shell);
1290 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1292 XTextProperty text_prop;
1293 char *pname = "otfview";
1294 char *fname = basename (filename);
1295 char *name = alloca (strlen (fname) + 3 + strlen (pname) + 1);
1297 sprintf (name, "%s - %s", pname, fname);
1298 text_prop.value = (unsigned char *) name;
1299 text_prop.encoding = XA_STRING;
1300 text_prop.format = 8;
1301 text_prop.nitems = strlen (name);
1302 XSetWMName (display, XtWindow (shell), &text_prop);
1305 /* Format MSG by FMT and print the result to the stderr, and exit. */
1307 #define FATAL_ERROR(fmt, arg) \
1309 fprintf (stderr, fmt, arg); \
1314 x_error_handler (Display *display, XErrorEvent *error)
1321 main (int argc, char **argv)
1323 XtActionsRec actions[] = { {"Expose", ExposeProc} };
1327 OTF_GlyphString gstring;
1332 int fixed_pixel_size = 0;
1335 pixel_size = DEFAULT_PIXEL_SIZE;
1337 char *str = getenv ("PIXEL_SIZE");
1339 if (str && (i = atoi (str)) > 0)
1342 fixed_pixel_size = 1;
1346 gstring.size = gstring.used = 256;
1347 g = calloc (256, sizeof (OTF_Glyph));
1350 shell = XtOpenApplication (&context, "OTFView", NULL, 0, &argc, argv, NULL,
1351 shellWidgetClass, arg, 0);
1352 display = XtDisplay (shell);
1353 /*XSynchronize (display, True);*/
1354 XSetErrorHandler (x_error_handler);
1355 display_width = DisplayWidth (display,
1356 XScreenNumberOfScreen (XtScreen (shell)));
1357 font = XLoadQueryFont (display, DEFAULT_FONT_NAME);
1359 font = XLoadQueryFont (display, "fixed");
1361 if (argc != 2 || !strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
1363 fprintf (stderr, "Usage: %s [ X-OPTION ... ] OTF-FILE\n",
1364 basename (argv[0]));
1366 " Pixel size is decided by the environment variable PIXEL_SIZE ((default %d).\n", DEFAULT_PIXEL_SIZE);
1370 if (strstr (filename, ".ttf")
1371 || strstr (filename, ".TTF")
1372 || strstr (filename, ".otf")
1373 || strstr (filename, ".OTF"))
1375 otf = OTF_open (filename);
1377 || OTF_get_table (otf, "head") < 0
1378 || OTF_get_table (otf, "cmap") < 0
1379 || (OTF_check_table (otf, "GSUB") < 0
1380 && OTF_check_table (otf, "GPOS") < 0))
1384 if ((err = FT_Init_FreeType (&library)))
1385 FATAL_ERROR ("%s\n", "FT_Init_FreeType: error");
1386 err = FT_New_Face (library, filename, 0, &face);
1387 if (err == FT_Err_Unknown_File_Format)
1388 FATAL_ERROR ("%s\n", "FT_New_Face: unknown file format");
1390 FATAL_ERROR ("%s\n", "FT_New_Face: unknown error");
1391 if ((err = FT_Set_Pixel_Sizes (face, 0, pixel_size)))
1392 FATAL_ERROR ("%s\n", "FT_Set_Pixel_Sizes: error");
1398 filename = basename (filename);
1399 sprintf (title, "%s family:%s style:%s",
1400 filename, face->family_name, face->style_name);
1401 XtSetArg (arg[0], XtNtitle, title);
1402 XtSetValues (shell, arg, 1);
1405 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1406 * pixel_size / face->units_per_EM);
1407 if (! fixed_pixel_size && glyph_width * 16 > display_width * 0.8)
1409 pixel_size = (pixel_size * display_width * 0.8 / 16 / glyph_width);
1410 FT_Set_Pixel_Sizes (face, 0, pixel_size);
1411 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1412 * pixel_size / face->units_per_EM);
1414 if (glyph_width < FONT_WIDTH * 4)
1415 glyph_width = FONT_WIDTH * 4;
1417 glyph_height = ((face->bbox.yMax - face->bbox.yMin)
1418 * pixel_size / face->units_per_EM);
1420 glyph_x = - (face->bbox.xMin * pixel_size / face->units_per_EM);
1421 glyph_y = face->bbox.yMax * pixel_size / face->units_per_EM;
1422 none_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1423 glyph_width, glyph_height, 1);
1426 unsigned long valuemask = GCFunction | GCLineWidth;
1429 gc = XCreateGC (display, none_pixmap, (unsigned long) 0, NULL);
1430 values.function = GXset;
1431 values.line_width = 1;
1432 gc_set = XCreateGC (display, none_pixmap, valuemask, &values);
1433 values.function = GXor;
1434 gc_or = XCreateGC (display, none_pixmap, valuemask, &values);
1435 values.function = GXcopyInverted;
1436 gc_inv = XCreateGC (display, none_pixmap, valuemask, &values);
1439 XFillRectangle (display, none_pixmap, gc, 0, 0,
1440 glyph_width, glyph_height);
1441 XDrawString (display, none_pixmap, gc_inv,
1442 (glyph_width - XTextWidth (font, "none", 4)) / 2,
1443 glyph_height / 2, "none", 4);
1445 render_width = (glyph_width + 4) * 15 + 1;
1446 render_height = glyph_height + 2;
1448 charmap_rec[0].platform_id = -1;
1449 charmap_rec[0].encoding_id = -1;
1450 strcpy (charmap_rec[0].name, "no charmap");
1452 for (i = 0; i < face->num_charmaps; i++)
1454 charmap_rec[i + 1].platform_id = face->charmaps[i]->platform_id;
1455 charmap_rec[i + 1].encoding_id = face->charmaps[i]->encoding_id;
1456 sprintf (charmap_rec[i + 1].name, "%d-%d",
1457 charmap_rec[i + 1].platform_id, charmap_rec[i + 1].encoding_id);
1458 if (face->charmaps[i]->platform_id == 0
1459 || (face->charmaps[i]->platform_id == 3
1460 && face->charmaps[i]->encoding_id == 1))
1461 strcat (charmap_rec[i + 1].name, " (unicode)");
1462 else if (face->charmaps[i]->platform_id == 1
1463 && face->charmaps[i]->encoding_id == 0)
1464 strcat (charmap_rec[i + 1].name, " (apple-roman)");
1467 raw_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1468 render_width, render_height, 1);
1469 seq_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1470 render_width, render_height, 1);
1472 memset (bitmap, 0, sizeof (bitmap));
1476 update_glyph_area ();
1477 update_render_area ();
1479 XtAppAddActions (context, actions, XtNumber (actions));
1480 XtRealizeWidget (shell);
1481 XtAppMainLoop (context);
1486 #else /* not HAVE_X11_XAW_COMMAND_H */
1489 main (int argc, char **argv)
1492 "Building of this program failed (lack of some header files)\n");