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 str = malloc (n * 5);
252 for (i = 0, p = str; i < n; i++, p += 5)
254 OTF_tag_name (rec->features[i].tag, p);
262 #define DEVICE_DELTA(table, size) \
263 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
264 ? (table).DeltaValue[(size) >= (table).StartSize] \
268 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
269 OTF_Glyph *g, int *x, int *y)
271 if (anchor->AnchorFormat == 2)
274 int ap = anchor->f.f1.AnchorPoint;
276 FT_Load_Glyph (ft_face, (FT_UInt) g->glyph_id, FT_LOAD_MONOCHROME);
277 outline = &ft_face->glyph->outline;
278 if (ap < outline->n_points)
280 *x = outline->points[ap].x;
281 *y = outline->points[ap].y;
284 else if (anchor->AnchorFormat == 3)
286 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, pixel_size);
287 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, pixel_size);
295 OTF_GlyphString gstring;
296 OTF_Glyph *g, *prev, *base, *mark;
298 int len = glyph_rec.n_glyphs;
300 int unitsPerEm = face->units_per_EM;
302 gstring.size = gstring.used = len;
303 gstring.glyphs = malloc (sizeof (OTF_Glyph) * len);
304 memset (gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
305 for (i = 0; i < len; i++)
306 gstring.glyphs[i].c = gstring.glyphs[i].glyph_id = glyph_rec.glyphs[i];
308 XFillRectangle (display, seq_pixmap, gc, 0, 0, render_width, render_height);
309 XDrawLine (display, seq_pixmap, gc_set, 0, glyph_y, render_width, glyph_y);
314 OTF_drive_gdef (otf, &gstring);
317 str = get_features (&otf->gsub->FeatureList, &gsub);
320 if (do_alternate_subst)
321 OTF_drive_gsub_alternate (otf, &gstring, NULL, NULL, str);
323 OTF_drive_gsub (otf, &gstring, NULL, NULL, str);
329 str = get_features (&otf->gpos->FeatureList, &gpos);
332 OTF_drive_gpos (otf, &gstring, NULL, NULL, str);
343 for (prev = gstring.glyphs, g = gstring.glyphs + gstring.used - 1;
344 prev < g; prev++, g--)
345 temp = *prev, *prev = *g, *g = temp;
346 for (g = gstring.glyphs; g < gstring.glyphs + gstring.used; g++)
347 if (g->GlyphClass == 3)
351 while (g < gstring.glyphs + gstring.used && g->GlyphClass == 3)
353 for (g0 = g; prev < g0; prev++, g0--)
354 temp = *prev, *prev = *g, *g = temp;
360 for (i = 0, x = glyph_x, prev = NULL, g = gstring.glyphs;
361 i < gstring.used; i++, prev = g++)
363 BitmapRec *bmp = bitmap + gstring.glyphs[i].glyph_id;
364 int xoff = 0, yoff = 0;
366 int advance = bmp->advance;
370 create_pixmap (gstring.glyphs[i].glyph_id);
373 advance = bmp->advance;
375 switch (g->positioning_type)
382 int format = g->f.f1.format;
384 if (format & OTF_XPlacement)
385 xoff = g->f.f1.value->XPlacement * pixel_size / unitsPerEm;
386 if (format & OTF_XPlaDevice)
387 xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, pixel_size);
388 if (format & OTF_YPlacement)
389 yoff = g->f.f1.value->YPlacement * pixel_size / unitsPerEm;
390 if (format & OTF_YPlaDevice)
391 yoff += DEVICE_DELTA (g->f.f1.value->YPlaDevice, pixel_size);
392 if (format & OTF_XAdvance)
393 advance += g->f.f1.value->XAdvance * pixel_size / unitsPerEm;
394 if (format & OTF_XAdvDevice)
395 advance += DEVICE_DELTA (g->f.f1.value->XAdvDevice, pixel_size);
400 /* Not yet supported. */
406 prev_width = base_width;
407 goto label_adjust_anchor;
408 default: /* i.e. case 6 */
415 int base_x, base_y, mark_x, mark_y;
417 base_x = g->f.f4.base_anchor->XCoordinate * pixel_size / unitsPerEm;
418 base_y = g->f.f4.base_anchor->YCoordinate * pixel_size / unitsPerEm;
419 mark_x = g->f.f4.mark_anchor->XCoordinate * pixel_size / unitsPerEm;
420 mark_y = g->f.f4.mark_anchor->YCoordinate * pixel_size / unitsPerEm;
422 if (g->f.f4.base_anchor->AnchorFormat != 1)
423 adjust_anchor (g->f.f4.base_anchor, face, prev, &base_x, &base_y);
424 if (g->f.f4.mark_anchor->AnchorFormat != 1)
425 adjust_anchor (g->f.f4.mark_anchor, face, g, &mark_x, &mark_y);
426 xoff = (base_x - prev_width) - mark_x;
427 yoff = base_y - mark_y;
431 XCopyArea (display, bmp->pixmap, seq_pixmap, gc_or,
432 glyph_x + bmp->x, glyph_y + bmp->y, bmp->width, bmp->height,
433 x + bmp->x + xoff, glyph_y + bmp->y - yoff);
436 if (g->GlyphClass == OTF_GlyphClass0)
437 base = mark = g, base_width = advance;
438 else if (g->GlyphClass == OTF_GlyphClassMark)
441 base = g, base_width = advance;
443 free (gstring.glyphs);
445 XtSetArg (arg[0], XtNbitmap, seq_pixmap);
446 XtSetValues (seq_image, arg, 1);
451 update_render_area ()
457 XFillRectangle (display, raw_pixmap, gc, 0, 0, render_width, render_height);
458 for (i = 0, x = glyph_x; i < glyph_rec.n_glyphs; i++)
460 BitmapRec *bmp = bitmap + glyph_rec.glyphs[i];
463 XCopyArea (display, bmp->pixmap, raw_pixmap, gc,
464 0, 0, glyph_width, glyph_height,
465 (glyph_width + 4) * i + 1, 1);
466 XDrawRectangle (display, raw_pixmap, gc_set,
467 (glyph_width + 4) * i, 0,
468 glyph_width + 1, glyph_height + 1);
469 XDrawLine (display, raw_pixmap, gc_set,
470 (glyph_width + 4) * i + 1 + glyph_x, 1,
471 (glyph_width + 4) * i + 1 + glyph_x, glyph_height + 1);
472 XDrawLine (display, raw_pixmap, gc_set,
473 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance, 1,
474 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance,
477 sprintf (buf, "%04X", glyph_rec.codes[i]);
478 XDrawString (display, raw_pixmap, gc_inv,
479 (glyph_width + 1) * i + 1
480 + (glyph_width - XTextWidth (font, buf, 4)) / 2,
481 glyph_height + 2 + FONT_HEIGHT, buf, 4);
483 XtSetArg (arg[0], XtNbitmap, raw_pixmap);
484 XtSetValues (raw_image, arg, 1);
489 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
491 XtAppSetExitFlag (XtWidgetToApplicationContext (w));
495 DumpProc (Widget w, XtPointer client_data, XtPointer call_data)
497 int g_width, g_height, g_x, g_y, pix_width, pix_height;
498 int margin = 20 * 300 / 25.4;
499 int a4_width = 210 * 300 / 25.4 - margin * 2;
500 int a4_height = 297 * 300 / 25.4 - margin * 2;
503 XImage ximage, *image;
508 FT_Set_Pixel_Sizes (face, 0, size);
509 g_width = ((face->bbox.xMax - face->bbox.xMin) * size / face->units_per_EM);
510 g_height = ((face->bbox.yMax - face->bbox.yMin) * size / face->units_per_EM);
511 pix_width = (g_width + 1) * 16 + margin + 1;
512 pix_height = (g_height + 1 + FONT_HEIGHT) * 16 + margin + 1;
513 while (pix_width > a4_width || pix_height > a4_height)
516 FT_Set_Pixel_Sizes (face, 0, size);
517 g_width = ((face->bbox.xMax - face->bbox.xMin)
518 * size / face->units_per_EM);
519 g_height = ((face->bbox.yMax - face->bbox.yMin)
520 * size / face->units_per_EM);
521 pix_width = (g_width + 1) * 16 + margin + 1;
522 pix_height = (g_height + 1 + FONT_HEIGHT) * 16 + margin + 1;
525 g_x = - (face->bbox.xMin * size / face->units_per_EM);
526 g_y = face->bbox.yMax * size / face->units_per_EM;
527 for (i = 0; i < 0xFF; i++)
531 if (charmap_index >= 0)
532 idx = FT_Get_Char_Index (face, (FT_ULong) i);
535 if (FT_Load_Glyph (face, idx, FT_LOAD_RENDER | FT_LOAD_MONOCHROME) == 0)
537 if (g_x < - face->glyph->bitmap_left)
538 g_x = - face->glyph->bitmap_left;
539 if (g_y < face->glyph->bitmap_top)
540 g_y = face->glyph->bitmap_top;
542 < g_x + face->glyph->bitmap_left + face->glyph->bitmap.width)
544 = g_x + face->glyph->bitmap_left + face->glyph->bitmap.width;
546 < g_y - face->glyph->bitmap_top + face->glyph->bitmap.rows)
548 = g_y - face->glyph->bitmap_top + face->glyph->bitmap.rows;
551 pix_width = (g_width + 1) * 16 + margin + 1;
552 pix_height = (g_height + FONT_HEIGHT + 1) * 16 + margin + 1;
553 pixmap = XCreatePixmap (display,
554 RootWindow (display, DefaultScreen (display)),
555 pix_width, pix_height, 1);
556 XFillRectangle (display, pixmap, gc, 0, 0, pix_width, pix_height);
558 for (i = 0, x = margin; i <= 16; i++, x += g_width + 1)
559 XDrawLine (display, pixmap, gc_set, x, margin,
560 x, margin + (g_height + FONT_HEIGHT + 1) * 16);
561 for (i = 0, y = margin; i <= 16; i++, y += g_height + FONT_HEIGHT + 1)
562 XDrawLine (display, pixmap, gc_set, margin, y,
563 margin + (g_width + 1) * 16, y);
564 for (i = 0; i < 256; i++)
569 if (charmap_index >= 0)
570 idx = FT_Get_Char_Index (face, (FT_ULong) i);
573 x = margin + (g_width + 1) * (i % 16);
574 y = margin + (g_height + FONT_HEIGHT + 1) * (i / 16);
575 if (FT_Load_Glyph (face, idx, FT_LOAD_RENDER | FT_LOAD_MONOCHROME) == 0)
577 ximage.height = face->glyph->bitmap.rows;
578 ximage.width = face->glyph->bitmap.width;
580 ximage.bits_per_pixel = 1;
582 ximage.format = XYPixmap;
583 ximage.data = (char *) face->glyph->bitmap.buffer;
584 ximage.byte_order = MSBFirst;
585 ximage.bitmap_unit = 8;
586 ximage.bitmap_bit_order = MSBFirst;
587 ximage.bitmap_pad = 8;
588 ximage.bytes_per_line = face->glyph->bitmap.pitch;
589 XInitImage (&ximage);
590 XPutImage (display, pixmap, gc, &ximage, 0, 0,
591 x + g_x + face->glyph->bitmap_left,
592 y + g_y - face->glyph->bitmap_top,
593 ximage.width, ximage.height);
595 sprintf (str, "0x%02X", i);
596 XDrawString (display, pixmap, gc_inv,
597 x + (g_width - XTextWidth (font, str, 4))/ 2,
598 y + g_height + FONT_ASCENT, str, 4);
601 image = XGetImage (display, pixmap, 0, 0, pix_width, pix_height,
602 AllPlanes, XYPixmap);
605 char *name = alloca (strlen (filename) + 5);
608 sprintf (name, "%s.pbm", filename);
609 printf ("Writing %s ...", name);
610 fp = fopen (name, "w");
611 fprintf (fp, "P4\n%d %d\n", image->width, image->height);
612 bytes_per_line = (image->width + 7) / 8;
614 for (y = 0; y < image->height; y++, data += image->bytes_per_line)
615 fwrite (data, 1, bytes_per_line, fp);
619 FT_Set_Pixel_Sizes (face, 0, (int) pixel_size);
624 GlyphProc (Widget w, XtPointer client_data, XtPointer call_data)
626 int old_glyph_index = glyph_index;
628 if ((int) client_data == -3 && glyph_index > 0)
630 else if ((int) client_data == -2 && glyph_index > 0)
631 glyph_index = (glyph_index - 1) & 0xF000;
632 else if ((int) client_data == -1 && glyph_index > 0)
634 else if ((int) client_data == 1 && glyph_index < 0xFF80)
636 else if ((int) client_data == 2 && glyph_index < 0xF000)
637 glyph_index = (glyph_index + 0x1000) & 0xF000;
638 else if ((int) client_data == 3 && glyph_index < 0xF000)
639 glyph_index = 0xFF80;
640 if (glyph_index != old_glyph_index)
641 update_glyph_area ();
645 CharmapProc (Widget w, XtPointer client_data, XtPointer call_data)
647 if (charmap_index == (int) client_data)
649 charmap_index = (int) client_data;
650 if (charmap_index >= 0)
651 FT_Set_Charmap (face, face->charmaps[charmap_index]);
652 update_glyph_area ();
656 RenderProc (Widget w, XtPointer client_data, XtPointer call_data)
658 if ((int) client_data < 0)
660 if (glyph_rec.n_glyphs > 0)
662 if ((int) client_data == -2)
663 glyph_rec.n_glyphs--;
665 glyph_rec.n_glyphs = 0;
666 update_render_area ();
669 else if (glyph_rec.n_glyphs < 64)
671 int index = glyph_index + (int) client_data;
673 if (charmap_index >= 0)
674 index = FT_Get_Char_Index (face, (FT_ULong) index);
675 if (bitmap[index].pixmap)
677 glyph_rec.codes[glyph_rec.n_glyphs] = glyph_index + (int) client_data;
678 glyph_rec.glyphs[glyph_rec.n_glyphs++] = index;
679 update_render_area ();
685 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
689 reversed = ! reversed;
691 XtSetArg (arg[0], XtNlabel, "L<-R");
693 XtSetArg (arg[0], XtNlabel, "L->R");
694 XtSetValues (w, arg, 1);
699 AltSubstProc (Widget w, XtPointer client_data, XtPointer call_data)
701 do_alternate_subst = ! do_alternate_subst;
706 FeatureProc (Widget w, XtPointer client_data, XtPointer call_data)
708 FeatureRec *rec = (FeatureRec *) client_data;
715 XtSetArg (arg[0], XtNlabel, &label);
716 XtGetValues (w, arg, 1);
717 if (! strcmp (label, "all"))
719 else if (! strcmp (label, "none"))
723 for (idx = 0; idx < rec->langsys->FeatureCount; idx++)
724 if (rec->features[idx].w == w)
726 if (idx == rec->langsys->FeatureCount)
733 for (i = j = 0; j < rec->langsys->FeatureCount; j++)
735 int index = rec->langsys->FeatureIndex[j];
738 = rec->gsub_gpos->FeatureList.Feature[index].FeatureTag;
739 rec->features[j].on = on;
744 OTF_Tag tag = rec->features[idx].tag;
747 if (rec->features[i].on)
750 j < rec->langsys->FeatureCount && rec->features[j].on; j++)
751 rec->features[j - 1].tag = rec->features[j].tag;
752 rec->features[j - 1].tag = tag;
753 rec->features[j - 1].on = 0;
757 for (j = i + 1; i > 0 && ! rec->features[i - 1].on; i--)
758 rec->features[i].tag = rec->features[i - 1].tag;
759 rec->features[i].tag = tag;
760 rec->features[i].on = 1;
768 if (rec->features[i].on)
770 XtSetArg (arg[0], XtNborderWidth, 3);
771 XtSetArg (arg[1], XtNinternalHeight, 2);
772 XtSetArg (arg[2], XtNinternalWidth, 2);
776 XtSetArg (arg[0], XtNborderWidth, 1);
777 XtSetArg (arg[1], XtNinternalHeight, 4);
778 XtSetArg (arg[2], XtNinternalWidth, 4);
780 OTF_tag_name (rec->features[i].tag, str);
781 XtSetArg (arg[3], XtNlabel, str);
782 XtSetValues (rec->features[i].w, arg, 4);
788 setup_feature_rec (FeatureRec *rec)
794 if (! rec->gsub_gpos)
796 for (i = 0; i < rec->gsub_gpos->ScriptList.ScriptCount; i++)
797 if (rec->gsub_gpos->ScriptList.Script[i].ScriptTag == script_tag)
799 OTF_Script *script = rec->gsub_gpos->ScriptList.Script + i;
803 for (j = 0; j < script->LangSysCount; j++)
804 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
806 rec->langsys = script->LangSys + j;
811 rec->langsys = &rec->gsub_gpos->ScriptList.Script[i].DefaultLangSys;
819 XtSetArg (arg[0], XtNborderWidth, 1);
820 XtSetArg (arg[1], XtNinternalHeight, 4);
821 XtSetArg (arg[2], XtNinternalWidth, 4);
822 XtSetArg (arg[3], XtNborderColor, foreground);
823 XtSetArg (arg[4], XtNsensitive, True);
824 for (i = 0; i < rec->langsys->FeatureCount; i++)
826 OTF_Feature *feature = rec->gsub_gpos->FeatureList.Feature;
827 int index = rec->langsys->FeatureIndex[i];
830 if (! rec->features[i].w)
832 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
833 rec->parent, arg, 0);
834 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
835 rec->features[i].w = w;
838 rec->features[i].tag = feature[index].FeatureTag;
839 rec->features[i].on = 0;
840 OTF_tag_name (rec->features[i].tag, label);
841 XtSetArg (arg[5], XtNlabel, label);
842 XtSetValues (rec->features[i].w, arg, 6);
845 XtSetArg (arg[0], XtNborderColor, background);
846 XtSetArg (arg[1], XtNsensitive, False);
847 XtSetArg (arg[2], XtNlabel, " ");
848 for (; i < rec->num_features; i++)
850 if (! rec->features[i].w)
852 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
853 rec->parent, arg, 0);
854 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
855 rec->features[i].w = w;
857 XtSetValues (rec->features[i].w, arg, 3);
862 compose_script_langsys (OTF_Tag script, OTF_Tag langsys, char *name)
864 OTF_tag_name (script, name);
868 OTF_tag_name (langsys, name + 5);
875 decompose_script_langsys (OTF_Tag *script, OTF_Tag *langsys, char *name)
877 *script = OTF_tag (name);
879 *langsys = OTF_tag (name + 5);
885 ScriptProc (Widget w, XtPointer client_data, XtPointer call_data)
888 OTF_Tag script, langsys;
891 XtSetArg (arg[0], XtNlabel, &name);
892 XtGetValues (w, arg, 1);
893 decompose_script_langsys (&script, &langsys, name);
894 if (script_tag == script && langsys_tag == langsys)
897 langsys_tag = langsys;
898 setup_feature_rec (&gsub);
899 setup_feature_rec (&gpos);
904 create_otf_script_widgets (Widget prev)
916 XtSetArg (arg[0], XtNborderWidth, 0);
917 XtSetArg (arg[1], XtNleft, XawChainLeft);
918 XtSetArg (arg[2], XtNright, XawChainLeft);
919 XtSetArg (arg[3], XtNtop, XawChainTop);
920 XtSetArg (arg[4], XtNbottom, XawChainTop);
921 XtSetArg (arg[5], XtNfromVert, prev);
922 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
923 prev = XtCreateManagedWidget ("Script", boxWidgetClass, render_area, arg, 7);
924 XtCreateManagedWidget ("script(langsys)", labelWidgetClass, prev, arg, 1);
928 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
929 n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
931 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
932 n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
933 script_langsys = alloca ((sizeof script_langsys[0]) * n);
937 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
939 OTF_Tag tag = otf->gsub->ScriptList.Script[i].ScriptTag;
941 script_langsys[n].script = tag;
942 script_langsys[n++].langsys = 0;
944 < otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount)
946 = otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount;
947 for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
949 script_langsys[n].script = tag;
950 script_langsys[n++].langsys
951 = otf->gsub->ScriptList.Script[i].LangSysRecord[j].LangSysTag;
953 < otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount)
955 = otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount;
958 gsub.num_features = nfeatures;
961 gsub.num_features = nfeatures;
962 gsub.features = malloc ((sizeof (FeatureElement)) * nfeatures);
963 memset (gsub.features, 0, (sizeof (FeatureElement)) * nfeatures);
968 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
970 OTF_Tag tag = otf->gpos->ScriptList.Script[i].ScriptTag;
974 < otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount)
976 = otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount;
977 for (k = 0; k < prev_n; k++)
978 if (tag == script_langsys[k].script)
982 script_langsys[n].script = tag;
983 script_langsys[n++].langsys = 0;
985 for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
991 OTF_Script *script = otf->gsub->ScriptList.Script + i;
993 for (l = k; l < prev_n && tag == script_langsys[l].script; l++)
994 if (script->LangSysRecord[j].LangSysTag
995 == script_langsys[l].langsys)
1002 script_langsys[n].script = tag;
1003 script_langsys[n++].langsys = 0;
1006 < otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount)
1008 = otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount;
1014 gpos.num_features = nfeatures;
1015 gpos.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1016 memset (gpos.features, 0, (sizeof (FeatureElement)) * nfeatures);
1022 script_tag = script_langsys[0].script;
1023 langsys_tag = script_langsys[0].langsys;
1024 compose_script_langsys (script_tag, langsys_tag, name);
1028 XtSetArg (arg[0], XtNforeground, background);
1029 XtSetArg (arg[1], XtNbackground, foreground);
1030 XtCreateManagedWidget (name, labelWidgetClass, prev, arg, 2);
1034 XtSetArg (arg[0], XtNstate, True);
1035 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1036 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1037 XtSetArg (arg[0], XtNradioGroup, w);
1038 for (i = 1; i < n; i++)
1040 compose_script_langsys (script_langsys[i].script,
1041 script_langsys[i].langsys, name);
1042 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1043 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1051 create_otf_widgets (Widget prev, FeatureRec *rec)
1056 XtSetArg (arg[0], XtNborderWidth, 0);
1057 XtSetArg (arg[1], XtNleft, XawChainLeft);
1058 XtSetArg (arg[2], XtNright, XawChainLeft);
1059 XtSetArg (arg[3], XtNtop, XawChainTop);
1060 XtSetArg (arg[4], XtNbottom, XawChainTop);
1061 XtSetArg (arg[5], XtNfromVert, prev);
1062 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1063 prev = XtCreateManagedWidget (rec->label, boxWidgetClass, render_area,
1065 XtCreateManagedWidget (rec->label, labelWidgetClass, prev, arg, 1);
1066 XtSetArg (arg[0], XtNborderWidth, 1);
1067 XtSetArg (arg[1], XtNinternalHeight, 4);
1068 XtSetArg (arg[2], XtNinternalWidth, 4);
1069 w = XtCreateManagedWidget ("all", commandWidgetClass, prev, arg, 3);
1070 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1071 w = XtCreateManagedWidget ("none", commandWidgetClass, prev, arg, 3);
1072 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1075 setup_feature_rec (rec);
1082 String quit_action = "<KeyPress>q: set() notify() unset()";
1083 String FIRST_action = "<KeyPress>f: set() notify() unset()\n\
1084 <KeyPress>Home: set() notify() unset()";
1085 String PREV_action = "Shift<KeyPress>p: set() notify() unset()\n\
1086 <KeyPress>Up: set() notify() unset()";
1087 String prev_action = "~Shift<KeyPress>p: set() notify() unset()\n\
1088 <KeyPress>Left: set() notify() unset()";
1089 String next_action = "~Shift<KeyPress>n: set() notify() unset()\n\
1090 <KeyPress>Right: set() notify() unset()";
1091 String NEXT_action = "Shift<KeyPress>n: set() notify() unset()\n\
1092 <KeyPress>Down: set() notify() unset()";
1093 String LAST_action = "<KeyPress>l: set() notify() unset()\n\
1094 <KeyPress>End: set() notify() unset()";
1098 String trans = "<Expose>: Expose()";
1100 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans));
1101 frame = XtCreateManagedWidget ("frame", formWidgetClass, shell, arg, 1);
1103 XtSetArg (arg[0], XtNleft, XawChainLeft);
1104 XtSetArg (arg[1], XtNright, XawChainLeft);
1105 XtSetArg (arg[2], XtNtop, XawChainTop);
1106 XtSetArg (arg[3], XtNbottom, XawChainTop);
1107 XtSetArg (arg[4], XtNborderWidth, 0);
1108 XtSetArg (arg[5], XtNorientation, XtorientHorizontal);
1109 command_area = XtCreateManagedWidget ("command-area", boxWidgetClass,
1111 XtSetArg (arg[6], XtNfromVert, command_area);
1112 navi_area = XtCreateManagedWidget ("navi-area", boxWidgetClass,
1114 XtSetArg (arg[4], XtNborderWidth, 0);
1115 XtSetArg (arg[5], XtNfromVert, navi_area);
1116 XtSetArg (arg[6], XtNdefaultDistance, 0);
1117 glyph_area = XtCreateManagedWidget ("glyph-area", formWidgetClass,
1119 XtSetArg (arg[5], XtNfromVert, glyph_area);
1120 render_area = XtCreateManagedWidget ("render-area", formWidgetClass,
1123 XtSetArg (arg[0], XtNaccelerators, XtParseAcceleratorTable (quit_action));
1124 quit = XtCreateManagedWidget ("Quit", commandWidgetClass,
1125 command_area, arg, 1);
1126 XtAddCallback (quit, XtNcallback, QuitProc, NULL);
1128 dump = XtCreateManagedWidget ("Dump Image", commandWidgetClass,
1129 command_area, arg, 1);
1130 XtAddCallback (dump, XtNcallback, DumpProc, NULL);
1132 XtSetArg (arg[0], XtNborderWidth, 0);
1133 XtSetArg (arg[1], XtNwidth, 10);
1134 XtCreateManagedWidget ("spacer", boxWidgetClass, command_area, arg, 2);
1136 charmap = alloca (sizeof (Widget) * (face->num_charmaps + 1));
1137 XtSetArg (arg[0], XtNstate, True);
1138 charmap[0] = XtCreateManagedWidget (charmap_rec[0].name, toggleWidgetClass,
1139 command_area, arg, 1);
1140 XtAddCallback (charmap[0], XtNcallback, CharmapProc, (XtPointer) -1);
1141 XtSetArg (arg[0], XtNradioGroup, charmap[0]);
1142 for (i = 0; i < face->num_charmaps; i++)
1144 charmap[i + 1] = XtCreateManagedWidget (charmap_rec[i + 1].name,
1146 command_area, arg, 1);
1147 XtAddCallback (charmap[i + 1], XtNcallback, CharmapProc, (XtPointer) i);
1150 XtSetArg (arg[0], XtNlabel, " |< (f)");
1151 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (FIRST_action));
1152 FIRST = XtCreateManagedWidget ("FIRST", commandWidgetClass,
1154 XtAddCallback (FIRST, XtNcallback, GlyphProc, (XtPointer) -3);
1155 XtSetArg (arg[0], XtNlabel, "<< (P)");
1156 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (PREV_action));
1157 PREV = XtCreateManagedWidget ("PREV", commandWidgetClass,
1159 XtAddCallback (PREV, XtNcallback, GlyphProc, (XtPointer) -2);
1160 XtSetArg (arg[0], XtNlabel, "< (p)");
1161 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (prev_action));
1162 prev = XtCreateManagedWidget ("prev", commandWidgetClass,
1164 XtAddCallback (prev, XtNcallback, GlyphProc, (XtPointer) -1);
1165 XtSetArg (arg[0], XtNlabel, " 0000 ");
1166 range = XtCreateManagedWidget ("range", labelWidgetClass,
1168 XtSetArg (arg[0], XtNforeground, &foreground);
1169 XtSetArg (arg[1], XtNbackground, &background);
1170 XtGetValues (range, arg, 2);
1172 XtSetArg (arg[0], XtNlabel, "> (n)");
1173 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (next_action));
1174 next = XtCreateManagedWidget ("next", commandWidgetClass,
1176 XtAddCallback (next, XtNcallback, GlyphProc, (XtPointer) 1);
1177 XtSetArg (arg[0], XtNlabel, ">> (N)");
1178 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (NEXT_action));
1179 NEXT = XtCreateManagedWidget ("NEXT", commandWidgetClass,
1181 XtAddCallback (NEXT, XtNcallback, GlyphProc, (XtPointer) 2);
1182 XtSetArg (arg[0], XtNlabel, ">| (l)");
1183 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (LAST_action));
1184 LAST = XtCreateManagedWidget ("LAST", commandWidgetClass,
1186 XtAddCallback (LAST, XtNcallback, GlyphProc, (XtPointer) 3);
1188 XtSetArg (arg[0], XtNleft, XawChainLeft);
1189 XtSetArg (arg[1], XtNright, XawChainLeft);
1190 XtSetArg (arg[2], XtNtop, XawChainTop);
1191 XtSetArg (arg[3], XtNbottom, XawChainTop);
1193 for (i = 0; i < 8; i++)
1199 sprintf (str, "%XX", i);
1200 XtSetArg (arg[n], XtNheight, glyph_height + 5), n++;
1201 XtSetArg (arg[n], XtNlabel, str), n++;
1202 XtSetArg (arg[n], XtNborderWidth, 0), n++;
1204 XtSetArg (arg[n], XtNfromVert, w), n++;
1205 head = XtCreateManagedWidget (str, labelWidgetClass, glyph_area, arg, n);
1206 index_label[i] = head;
1207 for (j = 0; j < 16; j++)
1213 XtSetArg (arg[n], XtNfromVert, w), n++;
1215 XtSetArg (arg[n], XtNfromHoriz, head), n++;
1217 XtSetArg (arg[n], XtNfromHoriz, glyph[k - 1]), n++;
1218 XtSetArg (arg[n], XtNbitmap, none_pixmap), n++;
1219 glyph[k] = XtCreateManagedWidget ("glyph", commandWidgetClass,
1220 glyph_area, arg, n);
1221 XtAddCallback (glyph[k], XtNcallback, RenderProc, (XtPointer) k);
1225 /* 10 = (1 (border_width) + 4 (inner_width)) * 2 */
1226 XtSetArg(arg[4], XtNwidth, glyph_width + 10);
1227 XtSetArg (arg[5], XtNfromVert, glyph[112]);
1228 XtSetArg (arg[6], XtNfromHoriz, w);
1229 XtSetArg (arg[7], XtNborderWidth, 0);
1231 for (j = 0; j < 16; j++)
1235 sprintf (str, "X%X", j);
1236 XtSetArg (arg[8], XtNlabel, str);
1237 w = XtCreateManagedWidget ("idx", labelWidgetClass, glyph_area, arg, 9);
1238 XtSetArg (arg[6], XtNfromHoriz, w);
1241 XtSetArg (arg[0], XtNleft, XawChainLeft);
1242 XtSetArg (arg[1], XtNright, XawChainLeft);
1243 XtSetArg (arg[2], XtNtop, XawChainTop);
1244 XtSetArg (arg[3], XtNbottom, XawChainTop);
1245 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1246 XtSetArg (arg[5], XtNborderWidth, 0);
1247 w = XtCreateManagedWidget ("clear-box", boxWidgetClass, render_area, arg, 6);
1248 clear = XtCreateManagedWidget ("clear", commandWidgetClass, w, arg, 0);
1249 XtAddCallback (clear, XtNcallback, RenderProc, (XtPointer) -1);
1250 del = XtCreateManagedWidget ("delete", commandWidgetClass, w, arg, 0);
1251 XtAddCallback (del, XtNcallback, RenderProc, (XtPointer) -2);
1252 bidi = XtCreateManagedWidget ("L->R", toggleWidgetClass, w, arg, 0);
1253 XtAddCallback (bidi, XtNcallback, BidiProc, NULL);
1254 alt_subst = XtCreateManagedWidget ("AltSubst", toggleWidgetClass, w, arg, 0);
1255 XtAddCallback (alt_subst, XtNcallback, AltSubstProc, NULL);
1257 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1258 XtSetArg (arg[5], XtNborderWidth, 0);
1259 XtSetArg (arg[6], XtNfromVert, w);
1260 raw = XtCreateManagedWidget ("raw", boxWidgetClass, render_area, arg, 7);
1262 XtSetArg (arg[0], XtNborderWidth, 0);
1263 XtSetArg (arg[1], XtNlabel, "raw: ");
1264 raw_label = XtCreateManagedWidget ("raw-label", labelWidgetClass,
1266 XtSetArg (arg[1], XtNbitmap, raw_pixmap);
1267 raw_image = XtCreateManagedWidget ("raw-image", labelWidgetClass,
1272 OTF_get_table (otf, "GSUB");
1273 OTF_get_table (otf, "GPOS");
1274 w = create_otf_script_widgets (w);
1277 gsub.label = "GSUB";
1278 gsub.gsub_gpos = otf->gsub;
1279 w = create_otf_widgets (w, &gsub);
1283 gpos.label = "GPOS";
1284 gpos.gsub_gpos = otf->gpos;
1285 w = create_otf_widgets (w, &gpos);
1289 XtSetArg (arg[6], XtNfromVert, w);
1290 seq = XtCreateManagedWidget ("seq", boxWidgetClass, render_area, arg, 7);
1291 XtSetArg (arg[0], XtNborderWidth, 0);
1292 XtSetArg (arg[1], XtNlabel, "seq: ");
1293 seq_label = XtCreateManagedWidget ("seq-label", labelWidgetClass,
1295 XtSetArg (arg[1], XtNbitmap, seq_pixmap);
1296 seq_image = XtCreateManagedWidget ("seq-image", labelWidgetClass,
1298 XtInstallAllAccelerators (shell, shell);
1302 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1304 XTextProperty text_prop;
1305 char *pname = "otfview";
1306 char *fname = basename (filename);
1307 char *name = alloca (strlen (fname) + 3 + strlen (pname) + 1);
1309 sprintf (name, "%s - %s", pname, fname);
1310 text_prop.value = (unsigned char *) name;
1311 text_prop.encoding = XA_STRING;
1312 text_prop.format = 8;
1313 text_prop.nitems = strlen (name);
1314 XSetWMName (display, XtWindow (shell), &text_prop);
1317 /* Format MSG by FMT and print the result to the stderr, and exit. */
1319 #define FATAL_ERROR(fmt, arg) \
1321 fprintf (stderr, fmt, arg); \
1326 x_error_handler (Display *display, XErrorEvent *error)
1333 main (int argc, char **argv)
1335 XtActionsRec actions[] = { {"Expose", ExposeProc} };
1339 OTF_GlyphString gstring;
1344 int fixed_pixel_size = 0;
1347 pixel_size = DEFAULT_PIXEL_SIZE;
1349 char *str = getenv ("PIXEL_SIZE");
1351 if (str && (i = atoi (str)) > 0)
1354 fixed_pixel_size = 1;
1358 gstring.size = gstring.used = 256;
1359 g = calloc (256, sizeof (OTF_Glyph));
1362 shell = XtOpenApplication (&context, "OTFView", NULL, 0, &argc, argv, NULL,
1363 shellWidgetClass, arg, 0);
1364 display = XtDisplay (shell);
1365 /*XSynchronize (display, True);*/
1366 XSetErrorHandler (x_error_handler);
1367 display_width = DisplayWidth (display,
1368 XScreenNumberOfScreen (XtScreen (shell)));
1369 font = XLoadQueryFont (display, DEFAULT_FONT_NAME);
1371 font = XLoadQueryFont (display, "fixed");
1373 if (argc != 2 || !strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
1375 fprintf (stderr, "Usage: %s [ X-OPTION ... ] OTF-FILE\n",
1376 basename (argv[0]));
1378 " Pixel size is decided by the environment variable PIXEL_SIZE ((default %d).\n", DEFAULT_PIXEL_SIZE);
1382 if (strstr (filename, ".ttf")
1383 || strstr (filename, ".TTF")
1384 || strstr (filename, ".otf")
1385 || strstr (filename, ".OTF"))
1387 otf = OTF_open (filename);
1389 || OTF_get_table (otf, "head") < 0
1390 || OTF_get_table (otf, "cmap") < 0
1391 || (OTF_check_table (otf, "GSUB") < 0
1392 && OTF_check_table (otf, "GPOS") < 0))
1396 if ((err = FT_Init_FreeType (&library)))
1397 FATAL_ERROR ("%s\n", "FT_Init_FreeType: error");
1398 err = FT_New_Face (library, filename, 0, &face);
1399 if (err == FT_Err_Unknown_File_Format)
1400 FATAL_ERROR ("%s\n", "FT_New_Face: unknown file format");
1402 FATAL_ERROR ("%s\n", "FT_New_Face: unknown error");
1403 if ((err = FT_Set_Pixel_Sizes (face, 0, pixel_size)))
1404 FATAL_ERROR ("%s\n", "FT_Set_Pixel_Sizes: error");
1410 filename = basename (filename);
1411 sprintf (title, "%s family:%s style:%s",
1412 filename, face->family_name, face->style_name);
1413 XtSetArg (arg[0], XtNtitle, title);
1414 XtSetValues (shell, arg, 1);
1417 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1418 * pixel_size / face->units_per_EM);
1419 if (! fixed_pixel_size && glyph_width * 16 > display_width * 0.8)
1421 pixel_size = (pixel_size * display_width * 0.8 / 16 / glyph_width);
1422 FT_Set_Pixel_Sizes (face, 0, pixel_size);
1423 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1424 * pixel_size / face->units_per_EM);
1426 if (glyph_width < FONT_WIDTH * 4)
1427 glyph_width = FONT_WIDTH * 4;
1429 glyph_height = ((face->bbox.yMax - face->bbox.yMin)
1430 * pixel_size / face->units_per_EM);
1432 glyph_x = - (face->bbox.xMin * pixel_size / face->units_per_EM);
1433 glyph_y = face->bbox.yMax * pixel_size / face->units_per_EM;
1434 none_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1435 glyph_width, glyph_height, 1);
1438 unsigned long valuemask = GCFunction | GCLineWidth;
1441 gc = XCreateGC (display, none_pixmap, (unsigned long) 0, NULL);
1442 values.function = GXset;
1443 values.line_width = 1;
1444 gc_set = XCreateGC (display, none_pixmap, valuemask, &values);
1445 values.function = GXor;
1446 gc_or = XCreateGC (display, none_pixmap, valuemask, &values);
1447 values.function = GXcopyInverted;
1448 gc_inv = XCreateGC (display, none_pixmap, valuemask, &values);
1451 XFillRectangle (display, none_pixmap, gc, 0, 0,
1452 glyph_width, glyph_height);
1453 XDrawString (display, none_pixmap, gc_inv,
1454 (glyph_width - XTextWidth (font, "none", 4)) / 2,
1455 glyph_height / 2, "none", 4);
1457 render_width = (glyph_width + 4) * 15 + 1;
1458 render_height = glyph_height + 2;
1460 charmap_rec[0].platform_id = -1;
1461 charmap_rec[0].encoding_id = -1;
1462 strcpy (charmap_rec[0].name, "no charmap");
1464 for (i = 0; i < face->num_charmaps; i++)
1466 charmap_rec[i + 1].platform_id = face->charmaps[i]->platform_id;
1467 charmap_rec[i + 1].encoding_id = face->charmaps[i]->encoding_id;
1468 sprintf (charmap_rec[i + 1].name, "%d-%d",
1469 charmap_rec[i + 1].platform_id, charmap_rec[i + 1].encoding_id);
1470 if (face->charmaps[i]->platform_id == 0
1471 || (face->charmaps[i]->platform_id == 3
1472 && face->charmaps[i]->encoding_id == 1))
1473 strcat (charmap_rec[i + 1].name, " (unicode)");
1474 else if (face->charmaps[i]->platform_id == 1
1475 && face->charmaps[i]->encoding_id == 0)
1476 strcat (charmap_rec[i + 1].name, " (apple-roman)");
1479 raw_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1480 render_width, render_height, 1);
1481 seq_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1482 render_width, render_height, 1);
1484 memset (bitmap, 0, sizeof (bitmap));
1488 update_glyph_area ();
1489 update_render_area ();
1491 XtAppAddActions (context, actions, XtNumber (actions));
1492 XtRealizeWidget (shell);
1493 XtAppMainLoop (context);
1498 #else /* not HAVE_X11_XAW_COMMAND_H */
1501 main (int argc, char **argv)
1504 "Building of this program failed (lack of some header files)\n");