1 /* otfview.c -- View glyphs of OpenType fonts.
3 Copyright (C) 2003, 2004
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);
214 if (! bitmap[index].pixmap)
215 create_pixmap (index);
216 XtSetArg (arg[0], XtNbitmap, bitmap[index].pixmap);
217 XtSetValues (glyph[i], arg, 1);
220 msb = (glyph_index >> 7) % 2 ? 8 : 0;
221 for (i = 0; i < 8; i++)
225 sprintf (str, "%XX", i | msb );
226 XtSetArg (arg[0], XtNheight, glyph_height + 5);
227 XtSetArg (arg[1], XtNlabel, str);
228 XtSetValues (index_label[i], arg, 2);
231 sprintf (buf, " %04X-%04X ", glyph_index, glyph_index + 0x7F);
232 XtSetArg (arg[0], XtNlabel, buf);
233 XtSetValues (range, arg, 1);
237 get_features (OTF_FeatureList *list, FeatureRec *rec)
242 if (! rec->langsys || ! rec->features || ! rec->features[0].on)
244 for (i = n = 0; i < rec->langsys->FeatureCount; i++)
246 if (rec->features[i].on)
251 if (i == rec->langsys->FeatureCount)
257 str = malloc (n * 5);
258 for (i = 0, p = str; i < n; i++, p += 5)
260 OTF_tag_name (rec->features[i].tag, p);
268 #define DEVICE_DELTA(table, size) \
269 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
270 ? (table).DeltaValue[(size) >= (table).StartSize] \
274 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
275 OTF_Glyph *g, int *x, int *y)
277 if (anchor->AnchorFormat == 2)
280 int ap = anchor->f.f1.AnchorPoint;
282 FT_Load_Glyph (ft_face, (FT_UInt) g->glyph_id, FT_LOAD_MONOCHROME);
283 outline = &ft_face->glyph->outline;
284 if (ap < outline->n_points)
286 *x = outline->points[ap].x;
287 *y = outline->points[ap].y;
290 else if (anchor->AnchorFormat == 3)
292 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, pixel_size);
293 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, pixel_size);
301 OTF_GlyphString gstring;
302 OTF_Glyph *g, *prev, *base, *mark;
304 int len = glyph_rec.n_glyphs;
306 int unitsPerEm = face->units_per_EM;
308 gstring.size = gstring.used = len;
309 gstring.glyphs = malloc (sizeof (OTF_Glyph) * len);
310 memset (gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
311 for (i = 0; i < len; i++)
312 gstring.glyphs[i].c = gstring.glyphs[i].glyph_id = glyph_rec.glyphs[i];
314 XFillRectangle (display, seq_pixmap, gc, 0, 0, render_width, render_height);
315 XDrawLine (display, seq_pixmap, gc_set, 0, glyph_y, render_width, glyph_y);
320 OTF_drive_gdef (otf, &gstring);
323 str = get_features (&otf->gsub->FeatureList, &gsub);
326 if (do_alternate_subst)
327 OTF_drive_gsub_alternate (otf, &gstring, NULL, NULL, str);
329 OTF_drive_gsub (otf, &gstring, NULL, NULL, str);
335 str = get_features (&otf->gpos->FeatureList, &gpos);
338 OTF_drive_gpos (otf, &gstring, NULL, NULL, str);
349 for (prev = gstring.glyphs, g = gstring.glyphs + gstring.used - 1;
350 prev < g; prev++, g--)
351 temp = *prev, *prev = *g, *g = temp;
352 for (g = gstring.glyphs; g < gstring.glyphs + gstring.used; g++)
353 if (g->GlyphClass == 3)
357 while (g < gstring.glyphs + gstring.used && g->GlyphClass == 3)
359 for (g0 = g; prev < g0; prev++, g0--)
360 temp = *prev, *prev = *g, *g = temp;
366 for (i = 0, x = glyph_x, prev = NULL, g = gstring.glyphs;
367 i < gstring.used; i++, prev = g++)
369 BitmapRec *bmp = bitmap + gstring.glyphs[i].glyph_id;
370 int xoff = 0, yoff = 0;
372 int advance = bmp->advance;
376 create_pixmap (gstring.glyphs[i].glyph_id);
379 advance = bmp->advance;
381 switch (g->positioning_type)
388 int format = g->f.f1.format;
390 if (format & OTF_XPlacement)
391 xoff = g->f.f1.value->XPlacement * pixel_size / unitsPerEm;
392 if (format & OTF_XPlaDevice)
393 xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, pixel_size);
394 if (format & OTF_YPlacement)
395 yoff = g->f.f1.value->YPlacement * pixel_size / unitsPerEm;
396 if (format & OTF_YPlaDevice)
397 yoff += DEVICE_DELTA (g->f.f1.value->YPlaDevice, pixel_size);
398 if (format & OTF_XAdvance)
399 advance += g->f.f1.value->XAdvance * pixel_size / unitsPerEm;
400 if (format & OTF_XAdvDevice)
401 advance += DEVICE_DELTA (g->f.f1.value->XAdvDevice, pixel_size);
406 /* Not yet supported. */
412 prev_width = base_width;
413 goto label_adjust_anchor;
414 default: /* i.e. case 6 */
421 int base_x, base_y, mark_x, mark_y;
423 base_x = g->f.f4.base_anchor->XCoordinate * pixel_size / unitsPerEm;
424 base_y = g->f.f4.base_anchor->YCoordinate * pixel_size / unitsPerEm;
425 mark_x = g->f.f4.mark_anchor->XCoordinate * pixel_size / unitsPerEm;
426 mark_y = g->f.f4.mark_anchor->YCoordinate * pixel_size / unitsPerEm;
428 if (g->f.f4.base_anchor->AnchorFormat != 1)
429 adjust_anchor (g->f.f4.base_anchor, face, prev, &base_x, &base_y);
430 if (g->f.f4.mark_anchor->AnchorFormat != 1)
431 adjust_anchor (g->f.f4.mark_anchor, face, g, &mark_x, &mark_y);
432 xoff = (base_x - prev_width) - mark_x;
433 yoff = base_y - mark_y;
437 XCopyArea (display, bmp->pixmap, seq_pixmap, gc_or,
438 glyph_x + bmp->x, glyph_y + bmp->y, bmp->width, bmp->height,
439 x + bmp->x + xoff, glyph_y + bmp->y - yoff);
442 if (g->GlyphClass == OTF_GlyphClass0)
443 base = mark = g, base_width = advance;
444 else if (g->GlyphClass == OTF_GlyphClassMark)
447 base = g, base_width = advance;
449 free (gstring.glyphs);
451 XtSetArg (arg[0], XtNbitmap, seq_pixmap);
452 XtSetValues (seq_image, arg, 1);
457 update_render_area ()
463 XFillRectangle (display, raw_pixmap, gc, 0, 0, render_width, render_height);
464 for (i = 0, x = glyph_x; i < glyph_rec.n_glyphs; i++)
466 BitmapRec *bmp = bitmap + glyph_rec.glyphs[i];
469 XCopyArea (display, bmp->pixmap, raw_pixmap, gc,
470 0, 0, glyph_width, glyph_height,
471 (glyph_width + 4) * i + 1, 1);
472 XDrawRectangle (display, raw_pixmap, gc_set,
473 (glyph_width + 4) * i, 0,
474 glyph_width + 1, glyph_height + 1);
475 XDrawLine (display, raw_pixmap, gc_set,
476 (glyph_width + 4) * i + 1 + glyph_x, 1,
477 (glyph_width + 4) * i + 1 + glyph_x, glyph_height + 1);
478 XDrawLine (display, raw_pixmap, gc_set,
479 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance, 1,
480 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance,
483 sprintf (buf, "%04X", glyph_rec.codes[i]);
484 XDrawString (display, raw_pixmap, gc_inv,
485 (glyph_width + 1) * i + 1
486 + (glyph_width - XTextWidth (font, buf, 4)) / 2,
487 glyph_height + 2 + FONT_HEIGHT, buf, 4);
489 XtSetArg (arg[0], XtNbitmap, raw_pixmap);
490 XtSetValues (raw_image, arg, 1);
495 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
497 XtAppSetExitFlag (XtWidgetToApplicationContext (w));
501 DumpProc (Widget w, XtPointer client_data, XtPointer call_data)
503 int g_width, g_height, g_x, g_y, pix_width, pix_height;
504 int margin = 20 * 300 / 25.4;
505 int a4_width = 210 * 300 / 25.4 - margin * 2;
506 int a4_height = 297 * 300 / 25.4 - margin * 2;
509 XImage ximage, *image;
514 FT_Set_Pixel_Sizes (face, 0, size);
515 g_width = ((face->bbox.xMax - face->bbox.xMin) * size / face->units_per_EM);
516 g_height = ((face->bbox.yMax - face->bbox.yMin) * size / face->units_per_EM);
517 pix_width = (g_width + 1) * 16 + margin + 1;
518 pix_height = (g_height + 1 + FONT_HEIGHT) * 16 + margin + 1;
519 while (pix_width > a4_width || pix_height > a4_height)
522 FT_Set_Pixel_Sizes (face, 0, size);
523 g_width = ((face->bbox.xMax - face->bbox.xMin)
524 * size / face->units_per_EM);
525 g_height = ((face->bbox.yMax - face->bbox.yMin)
526 * size / face->units_per_EM);
527 pix_width = (g_width + 1) * 16 + margin + 1;
528 pix_height = (g_height + 1 + FONT_HEIGHT) * 16 + margin + 1;
531 g_x = - (face->bbox.xMin * size / face->units_per_EM);
532 g_y = face->bbox.yMax * size / face->units_per_EM;
533 for (i = 0; i < 0xFF; i++)
537 if (charmap_index >= 0)
538 idx = FT_Get_Char_Index (face, (FT_ULong) i);
541 if (FT_Load_Glyph (face, idx, FT_LOAD_RENDER | FT_LOAD_MONOCHROME) == 0)
543 if (g_x < - face->glyph->bitmap_left)
544 g_x = - face->glyph->bitmap_left;
545 if (g_y < face->glyph->bitmap_top)
546 g_y = face->glyph->bitmap_top;
548 < g_x + face->glyph->bitmap_left + face->glyph->bitmap.width)
550 = g_x + face->glyph->bitmap_left + face->glyph->bitmap.width;
552 < g_y - face->glyph->bitmap_top + face->glyph->bitmap.rows)
554 = g_y - face->glyph->bitmap_top + face->glyph->bitmap.rows;
557 pix_width = (g_width + 1) * 16 + margin + 1;
558 pix_height = (g_height + FONT_HEIGHT + 1) * 16 + margin + 1;
559 pixmap = XCreatePixmap (display,
560 RootWindow (display, DefaultScreen (display)),
561 pix_width, pix_height, 1);
562 XFillRectangle (display, pixmap, gc, 0, 0, pix_width, pix_height);
564 for (i = 0, x = margin; i <= 16; i++, x += g_width + 1)
565 XDrawLine (display, pixmap, gc_set, x, margin,
566 x, margin + (g_height + FONT_HEIGHT + 1) * 16);
567 for (i = 0, y = margin; i <= 16; i++, y += g_height + FONT_HEIGHT + 1)
568 XDrawLine (display, pixmap, gc_set, margin, y,
569 margin + (g_width + 1) * 16, y);
570 for (i = 0; i < 256; i++)
575 if (charmap_index >= 0)
576 idx = FT_Get_Char_Index (face, (FT_ULong) i);
579 x = margin + (g_width + 1) * (i % 16);
580 y = margin + (g_height + FONT_HEIGHT + 1) * (i / 16);
581 if (FT_Load_Glyph (face, idx, FT_LOAD_RENDER | FT_LOAD_MONOCHROME) == 0)
583 ximage.height = face->glyph->bitmap.rows;
584 ximage.width = face->glyph->bitmap.width;
586 ximage.bits_per_pixel = 1;
588 ximage.format = XYPixmap;
589 ximage.data = (char *) face->glyph->bitmap.buffer;
590 ximage.byte_order = MSBFirst;
591 ximage.bitmap_unit = 8;
592 ximage.bitmap_bit_order = MSBFirst;
593 ximage.bitmap_pad = 8;
594 ximage.bytes_per_line = face->glyph->bitmap.pitch;
595 XInitImage (&ximage);
596 XPutImage (display, pixmap, gc, &ximage, 0, 0,
597 x + g_x + face->glyph->bitmap_left,
598 y + g_y - face->glyph->bitmap_top,
599 ximage.width, ximage.height);
601 sprintf (str, "0x%02X", i);
602 XDrawString (display, pixmap, gc_inv,
603 x + (g_width - XTextWidth (font, str, 4))/ 2,
604 y + g_height + FONT_ASCENT, str, 4);
607 image = XGetImage (display, pixmap, 0, 0, pix_width, pix_height,
608 AllPlanes, XYPixmap);
611 char *name = alloca (strlen (filename) + 5);
614 sprintf (name, "%s.pbm", filename);
615 printf ("Writing %s ...", name);
616 fp = fopen (name, "w");
617 fprintf (fp, "P4\n%d %d\n", image->width, image->height);
618 bytes_per_line = (image->width + 7) / 8;
620 for (y = 0; y < image->height; y++, data += image->bytes_per_line)
621 fwrite (data, 1, bytes_per_line, fp);
625 FT_Set_Pixel_Sizes (face, 0, (int) pixel_size);
630 GlyphProc (Widget w, XtPointer client_data, XtPointer call_data)
632 int old_glyph_index = glyph_index;
634 if ((int) client_data == -3 && glyph_index > 0)
636 else if ((int) client_data == -2 && glyph_index > 0)
637 glyph_index = (glyph_index - 1) & 0xF000;
638 else if ((int) client_data == -1 && glyph_index > 0)
640 else if ((int) client_data == 1 && glyph_index < 0xFF80)
642 else if ((int) client_data == 2 && glyph_index < 0xF000)
643 glyph_index = (glyph_index + 0x1000) & 0xF000;
644 else if ((int) client_data == 3 && glyph_index < 0xF000)
645 glyph_index = 0xFF80;
646 if (glyph_index != old_glyph_index)
647 update_glyph_area ();
651 CharmapProc (Widget w, XtPointer client_data, XtPointer call_data)
653 if (charmap_index == (int) client_data)
655 charmap_index = (int) client_data;
656 if (charmap_index >= 0)
657 FT_Set_Charmap (face, face->charmaps[charmap_index]);
658 update_glyph_area ();
662 RenderProc (Widget w, XtPointer client_data, XtPointer call_data)
664 if ((int) client_data < 0)
666 if (glyph_rec.n_glyphs > 0)
668 if ((int) client_data == -2)
669 glyph_rec.n_glyphs--;
671 glyph_rec.n_glyphs = 0;
672 update_render_area ();
675 else if (glyph_rec.n_glyphs < 64)
677 int index = glyph_index + (int) client_data;
679 if (charmap_index >= 0)
680 index = FT_Get_Char_Index (face, (FT_ULong) index);
681 if (bitmap[index].pixmap)
683 glyph_rec.codes[glyph_rec.n_glyphs] = glyph_index + (int) client_data;
684 glyph_rec.glyphs[glyph_rec.n_glyphs++] = index;
685 update_render_area ();
691 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
695 reversed = ! reversed;
697 XtSetArg (arg[0], XtNlabel, "L<-R");
699 XtSetArg (arg[0], XtNlabel, "L->R");
700 XtSetValues (w, arg, 1);
705 AltSubstProc (Widget w, XtPointer client_data, XtPointer call_data)
707 do_alternate_subst = ! do_alternate_subst;
712 FeatureProc (Widget w, XtPointer client_data, XtPointer call_data)
714 FeatureRec *rec = (FeatureRec *) client_data;
721 XtSetArg (arg[0], XtNlabel, &label);
722 XtGetValues (w, arg, 1);
723 if (! strcmp (label, "all"))
725 else if (! strcmp (label, "none"))
729 for (idx = 0; idx < rec->langsys->FeatureCount; idx++)
730 if (rec->features[idx].w == w)
732 if (idx == rec->langsys->FeatureCount)
739 for (i = j = 0; j < rec->langsys->FeatureCount; j++)
741 int index = rec->langsys->FeatureIndex[j];
744 = rec->gsub_gpos->FeatureList.Feature[index].FeatureTag;
745 rec->features[j].on = on;
750 OTF_Tag tag = rec->features[idx].tag;
753 if (rec->features[i].on)
756 j < rec->langsys->FeatureCount && rec->features[j].on; j++)
757 rec->features[j - 1].tag = rec->features[j].tag;
758 rec->features[j - 1].tag = tag;
759 rec->features[j - 1].on = 0;
763 for (j = i + 1; i > 0 && ! rec->features[i - 1].on; i--)
764 rec->features[i].tag = rec->features[i - 1].tag;
765 rec->features[i].tag = tag;
766 rec->features[i].on = 1;
774 if (rec->features[i].on)
776 XtSetArg (arg[0], XtNborderWidth, 3);
777 XtSetArg (arg[1], XtNinternalHeight, 2);
778 XtSetArg (arg[2], XtNinternalWidth, 2);
782 XtSetArg (arg[0], XtNborderWidth, 1);
783 XtSetArg (arg[1], XtNinternalHeight, 4);
784 XtSetArg (arg[2], XtNinternalWidth, 4);
786 OTF_tag_name (rec->features[i].tag, str);
787 XtSetArg (arg[3], XtNlabel, str);
788 XtSetValues (rec->features[i].w, arg, 4);
794 setup_feature_rec (FeatureRec *rec)
800 if (! rec->gsub_gpos)
802 for (i = 0; i < rec->gsub_gpos->ScriptList.ScriptCount; i++)
803 if (rec->gsub_gpos->ScriptList.Script[i].ScriptTag == script_tag)
805 OTF_Script *script = rec->gsub_gpos->ScriptList.Script + i;
809 for (j = 0; j < script->LangSysCount; j++)
810 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
812 rec->langsys = script->LangSys + j;
817 rec->langsys = &rec->gsub_gpos->ScriptList.Script[i].DefaultLangSys;
825 XtSetArg (arg[0], XtNborderWidth, 1);
826 XtSetArg (arg[1], XtNinternalHeight, 4);
827 XtSetArg (arg[2], XtNinternalWidth, 4);
828 XtSetArg (arg[3], XtNborderColor, foreground);
829 XtSetArg (arg[4], XtNsensitive, True);
830 for (i = 0; i < rec->langsys->FeatureCount; i++)
832 OTF_Feature *feature = rec->gsub_gpos->FeatureList.Feature;
833 int index = rec->langsys->FeatureIndex[i];
836 if (! rec->features[i].w)
838 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
839 rec->parent, arg, 0);
840 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
841 rec->features[i].w = w;
844 rec->features[i].tag = feature[index].FeatureTag;
845 rec->features[i].on = 0;
846 OTF_tag_name (rec->features[i].tag, label);
847 XtSetArg (arg[5], XtNlabel, label);
848 XtSetValues (rec->features[i].w, arg, 6);
851 XtSetArg (arg[0], XtNborderColor, background);
852 XtSetArg (arg[1], XtNsensitive, False);
853 XtSetArg (arg[2], XtNlabel, " ");
854 for (; i < rec->num_features; i++)
856 if (! rec->features[i].w)
858 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
859 rec->parent, arg, 0);
860 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
861 rec->features[i].w = w;
863 XtSetValues (rec->features[i].w, arg, 3);
868 compose_script_langsys (OTF_Tag script, OTF_Tag langsys, char *name)
870 OTF_tag_name (script, name);
874 OTF_tag_name (langsys, name + 5);
881 decompose_script_langsys (OTF_Tag *script, OTF_Tag *langsys, char *name)
883 *script = OTF_tag (name);
885 *langsys = OTF_tag (name + 5);
891 ScriptProc (Widget w, XtPointer client_data, XtPointer call_data)
894 OTF_Tag script, langsys;
897 XtSetArg (arg[0], XtNlabel, &name);
898 XtGetValues (w, arg, 1);
899 decompose_script_langsys (&script, &langsys, name);
900 if (script_tag == script && langsys_tag == langsys)
903 langsys_tag = langsys;
904 setup_feature_rec (&gsub);
905 setup_feature_rec (&gpos);
910 create_otf_script_widgets (Widget prev)
922 XtSetArg (arg[0], XtNborderWidth, 0);
923 XtSetArg (arg[1], XtNleft, XawChainLeft);
924 XtSetArg (arg[2], XtNright, XawChainLeft);
925 XtSetArg (arg[3], XtNtop, XawChainTop);
926 XtSetArg (arg[4], XtNbottom, XawChainTop);
927 XtSetArg (arg[5], XtNfromVert, prev);
928 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
929 prev = XtCreateManagedWidget ("Script", boxWidgetClass, render_area, arg, 7);
930 XtCreateManagedWidget ("script(langsys)", labelWidgetClass, prev, arg, 1);
934 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
935 n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
937 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
938 n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
939 script_langsys = alloca ((sizeof script_langsys[0]) * n);
943 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
945 OTF_Tag tag = otf->gsub->ScriptList.Script[i].ScriptTag;
947 script_langsys[n].script = tag;
948 script_langsys[n++].langsys = 0;
950 < otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount)
952 = otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount;
953 for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
955 script_langsys[n].script = tag;
956 script_langsys[n++].langsys
957 = otf->gsub->ScriptList.Script[i].LangSysRecord[j].LangSysTag;
959 < otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount)
961 = otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount;
964 gsub.num_features = nfeatures;
967 gsub.num_features = nfeatures;
968 gsub.features = malloc ((sizeof (FeatureElement)) * nfeatures);
969 memset (gsub.features, 0, (sizeof (FeatureElement)) * nfeatures);
974 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
976 OTF_Tag tag = otf->gpos->ScriptList.Script[i].ScriptTag;
980 < otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount)
982 = otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount;
983 for (k = 0; k < prev_n; k++)
984 if (tag == script_langsys[k].script)
988 script_langsys[n].script = tag;
989 script_langsys[n++].langsys = 0;
991 for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
997 OTF_Script *script = otf->gsub->ScriptList.Script + i;
999 for (l = k; l < prev_n && tag == script_langsys[l].script; l++)
1000 if (script->LangSysRecord[j].LangSysTag
1001 == script_langsys[l].langsys)
1008 script_langsys[n].script = tag;
1009 script_langsys[n++].langsys = 0;
1012 < otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount)
1014 = otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount;
1020 gpos.num_features = nfeatures;
1021 gpos.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1022 memset (gpos.features, 0, (sizeof (FeatureElement)) * nfeatures);
1028 script_tag = script_langsys[0].script;
1029 langsys_tag = script_langsys[0].langsys;
1030 compose_script_langsys (script_tag, langsys_tag, name);
1034 XtSetArg (arg[0], XtNforeground, background);
1035 XtSetArg (arg[1], XtNbackground, foreground);
1036 XtCreateManagedWidget (name, labelWidgetClass, prev, arg, 2);
1040 XtSetArg (arg[0], XtNstate, True);
1041 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1042 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1043 XtSetArg (arg[0], XtNradioGroup, w);
1044 for (i = 1; i < n; i++)
1046 compose_script_langsys (script_langsys[i].script,
1047 script_langsys[i].langsys, name);
1048 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1049 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1057 create_otf_widgets (Widget prev, FeatureRec *rec)
1062 XtSetArg (arg[0], XtNborderWidth, 0);
1063 XtSetArg (arg[1], XtNleft, XawChainLeft);
1064 XtSetArg (arg[2], XtNright, XawChainLeft);
1065 XtSetArg (arg[3], XtNtop, XawChainTop);
1066 XtSetArg (arg[4], XtNbottom, XawChainTop);
1067 XtSetArg (arg[5], XtNfromVert, prev);
1068 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1069 prev = XtCreateManagedWidget (rec->label, boxWidgetClass, render_area,
1071 XtCreateManagedWidget (rec->label, labelWidgetClass, prev, arg, 1);
1072 XtSetArg (arg[0], XtNborderWidth, 1);
1073 XtSetArg (arg[1], XtNinternalHeight, 4);
1074 XtSetArg (arg[2], XtNinternalWidth, 4);
1075 w = XtCreateManagedWidget ("all", commandWidgetClass, prev, arg, 3);
1076 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1077 w = XtCreateManagedWidget ("none", commandWidgetClass, prev, arg, 3);
1078 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1081 setup_feature_rec (rec);
1088 String quit_action = "<KeyPress>q: set() notify() unset()";
1089 String FIRST_action = "<KeyPress>f: set() notify() unset()\n\
1090 <KeyPress>Home: set() notify() unset()";
1091 String PREV_action = "Shift<KeyPress>p: set() notify() unset()\n\
1092 <KeyPress>Up: set() notify() unset()";
1093 String prev_action = "~Shift<KeyPress>p: set() notify() unset()\n\
1094 <KeyPress>Left: set() notify() unset()";
1095 String next_action = "~Shift<KeyPress>n: set() notify() unset()\n\
1096 <KeyPress>Right: set() notify() unset()";
1097 String NEXT_action = "Shift<KeyPress>n: set() notify() unset()\n\
1098 <KeyPress>Down: set() notify() unset()";
1099 String LAST_action = "<KeyPress>l: set() notify() unset()\n\
1100 <KeyPress>End: set() notify() unset()";
1104 String trans = "<Expose>: Expose()";
1106 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans));
1107 frame = XtCreateManagedWidget ("frame", formWidgetClass, shell, arg, 1);
1109 XtSetArg (arg[0], XtNleft, XawChainLeft);
1110 XtSetArg (arg[1], XtNright, XawChainLeft);
1111 XtSetArg (arg[2], XtNtop, XawChainTop);
1112 XtSetArg (arg[3], XtNbottom, XawChainTop);
1113 XtSetArg (arg[4], XtNborderWidth, 0);
1114 XtSetArg (arg[5], XtNorientation, XtorientHorizontal);
1115 command_area = XtCreateManagedWidget ("command-area", boxWidgetClass,
1117 XtSetArg (arg[6], XtNfromVert, command_area);
1118 navi_area = XtCreateManagedWidget ("navi-area", boxWidgetClass,
1120 XtSetArg (arg[4], XtNborderWidth, 0);
1121 XtSetArg (arg[5], XtNfromVert, navi_area);
1122 XtSetArg (arg[6], XtNdefaultDistance, 0);
1123 glyph_area = XtCreateManagedWidget ("glyph-area", formWidgetClass,
1125 XtSetArg (arg[5], XtNfromVert, glyph_area);
1126 render_area = XtCreateManagedWidget ("render-area", formWidgetClass,
1129 XtSetArg (arg[0], XtNaccelerators, XtParseAcceleratorTable (quit_action));
1130 quit = XtCreateManagedWidget ("Quit", commandWidgetClass,
1131 command_area, arg, 1);
1132 XtAddCallback (quit, XtNcallback, QuitProc, NULL);
1134 dump = XtCreateManagedWidget ("Dump Image", commandWidgetClass,
1135 command_area, arg, 1);
1136 XtAddCallback (dump, XtNcallback, DumpProc, NULL);
1138 XtSetArg (arg[0], XtNborderWidth, 0);
1139 XtSetArg (arg[1], XtNwidth, 10);
1140 XtCreateManagedWidget ("spacer", boxWidgetClass, command_area, arg, 2);
1142 charmap = alloca (sizeof (Widget) * (face->num_charmaps + 1));
1143 XtSetArg (arg[0], XtNstate, True);
1144 charmap[0] = XtCreateManagedWidget (charmap_rec[0].name, toggleWidgetClass,
1145 command_area, arg, 1);
1146 XtAddCallback (charmap[0], XtNcallback, CharmapProc, (XtPointer) -1);
1147 XtSetArg (arg[0], XtNradioGroup, charmap[0]);
1148 for (i = 0; i < face->num_charmaps; i++)
1150 charmap[i + 1] = XtCreateManagedWidget (charmap_rec[i + 1].name,
1152 command_area, arg, 1);
1153 XtAddCallback (charmap[i + 1], XtNcallback, CharmapProc, (XtPointer) i);
1156 XtSetArg (arg[0], XtNlabel, " |< (f)");
1157 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (FIRST_action));
1158 FIRST = XtCreateManagedWidget ("FIRST", commandWidgetClass,
1160 XtAddCallback (FIRST, XtNcallback, GlyphProc, (XtPointer) -3);
1161 XtSetArg (arg[0], XtNlabel, "<< (P)");
1162 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (PREV_action));
1163 PREV = XtCreateManagedWidget ("PREV", commandWidgetClass,
1165 XtAddCallback (PREV, XtNcallback, GlyphProc, (XtPointer) -2);
1166 XtSetArg (arg[0], XtNlabel, "< (p)");
1167 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (prev_action));
1168 prev = XtCreateManagedWidget ("prev", commandWidgetClass,
1170 XtAddCallback (prev, XtNcallback, GlyphProc, (XtPointer) -1);
1171 XtSetArg (arg[0], XtNlabel, " 0000 ");
1172 range = XtCreateManagedWidget ("range", labelWidgetClass,
1174 XtSetArg (arg[0], XtNforeground, &foreground);
1175 XtSetArg (arg[1], XtNbackground, &background);
1176 XtGetValues (range, arg, 2);
1178 XtSetArg (arg[0], XtNlabel, "> (n)");
1179 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (next_action));
1180 next = XtCreateManagedWidget ("next", commandWidgetClass,
1182 XtAddCallback (next, XtNcallback, GlyphProc, (XtPointer) 1);
1183 XtSetArg (arg[0], XtNlabel, ">> (N)");
1184 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (NEXT_action));
1185 NEXT = XtCreateManagedWidget ("NEXT", commandWidgetClass,
1187 XtAddCallback (NEXT, XtNcallback, GlyphProc, (XtPointer) 2);
1188 XtSetArg (arg[0], XtNlabel, ">| (l)");
1189 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (LAST_action));
1190 LAST = XtCreateManagedWidget ("LAST", commandWidgetClass,
1192 XtAddCallback (LAST, XtNcallback, GlyphProc, (XtPointer) 3);
1194 XtSetArg (arg[0], XtNleft, XawChainLeft);
1195 XtSetArg (arg[1], XtNright, XawChainLeft);
1196 XtSetArg (arg[2], XtNtop, XawChainTop);
1197 XtSetArg (arg[3], XtNbottom, XawChainTop);
1199 for (i = 0; i < 8; i++)
1205 sprintf (str, "%XX", i);
1206 XtSetArg (arg[n], XtNheight, glyph_height + 5), n++;
1207 XtSetArg (arg[n], XtNlabel, str), n++;
1208 XtSetArg (arg[n], XtNborderWidth, 0), n++;
1210 XtSetArg (arg[n], XtNfromVert, w), n++;
1211 head = XtCreateManagedWidget (str, labelWidgetClass, glyph_area, arg, n);
1212 index_label[i] = head;
1213 for (j = 0; j < 16; j++)
1219 XtSetArg (arg[n], XtNfromVert, w), n++;
1221 XtSetArg (arg[n], XtNfromHoriz, head), n++;
1223 XtSetArg (arg[n], XtNfromHoriz, glyph[k - 1]), n++;
1224 XtSetArg (arg[n], XtNbitmap, none_pixmap), n++;
1225 glyph[k] = XtCreateManagedWidget ("glyph", commandWidgetClass,
1226 glyph_area, arg, n);
1227 XtAddCallback (glyph[k], XtNcallback, RenderProc, (XtPointer) k);
1231 /* 10 = (1 (border_width) + 4 (inner_width)) * 2 */
1232 XtSetArg(arg[4], XtNwidth, glyph_width + 10);
1233 XtSetArg (arg[5], XtNfromVert, glyph[112]);
1234 XtSetArg (arg[6], XtNfromHoriz, w);
1235 XtSetArg (arg[7], XtNborderWidth, 0);
1237 for (j = 0; j < 16; j++)
1241 sprintf (str, "X%X", j);
1242 XtSetArg (arg[8], XtNlabel, str);
1243 w = XtCreateManagedWidget ("idx", labelWidgetClass, glyph_area, arg, 9);
1244 XtSetArg (arg[6], XtNfromHoriz, w);
1247 XtSetArg (arg[0], XtNleft, XawChainLeft);
1248 XtSetArg (arg[1], XtNright, XawChainLeft);
1249 XtSetArg (arg[2], XtNtop, XawChainTop);
1250 XtSetArg (arg[3], XtNbottom, XawChainTop);
1251 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1252 XtSetArg (arg[5], XtNborderWidth, 0);
1253 w = XtCreateManagedWidget ("clear-box", boxWidgetClass, render_area, arg, 6);
1254 clear = XtCreateManagedWidget ("clear", commandWidgetClass, w, arg, 0);
1255 XtAddCallback (clear, XtNcallback, RenderProc, (XtPointer) -1);
1256 del = XtCreateManagedWidget ("delete", commandWidgetClass, w, arg, 0);
1257 XtAddCallback (del, XtNcallback, RenderProc, (XtPointer) -2);
1258 bidi = XtCreateManagedWidget ("L->R", toggleWidgetClass, w, arg, 0);
1259 XtAddCallback (bidi, XtNcallback, BidiProc, NULL);
1260 alt_subst = XtCreateManagedWidget ("AltSubst", toggleWidgetClass, w, arg, 0);
1261 XtAddCallback (alt_subst, XtNcallback, AltSubstProc, NULL);
1263 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1264 XtSetArg (arg[5], XtNborderWidth, 0);
1265 XtSetArg (arg[6], XtNfromVert, w);
1266 raw = XtCreateManagedWidget ("raw", boxWidgetClass, render_area, arg, 7);
1268 XtSetArg (arg[0], XtNborderWidth, 0);
1269 XtSetArg (arg[1], XtNlabel, "raw: ");
1270 raw_label = XtCreateManagedWidget ("raw-label", labelWidgetClass,
1272 XtSetArg (arg[1], XtNbitmap, raw_pixmap);
1273 raw_image = XtCreateManagedWidget ("raw-image", labelWidgetClass,
1278 OTF_get_table (otf, "GSUB");
1279 OTF_get_table (otf, "GPOS");
1280 w = create_otf_script_widgets (w);
1283 gsub.label = "GSUB";
1284 gsub.gsub_gpos = otf->gsub;
1285 w = create_otf_widgets (w, &gsub);
1289 gpos.label = "GPOS";
1290 gpos.gsub_gpos = otf->gpos;
1291 w = create_otf_widgets (w, &gpos);
1295 XtSetArg (arg[6], XtNfromVert, w);
1296 seq = XtCreateManagedWidget ("seq", boxWidgetClass, render_area, arg, 7);
1297 XtSetArg (arg[0], XtNborderWidth, 0);
1298 XtSetArg (arg[1], XtNlabel, "seq: ");
1299 seq_label = XtCreateManagedWidget ("seq-label", labelWidgetClass,
1301 XtSetArg (arg[1], XtNbitmap, seq_pixmap);
1302 seq_image = XtCreateManagedWidget ("seq-image", labelWidgetClass,
1304 XtInstallAllAccelerators (shell, shell);
1308 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1310 XTextProperty text_prop;
1311 char *pname = "otfview";
1312 char *fname = basename (filename);
1313 char *name = alloca (strlen (fname) + 3 + strlen (pname) + 1);
1315 sprintf (name, "%s - %s", pname, fname);
1316 text_prop.value = (unsigned char *) name;
1317 text_prop.encoding = XA_STRING;
1318 text_prop.format = 8;
1319 text_prop.nitems = strlen (name);
1320 XSetWMName (display, XtWindow (shell), &text_prop);
1323 /* Format MSG by FMT and print the result to the stderr, and exit. */
1325 #define FATAL_ERROR(fmt, arg) \
1327 fprintf (stderr, fmt, arg); \
1332 x_error_handler (Display *display, XErrorEvent *error)
1339 main (int argc, char **argv)
1341 XtActionsRec actions[] = { {"Expose", ExposeProc} };
1345 OTF_GlyphString gstring;
1350 int fixed_pixel_size = 0;
1353 pixel_size = DEFAULT_PIXEL_SIZE;
1355 char *str = getenv ("PIXEL_SIZE");
1357 if (str && (i = atoi (str)) > 0)
1360 fixed_pixel_size = 1;
1364 gstring.size = gstring.used = 256;
1365 g = calloc (256, sizeof (OTF_Glyph));
1368 shell = XtOpenApplication (&context, "OTFView", NULL, 0, &argc, argv, NULL,
1369 shellWidgetClass, arg, 0);
1370 display = XtDisplay (shell);
1371 /*XSynchronize (display, True);*/
1372 XSetErrorHandler (x_error_handler);
1373 display_width = DisplayWidth (display,
1374 XScreenNumberOfScreen (XtScreen (shell)));
1375 font = XLoadQueryFont (display, DEFAULT_FONT_NAME);
1377 font = XLoadQueryFont (display, "fixed");
1379 if (argc != 2 || !strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
1381 fprintf (stderr, "Usage: %s [ X-OPTION ... ] OTF-FILE\n",
1382 basename (argv[0]));
1384 " Pixel size is decided by the environment variable PIXEL_SIZE ((default %d).\n", DEFAULT_PIXEL_SIZE);
1388 if (strstr (filename, ".ttf")
1389 || strstr (filename, ".TTF")
1390 || strstr (filename, ".otf")
1391 || strstr (filename, ".OTF"))
1393 otf = OTF_open (filename);
1395 || OTF_get_table (otf, "head") < 0
1396 || OTF_get_table (otf, "cmap") < 0
1397 || (OTF_check_table (otf, "GSUB") < 0
1398 && OTF_check_table (otf, "GPOS") < 0))
1402 if ((err = FT_Init_FreeType (&library)))
1403 FATAL_ERROR ("%s\n", "FT_Init_FreeType: error");
1404 err = FT_New_Face (library, filename, 0, &face);
1405 if (err == FT_Err_Unknown_File_Format)
1406 FATAL_ERROR ("%s\n", "FT_New_Face: unknown file format");
1408 FATAL_ERROR ("%s\n", "FT_New_Face: unknown error");
1409 if ((err = FT_Set_Pixel_Sizes (face, 0, pixel_size)))
1410 FATAL_ERROR ("%s\n", "FT_Set_Pixel_Sizes: error");
1416 filename = basename (filename);
1417 sprintf (title, "%s family:%s style:%s",
1418 filename, face->family_name, face->style_name);
1419 XtSetArg (arg[0], XtNtitle, title);
1420 XtSetValues (shell, arg, 1);
1423 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1424 * pixel_size / face->units_per_EM);
1425 if (! fixed_pixel_size && glyph_width * 16 > display_width * 0.8)
1427 pixel_size = (pixel_size * display_width * 0.8 / 16 / glyph_width);
1428 FT_Set_Pixel_Sizes (face, 0, pixel_size);
1429 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1430 * pixel_size / face->units_per_EM);
1432 if (glyph_width < FONT_WIDTH * 4)
1433 glyph_width = FONT_WIDTH * 4;
1435 glyph_height = ((face->bbox.yMax - face->bbox.yMin)
1436 * pixel_size / face->units_per_EM);
1438 glyph_x = - (face->bbox.xMin * pixel_size / face->units_per_EM);
1439 glyph_y = face->bbox.yMax * pixel_size / face->units_per_EM;
1440 none_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1441 glyph_width, glyph_height, 1);
1444 unsigned long valuemask = GCFunction | GCLineWidth;
1447 gc = XCreateGC (display, none_pixmap, (unsigned long) 0, NULL);
1448 values.function = GXset;
1449 values.line_width = 1;
1450 gc_set = XCreateGC (display, none_pixmap, valuemask, &values);
1451 values.function = GXor;
1452 gc_or = XCreateGC (display, none_pixmap, valuemask, &values);
1453 values.function = GXcopyInverted;
1454 gc_inv = XCreateGC (display, none_pixmap, valuemask, &values);
1457 XFillRectangle (display, none_pixmap, gc, 0, 0,
1458 glyph_width, glyph_height);
1459 XDrawString (display, none_pixmap, gc_inv,
1460 (glyph_width - XTextWidth (font, "none", 4)) / 2,
1461 glyph_height / 2, "none", 4);
1463 render_width = (glyph_width + 4) * 15 + 1;
1464 render_height = glyph_height + 2;
1466 charmap_rec[0].platform_id = -1;
1467 charmap_rec[0].encoding_id = -1;
1468 strcpy (charmap_rec[0].name, "no charmap");
1470 for (i = 0; i < face->num_charmaps; i++)
1472 charmap_rec[i + 1].platform_id = face->charmaps[i]->platform_id;
1473 charmap_rec[i + 1].encoding_id = face->charmaps[i]->encoding_id;
1474 sprintf (charmap_rec[i + 1].name, "%d-%d",
1475 charmap_rec[i + 1].platform_id, charmap_rec[i + 1].encoding_id);
1476 if (face->charmaps[i]->platform_id == 0
1477 || (face->charmaps[i]->platform_id == 3
1478 && face->charmaps[i]->encoding_id == 1))
1479 strcat (charmap_rec[i + 1].name, " (unicode)");
1480 else if (face->charmaps[i]->platform_id == 1
1481 && face->charmaps[i]->encoding_id == 0)
1482 strcat (charmap_rec[i + 1].name, " (apple-roman)");
1485 raw_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1486 render_width, render_height, 1);
1487 seq_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1488 render_width, render_height, 1);
1490 memset (bitmap, 0, sizeof (bitmap));
1494 update_glyph_area ();
1495 update_render_area ();
1497 XtAppAddActions (context, actions, XtNumber (actions));
1498 XtRealizeWidget (shell);
1499 XtAppMainLoop (context);
1504 #else /* not HAVE_X11_XAW_COMMAND_H */
1507 main (int argc, char **argv)
1510 "Building of this program failed (lack of some header files)\n",