1 /* otfview.c -- View glyphs of OpenType fonts.
3 Copyright (C) 2003, 2004, 2005, 2006, 2008
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[0x110000];
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;
162 create_pixmap (int index)
164 int err = FT_Load_Glyph (face, index, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
170 bitmap[index].pixmap = none_pixmap;
173 ximage.height = face->glyph->bitmap.rows;
174 ximage.width = face->glyph->bitmap.width;
176 ximage.bits_per_pixel = 1;
178 ximage.format = XYPixmap;
179 ximage.data = (char *) face->glyph->bitmap.buffer;
180 ximage.byte_order = MSBFirst;
181 ximage.bitmap_unit = 8;
182 ximage.bitmap_bit_order = MSBFirst;
183 ximage.bitmap_pad = 8;
184 ximage.bytes_per_line = face->glyph->bitmap.pitch;
185 XInitImage (&ximage);
186 pixmap = XCreatePixmap (display, DefaultRootWindow (display),
187 glyph_width, glyph_height, 1);
188 XFillRectangle (display, pixmap, gc, 0, 0, glyph_width, glyph_height);
189 XPutImage (display, pixmap, gc, &ximage, 0, 0,
190 glyph_x + face->glyph->bitmap_left,
191 glyph_y - face->glyph->bitmap_top,
192 ximage.width, ximage.height);
193 bitmap[index].pixmap = pixmap;
194 bitmap[index].width = ximage.width;
195 bitmap[index].height = ximage.height;
196 bitmap[index].x = face->glyph->bitmap_left;
197 bitmap[index].y = - face->glyph->bitmap_top;
198 bitmap[index].advance = face->glyph->metrics.horiAdvance >> 6;
209 for (i = 0; i < 128; i++)
211 int index = glyph_index + i;
213 if (charmap_index >= 0)
214 index = FT_Get_Char_Index (face, (FT_ULong) index);
215 if (charmap_index >= 0 && ! index)
216 XtSetArg (arg[0], XtNbitmap, none_pixmap);
219 if (! bitmap[index].pixmap)
220 create_pixmap (index);
221 XtSetArg (arg[0], XtNbitmap, bitmap[index].pixmap);
223 XtSetValues (glyph[i], arg, 1);
226 msb = (glyph_index >> 7) % 2 ? 8 : 0;
227 for (i = 0; i < 8; i++)
231 sprintf (str, "%XX", i | msb );
232 XtSetArg (arg[0], XtNheight, glyph_height + 5);
233 XtSetArg (arg[1], XtNlabel, str);
234 XtSetValues (index_label[i], arg, 2);
237 if (glyph_index < 0x10000)
238 sprintf (buf, " %04X-%04X ", glyph_index, glyph_index + 0x7F);
240 sprintf (buf, "%06X-%06X", glyph_index, glyph_index + 0x7F);
241 XtSetArg (arg[0], XtNlabel, buf);
242 XtSetValues (range, arg, 1);
246 get_features (OTF_FeatureList *list, FeatureRec *rec)
251 if (! rec->langsys || ! rec->features || ! rec->features[0].on)
253 for (i = n = 0; i < rec->langsys->FeatureCount; i++)
255 if (rec->features[i].on)
260 str = malloc (n * 5);
261 for (i = 0, p = str; i < n; i++, p += 5)
263 OTF_tag_name (rec->features[i].tag, p);
271 #define DEVICE_DELTA(table, size) \
272 (((table).DeltaValue \
273 && ((size) >= (table).StartSize && (size) <= (table).EndSize)) \
274 ? (table).DeltaValue[(size) >= (table).StartSize] \
278 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
279 OTF_Glyph *g, int *x, int *y)
281 if (anchor->AnchorFormat == 2)
284 int ap = anchor->f.f1.AnchorPoint;
286 FT_Load_Glyph (ft_face, (FT_UInt) g->glyph_id, FT_LOAD_MONOCHROME);
287 outline = &ft_face->glyph->outline;
288 if (ap < outline->n_points)
290 *x = outline->points[ap].x;
291 *y = outline->points[ap].y;
294 else if (anchor->AnchorFormat == 3)
296 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, pixel_size);
297 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, pixel_size);
305 OTF_GlyphString gstring;
306 OTF_Glyph *g, *prev, *base, *mark;
308 int len = glyph_rec.n_glyphs;
310 int unitsPerEm = face->units_per_EM;
312 gstring.size = gstring.used = len;
313 gstring.glyphs = malloc (sizeof (OTF_Glyph) * len);
314 memset (gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
315 for (i = 0; i < len; i++)
316 gstring.glyphs[i].c = gstring.glyphs[i].glyph_id = glyph_rec.glyphs[i];
318 XFillRectangle (display, seq_pixmap, gc, 0, 0, render_width, render_height);
319 XDrawLine (display, seq_pixmap, gc_set, 0, glyph_y, render_width, glyph_y);
324 OTF_drive_gdef (otf, &gstring);
325 OTF_drive_cmap (otf, &gstring);
328 str = get_features (&otf->gsub->FeatureList, &gsub);
331 if (do_alternate_subst)
332 OTF_drive_gsub_alternate (otf, &gstring, NULL, NULL, str);
334 OTF_drive_gsub (otf, &gstring, NULL, NULL, str);
340 str = get_features (&otf->gpos->FeatureList, &gpos);
343 OTF_drive_gpos2 (otf, &gstring, NULL, NULL, str);
354 for (prev = gstring.glyphs, g = gstring.glyphs + gstring.used - 1;
355 prev < g; prev++, g--)
356 temp = *prev, *prev = *g, *g = temp;
357 for (g = gstring.glyphs; g < gstring.glyphs + gstring.used; g++)
358 if (g->GlyphClass == 3)
362 while (g < gstring.glyphs + gstring.used && g->GlyphClass == 3)
364 for (g0 = g; prev < g0; prev++, g0--)
365 temp = *prev, *prev = *g, *g = temp;
371 for (i = 0, x = glyph_x, prev = NULL, g = gstring.glyphs;
372 i < gstring.used; i++, prev = g++)
374 BitmapRec *bmp = bitmap + gstring.glyphs[i].glyph_id;
375 int xoff = 0, yoff = 0;
377 int advance = bmp->advance;
379 if (gstring.glyphs[i].glyph_id && ! bmp->pixmap)
381 create_pixmap (gstring.glyphs[i].glyph_id);
384 advance = bmp->advance;
386 if (g->positioning_type)
390 switch (g->positioning_type)
394 int format = g->f.f1.format;
396 if (format & OTF_XPlacement)
397 xoff = g->f.f1.value->XPlacement * pixel_size / unitsPerEm;
398 if (format & OTF_XPlaDevice)
399 xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, pixel_size);
400 if (format & OTF_YPlacement)
401 yoff = g->f.f1.value->YPlacement * pixel_size / unitsPerEm;
402 if (format & OTF_YPlaDevice)
403 yoff += DEVICE_DELTA (g->f.f1.value->YPlaDevice, pixel_size);
404 if (format & OTF_XAdvance)
405 advance += g->f.f1.value->XAdvance * pixel_size / unitsPerEm;
406 if (format & OTF_XAdvDevice)
407 advance += DEVICE_DELTA (g->f.f1.value->XAdvDevice,
413 /* Not yet supported. */
419 prev_width = base_width;
420 goto label_adjust_anchor;
421 default: /* i.e. case 6 */
428 int base_x, base_y, mark_x, mark_y;
430 base_x = g->f.f4.base_anchor->XCoordinate * pixel_size / unitsPerEm;
431 base_y = g->f.f4.base_anchor->YCoordinate * pixel_size / unitsPerEm;
432 mark_x = g->f.f4.mark_anchor->XCoordinate * pixel_size / unitsPerEm;
433 mark_y = g->f.f4.mark_anchor->YCoordinate * pixel_size / unitsPerEm;
435 if (g->f.f4.base_anchor->AnchorFormat != 1)
436 adjust_anchor (g->f.f4.base_anchor, face, prev, &base_x, &base_y);
437 if (g->f.f4.mark_anchor->AnchorFormat != 1)
438 adjust_anchor (g->f.f4.mark_anchor, face, g, &mark_x, &mark_y);
439 xoff = (base_x - prev_width) - mark_x;
440 yoff = base_y - mark_y;
443 if (i + 1 == gstring.used
444 || gstring.glyphs[i + 1].glyph_id
445 || ! gstring.glyphs[i + 1].positioning_type)
451 XCopyArea (display, bmp->pixmap, seq_pixmap, gc_or,
452 glyph_x + bmp->x, glyph_y + bmp->y, bmp->width, bmp->height,
453 x + bmp->x + xoff, glyph_y + bmp->y - yoff);
456 if (g->GlyphClass == OTF_GlyphClass0)
457 base = mark = g, base_width = advance;
458 else if (g->GlyphClass == OTF_GlyphClassMark)
461 base = g, base_width = advance;
463 free (gstring.glyphs);
465 XtSetArg (arg[0], XtNbitmap, seq_pixmap);
466 XtSetValues (seq_image, arg, 1);
471 update_render_area ()
477 XFillRectangle (display, raw_pixmap, gc, 0, 0, render_width, render_height);
478 for (i = 0, x = glyph_x; i < glyph_rec.n_glyphs; i++)
480 BitmapRec *bmp = bitmap + glyph_rec.glyphs[i];
483 XCopyArea (display, bmp->pixmap, raw_pixmap, gc,
484 0, 0, glyph_width, glyph_height,
485 (glyph_width + 4) * i + 1, 1);
486 XDrawRectangle (display, raw_pixmap, gc_set,
487 (glyph_width + 4) * i, 0,
488 glyph_width + 1, glyph_height + 1);
489 XDrawLine (display, raw_pixmap, gc_set,
490 (glyph_width + 4) * i + 1 + glyph_x, 1,
491 (glyph_width + 4) * i + 1 + glyph_x, glyph_height + 1);
492 XDrawLine (display, raw_pixmap, gc_set,
493 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance, 1,
494 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance,
497 sprintf (buf, "%04X", glyph_rec.codes[i]);
498 XDrawString (display, raw_pixmap, gc_inv,
499 (glyph_width + 1) * i + 1
500 + (glyph_width - XTextWidth (font, buf, 4)) / 2,
501 glyph_height + 2 + FONT_HEIGHT, buf, 4);
503 XtSetArg (arg[0], XtNbitmap, raw_pixmap);
504 XtSetValues (raw_image, arg, 1);
509 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
511 XtAppSetExitFlag (XtWidgetToApplicationContext (w));
515 DumpProc (Widget w, XtPointer client_data, XtPointer call_data)
517 int g_width, g_height;
519 /* unit in points (1/72 inch); to fit in both US-letter and A4 */
520 static int xoff = 30, yoff = 30;
521 static int unit = 30;
522 static int margin = 2;
523 static int title_height = 20, label_height = 10;
524 int total_width = (unit + margin * 2) * 16;
525 int total_height = (unit + margin * 2 + label_height) * 16 + title_height;
526 /* pixel size (dots) */
529 char *name = alloca (strlen (filename) + 10);
531 int index = (glyph_index / 0x100) * 0x100;
534 g_width = face->bbox.xMax - face->bbox.xMin;
535 g_height = face->bbox.yMax - face->bbox.yMin;
536 if (g_width > g_height)
538 scale = g_width * size;
539 g_x = face->bbox.xMin * unit / g_width;
540 g_y = face->bbox.yMin * unit / g_width;
544 scale = g_height * size;
545 g_x = face->bbox.xMin * unit / g_height;
546 g_y = face->bbox.yMin * unit / g_height;
548 scale /= face->units_per_EM;
550 FT_Set_Pixel_Sizes (face, 0, size);
552 sprintf (name, "%s-%04X.ps", face->family_name, index);
553 printf ("Writing %s ... ", name);
555 fp = fopen (name, "w");
557 fprintf (fp, "%s\n", "%!PS-Adobe-2.0 EPSF-2.0");
558 fprintf (fp, "%s\n", "%%Creater: otfview");
559 fprintf (fp, "%s %s(%s)-%04X\n", "%%Title:",
560 face->family_name, face->style_name, index);
561 fprintf (fp, "%s\n", "%%Pages: 1");
562 fprintf (fp, "%s %d %d %d %d\n", "%%BoundingBox:",
563 xoff, yoff, xoff + total_width, yoff + total_height);
564 fprintf (fp, "%s\n", "%%EndComments");
565 fprintf (fp, "%s\n", "%%BeginProlog");
566 fprintf (fp, "/W %d def\n", unit + margin * 2);
567 fprintf (fp, "/H %d def\n", unit + margin * 2 + label_height);
568 fprintf (fp, "/STR 10 string def\n");
569 fprintf (fp, "/DrawIndex {\n");
570 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");
571 fprintf (fp, "} def\n");
572 fprintf (fp, "/DrawTitle {\n");
573 fprintf (fp, " /Courier findfont 20 scalefont setfont\n");
574 fprintf (fp, " %d %d 4 add moveto\n", xoff + total_width / 2,
575 yoff + total_height - title_height + 2);
576 fprintf (fp, " (%s(%s)-%04X) dup stringwidth pop 2 div neg 0 rmoveto show\n",
577 face->family_name, face->style_name, index);
578 fprintf (fp, "} def\n");
579 fprintf (fp, "/DrawFrame { gsave %d %d translate 0 setlinewidth\n",
581 fprintf (fp, " /Courier findfont 10 scalefont setfont\n");
582 fprintf (fp, " /I %d def\n", index);
583 fprintf (fp, " 0 1 16 { W mul 0 moveto 0 H 16 mul rlineto stroke } for\n");
584 fprintf (fp, " 0 1 16 { H mul 0 exch moveto W 16 mul 0 rlineto stroke } for\n");
585 fprintf (fp, " 0 1 15 { H mul %d add 0 exch moveto W 16 mul 0 rlineto stroke } for\n", label_height);
586 fprintf (fp, " 15 -1 0 { gsave H mul 0 exch translate 0 0 moveto\n");
587 fprintf (fp, " 0 1 15 { gsave W mul 0 moveto\n");
588 fprintf (fp, " 4 2 rmoveto DrawIndex /I I 1 add def grestore} for\n");
589 fprintf (fp, " grestore } for grestore } def\n");
590 fprintf (fp, "%s\n", "%%EndProlog");
591 fprintf (fp, "DrawTitle DrawFrame\n");
593 for (i = 0; i < 16; i++)
594 for (j = 0; j < 16; j++, index++)
598 if (charmap_index >= 0)
599 idx = FT_Get_Char_Index (face, (FT_ULong) index);
603 && FT_Load_Glyph (face, idx, FT_LOAD_RENDER | FT_LOAD_MONOCHROME) == 0
604 && face->glyph->bitmap.rows > 0
605 && face->glyph->bitmap.width > 0)
607 unsigned char *p = face->glyph->bitmap.buffer;
608 int width = (face->glyph->bitmap.width - 1) / 8 + 1;
610 fprintf (fp, "gsave %f %f translate %d %d scale 0 0 moveto\n",
611 xoff + (unit + margin * 2) * j + margin - g_x,
612 yoff + (unit + label_height + margin * 2) * (15 - i) + label_height + margin - g_y,
614 fprintf (fp, "%d %d true [%f 0 0 %f %d %d]\n",
615 width * 8, face->glyph->bitmap.rows,
616 scale, -scale, -face->glyph->bitmap_left,
617 face->glyph->bitmap_top);
619 for (k = 0; k < face->glyph->bitmap.rows;
620 k++, p += face->glyph->bitmap.pitch)
622 for (l = 0; l < width; l++)
623 fprintf (fp, "%02X", p[l]);
626 fprintf (fp, ">} imagemask grestore\n");
630 int boxsize = unit + margin * 2;
632 fprintf (fp, "gsave 0 setlinewidth %d %d translate\n",
634 yoff + (boxsize + label_height) * (15 - i) + label_height);
635 fprintf (fp, "0 0 moveto %d %d lineto stroke\n",
637 fprintf (fp, "0 %d moveto %d 0 lineto stroke grestore\n",
641 fprintf (fp, "showpage\n");
645 FT_Set_Pixel_Sizes (face, 0, (int) pixel_size);
650 GlyphProc (Widget w, XtPointer client_data, XtPointer call_data)
652 int old_glyph_index = glyph_index;
654 if ((int) client_data == -3 && glyph_index > 0)
656 else if ((int) client_data == -2 && glyph_index > 0)
657 glyph_index = (glyph_index - 1) & 0x1FF000;
658 else if ((int) client_data == -1 && glyph_index > 0)
660 else if ((int) client_data == 1 && glyph_index < 0x10FF80)
662 else if ((int) client_data == 2 && glyph_index < 0x10F000)
663 glyph_index = (glyph_index + 0x1000) & 0x1FF000;
664 else if ((int) client_data == 3 && glyph_index < 0x10F000)
665 glyph_index = 0x10FF80;
666 if (glyph_index != old_glyph_index)
667 update_glyph_area ();
671 CharmapProc (Widget w, XtPointer client_data, XtPointer call_data)
673 if (charmap_index == (int) client_data)
675 charmap_index = (int) client_data;
676 if (charmap_index >= 0)
677 FT_Set_Charmap (face, face->charmaps[charmap_index]);
678 update_glyph_area ();
682 RenderProc (Widget w, XtPointer client_data, XtPointer call_data)
684 if ((int) client_data < 0)
686 if (glyph_rec.n_glyphs > 0)
688 if ((int) client_data == -2)
689 glyph_rec.n_glyphs--;
691 glyph_rec.n_glyphs = 0;
692 update_render_area ();
695 else if (glyph_rec.n_glyphs < 64)
697 int index = glyph_index + (int) client_data;
699 if (charmap_index >= 0)
700 index = FT_Get_Char_Index (face, (FT_ULong) index);
701 if (bitmap[index].pixmap)
703 glyph_rec.codes[glyph_rec.n_glyphs] = glyph_index + (int) client_data;
704 glyph_rec.glyphs[glyph_rec.n_glyphs++] = index;
705 update_render_area ();
711 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
715 reversed = ! reversed;
717 XtSetArg (arg[0], XtNlabel, "L<-R");
719 XtSetArg (arg[0], XtNlabel, "L->R");
720 XtSetValues (w, arg, 1);
725 AltSubstProc (Widget w, XtPointer client_data, XtPointer call_data)
727 do_alternate_subst = ! do_alternate_subst;
732 FeatureProc (Widget w, XtPointer client_data, XtPointer call_data)
734 FeatureRec *rec = (FeatureRec *) client_data;
741 XtSetArg (arg[0], XtNlabel, &label);
742 XtGetValues (w, arg, 1);
743 if (! strcmp (label, "all"))
745 else if (! strcmp (label, "none"))
749 for (idx = 0; idx < rec->langsys->FeatureCount; idx++)
750 if (rec->features[idx].w == w)
752 if (idx == rec->langsys->FeatureCount)
759 for (i = j = 0; j < rec->langsys->FeatureCount; j++)
761 int index = rec->langsys->FeatureIndex[j];
764 = rec->gsub_gpos->FeatureList.Feature[index].FeatureTag;
765 rec->features[j].on = on;
770 OTF_Tag tag = rec->features[idx].tag;
773 if (rec->features[i].on)
776 j < rec->langsys->FeatureCount && rec->features[j].on; j++)
777 rec->features[j - 1].tag = rec->features[j].tag;
778 rec->features[j - 1].tag = tag;
779 rec->features[j - 1].on = 0;
783 for (j = i + 1; i > 0 && ! rec->features[i - 1].on; i--)
784 rec->features[i].tag = rec->features[i - 1].tag;
785 rec->features[i].tag = tag;
786 rec->features[i].on = 1;
794 if (rec->features[i].on)
796 XtSetArg (arg[0], XtNborderWidth, 3);
797 XtSetArg (arg[1], XtNinternalHeight, 2);
798 XtSetArg (arg[2], XtNinternalWidth, 2);
802 XtSetArg (arg[0], XtNborderWidth, 1);
803 XtSetArg (arg[1], XtNinternalHeight, 4);
804 XtSetArg (arg[2], XtNinternalWidth, 4);
806 OTF_tag_name (rec->features[i].tag, str);
807 XtSetArg (arg[3], XtNlabel, str);
808 XtSetValues (rec->features[i].w, arg, 4);
814 setup_feature_rec (FeatureRec *rec)
820 if (! rec->gsub_gpos)
822 for (i = 0; i < rec->gsub_gpos->ScriptList.ScriptCount; i++)
823 if (rec->gsub_gpos->ScriptList.Script[i].ScriptTag == script_tag)
825 OTF_Script *script = rec->gsub_gpos->ScriptList.Script + i;
829 for (j = 0; j < script->LangSysCount; j++)
830 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
832 rec->langsys = script->LangSys + j;
837 rec->langsys = &rec->gsub_gpos->ScriptList.Script[i].DefaultLangSys;
845 XtSetArg (arg[0], XtNborderWidth, 1);
846 XtSetArg (arg[1], XtNinternalHeight, 4);
847 XtSetArg (arg[2], XtNinternalWidth, 4);
848 XtSetArg (arg[3], XtNborderColor, foreground);
849 XtSetArg (arg[4], XtNsensitive, True);
850 for (i = 0; i < rec->langsys->FeatureCount; i++)
852 OTF_Feature *feature = rec->gsub_gpos->FeatureList.Feature;
853 int index = rec->langsys->FeatureIndex[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;
864 rec->features[i].tag = feature[index].FeatureTag;
865 rec->features[i].on = 0;
866 OTF_tag_name (rec->features[i].tag, label);
867 XtSetArg (arg[5], XtNlabel, label);
868 XtSetValues (rec->features[i].w, arg, 6);
871 XtSetArg (arg[0], XtNborderColor, background);
872 XtSetArg (arg[1], XtNsensitive, False);
873 XtSetArg (arg[2], XtNlabel, " ");
874 for (; i < rec->num_features; i++)
876 if (! rec->features[i].w)
878 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
879 rec->parent, arg, 0);
880 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
881 rec->features[i].w = w;
883 XtSetValues (rec->features[i].w, arg, 3);
888 compose_script_langsys (OTF_Tag script, OTF_Tag langsys, char *name)
890 OTF_tag_name (script, name);
894 OTF_tag_name (langsys, name + 5);
901 decompose_script_langsys (OTF_Tag *script, OTF_Tag *langsys, char *name)
903 *script = OTF_tag (name);
905 *langsys = OTF_tag (name + 5);
911 ScriptProc (Widget w, XtPointer client_data, XtPointer call_data)
914 OTF_Tag script, langsys;
917 XtSetArg (arg[0], XtNlabel, &name);
918 XtGetValues (w, arg, 1);
919 decompose_script_langsys (&script, &langsys, name);
920 if (script_tag == script && langsys_tag == langsys)
923 langsys_tag = langsys;
924 setup_feature_rec (&gsub);
925 setup_feature_rec (&gpos);
930 create_otf_script_widgets (Widget prev)
942 XtSetArg (arg[0], XtNborderWidth, 0);
943 XtSetArg (arg[1], XtNleft, XawChainLeft);
944 XtSetArg (arg[2], XtNright, XawChainLeft);
945 XtSetArg (arg[3], XtNtop, XawChainTop);
946 XtSetArg (arg[4], XtNbottom, XawChainTop);
947 XtSetArg (arg[5], XtNfromVert, prev);
948 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
949 prev = XtCreateManagedWidget ("Script", boxWidgetClass, render_area, arg, 7);
950 XtCreateManagedWidget ("script(langsys)", labelWidgetClass, prev, arg, 1);
954 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
955 n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
957 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
958 n += otf->gpos->ScriptList.Script[i].LangSysCount + 1;
959 script_langsys = alloca ((sizeof script_langsys[0]) * n);
963 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
965 OTF_Tag tag = otf->gsub->ScriptList.Script[i].ScriptTag;
967 script_langsys[n].script = tag;
968 script_langsys[n++].langsys = 0;
970 < otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount)
972 = otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount;
973 for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
975 script_langsys[n].script = tag;
976 script_langsys[n++].langsys
977 = otf->gsub->ScriptList.Script[i].LangSysRecord[j].LangSysTag;
979 < otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount)
981 = otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount;
984 gsub.num_features = nfeatures;
987 gsub.num_features = nfeatures;
988 gsub.features = malloc ((sizeof (FeatureElement)) * nfeatures);
989 memset (gsub.features, 0, (sizeof (FeatureElement)) * nfeatures);
994 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
996 OTF_Tag tag = otf->gpos->ScriptList.Script[i].ScriptTag;
1000 < otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount)
1002 = otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount;
1003 for (k = 0; k < prev_n; k++)
1004 if (tag == script_langsys[k].script)
1008 script_langsys[n].script = tag;
1009 script_langsys[n++].langsys = 0;
1011 for (j = 0; j < otf->gpos->ScriptList.Script[i].LangSysCount; j++)
1017 OTF_Script *script = otf->gpos->ScriptList.Script + i;
1019 for (l = k; l < prev_n && tag == script_langsys[l].script; l++)
1020 if (script->LangSysRecord[j].LangSysTag
1021 == script_langsys[l].langsys)
1028 script_langsys[n].script = tag;
1029 script_langsys[n++].langsys = 0;
1032 < otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount)
1034 = otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount;
1040 gpos.num_features = nfeatures;
1041 gpos.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1042 memset (gpos.features, 0, (sizeof (FeatureElement)) * nfeatures);
1048 script_tag = script_langsys[0].script;
1049 langsys_tag = script_langsys[0].langsys;
1050 compose_script_langsys (script_tag, langsys_tag, name);
1054 XtSetArg (arg[0], XtNforeground, background);
1055 XtSetArg (arg[1], XtNbackground, foreground);
1056 XtCreateManagedWidget (name, labelWidgetClass, prev, arg, 2);
1060 XtSetArg (arg[0], XtNstate, True);
1061 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1062 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1063 XtSetArg (arg[0], XtNradioGroup, w);
1064 for (i = 1; i < n; i++)
1066 compose_script_langsys (script_langsys[i].script,
1067 script_langsys[i].langsys, name);
1068 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1069 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1077 create_otf_widgets (Widget prev, FeatureRec *rec)
1082 XtSetArg (arg[0], XtNborderWidth, 0);
1083 XtSetArg (arg[1], XtNleft, XawChainLeft);
1084 XtSetArg (arg[2], XtNright, XawChainLeft);
1085 XtSetArg (arg[3], XtNtop, XawChainTop);
1086 XtSetArg (arg[4], XtNbottom, XawChainTop);
1087 XtSetArg (arg[5], XtNfromVert, prev);
1088 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1089 prev = XtCreateManagedWidget (rec->label, boxWidgetClass, render_area,
1091 XtCreateManagedWidget (rec->label, labelWidgetClass, prev, arg, 1);
1092 XtSetArg (arg[0], XtNborderWidth, 1);
1093 XtSetArg (arg[1], XtNinternalHeight, 4);
1094 XtSetArg (arg[2], XtNinternalWidth, 4);
1095 w = XtCreateManagedWidget ("all", commandWidgetClass, prev, arg, 3);
1096 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1097 w = XtCreateManagedWidget ("none", commandWidgetClass, prev, arg, 3);
1098 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1101 setup_feature_rec (rec);
1108 String quit_action = "<KeyPress>q: set() notify() unset()";
1109 String FIRST_action = "<KeyPress>f: set() notify() unset()\n\
1110 <KeyPress>Home: set() notify() unset()";
1111 String PREV_action = "Shift<KeyPress>p: set() notify() unset()\n\
1112 <KeyPress>Up: set() notify() unset()";
1113 String prev_action = "~Shift<KeyPress>p: set() notify() unset()\n\
1114 <KeyPress>Left: set() notify() unset()";
1115 String next_action = "~Shift<KeyPress>n: set() notify() unset()\n\
1116 <KeyPress>Right: set() notify() unset()";
1117 String NEXT_action = "Shift<KeyPress>n: set() notify() unset()\n\
1118 <KeyPress>Down: set() notify() unset()";
1119 String LAST_action = "<KeyPress>l: set() notify() unset()\n\
1120 <KeyPress>End: set() notify() unset()";
1124 String trans = "<Expose>: Expose()";
1126 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans));
1127 frame = XtCreateManagedWidget ("frame", formWidgetClass, shell, arg, 1);
1129 XtSetArg (arg[0], XtNleft, XawChainLeft);
1130 XtSetArg (arg[1], XtNright, XawChainLeft);
1131 XtSetArg (arg[2], XtNtop, XawChainTop);
1132 XtSetArg (arg[3], XtNbottom, XawChainTop);
1133 XtSetArg (arg[4], XtNborderWidth, 0);
1134 XtSetArg (arg[5], XtNorientation, XtorientHorizontal);
1135 command_area = XtCreateManagedWidget ("command-area", boxWidgetClass,
1137 XtSetArg (arg[6], XtNfromVert, command_area);
1138 navi_area = XtCreateManagedWidget ("navi-area", boxWidgetClass,
1140 XtSetArg (arg[4], XtNborderWidth, 0);
1141 XtSetArg (arg[5], XtNfromVert, navi_area);
1142 XtSetArg (arg[6], XtNdefaultDistance, 0);
1143 glyph_area = XtCreateManagedWidget ("glyph-area", formWidgetClass,
1145 XtSetArg (arg[5], XtNfromVert, glyph_area);
1146 render_area = XtCreateManagedWidget ("render-area", formWidgetClass,
1149 XtSetArg (arg[0], XtNaccelerators, XtParseAcceleratorTable (quit_action));
1150 quit = XtCreateManagedWidget ("Quit", commandWidgetClass,
1151 command_area, arg, 1);
1152 XtAddCallback (quit, XtNcallback, QuitProc, NULL);
1154 dump = XtCreateManagedWidget ("DumpImage", commandWidgetClass,
1155 command_area, arg, 1);
1156 XtAddCallback (dump, XtNcallback, DumpProc, NULL);
1158 XtSetArg (arg[0], XtNborderWidth, 0);
1159 XtSetArg (arg[1], XtNwidth, 10);
1160 XtCreateManagedWidget ("spacer", boxWidgetClass, command_area, arg, 2);
1162 charmap = alloca (sizeof (Widget) * (face->num_charmaps + 1));
1163 XtSetArg (arg[0], XtNstate, True);
1164 charmap[0] = XtCreateManagedWidget (charmap_rec[0].name, toggleWidgetClass,
1165 command_area, arg, 1);
1166 XtAddCallback (charmap[0], XtNcallback, CharmapProc, (XtPointer) -1);
1167 XtSetArg (arg[0], XtNradioGroup, charmap[0]);
1168 for (i = 0; i < face->num_charmaps; i++)
1170 charmap[i + 1] = XtCreateManagedWidget (charmap_rec[i + 1].name,
1172 command_area, arg, 1);
1173 XtAddCallback (charmap[i + 1], XtNcallback, CharmapProc, (XtPointer) i);
1176 XtSetArg (arg[0], XtNlabel, " |< (f)");
1177 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (FIRST_action));
1178 FIRST = XtCreateManagedWidget ("FIRST", commandWidgetClass,
1180 XtAddCallback (FIRST, XtNcallback, GlyphProc, (XtPointer) -3);
1181 XtSetArg (arg[0], XtNlabel, "<< (P)");
1182 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (PREV_action));
1183 PREV = XtCreateManagedWidget ("PREV", commandWidgetClass,
1185 XtAddCallback (PREV, XtNcallback, GlyphProc, (XtPointer) -2);
1186 XtSetArg (arg[0], XtNlabel, "< (p)");
1187 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (prev_action));
1188 prev = XtCreateManagedWidget ("prev", commandWidgetClass,
1190 XtAddCallback (prev, XtNcallback, GlyphProc, (XtPointer) -1);
1191 XtSetArg (arg[0], XtNlabel, " 0000 ");
1192 range = XtCreateManagedWidget ("range", labelWidgetClass,
1194 XtSetArg (arg[0], XtNforeground, &foreground);
1195 XtSetArg (arg[1], XtNbackground, &background);
1196 XtGetValues (range, arg, 2);
1198 XtSetArg (arg[0], XtNlabel, "> (n)");
1199 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (next_action));
1200 next = XtCreateManagedWidget ("next", commandWidgetClass,
1202 XtAddCallback (next, XtNcallback, GlyphProc, (XtPointer) 1);
1203 XtSetArg (arg[0], XtNlabel, ">> (N)");
1204 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (NEXT_action));
1205 NEXT = XtCreateManagedWidget ("NEXT", commandWidgetClass,
1207 XtAddCallback (NEXT, XtNcallback, GlyphProc, (XtPointer) 2);
1208 XtSetArg (arg[0], XtNlabel, ">| (l)");
1209 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (LAST_action));
1210 LAST = XtCreateManagedWidget ("LAST", commandWidgetClass,
1212 XtAddCallback (LAST, XtNcallback, GlyphProc, (XtPointer) 3);
1214 XtSetArg (arg[0], XtNleft, XawChainLeft);
1215 XtSetArg (arg[1], XtNright, XawChainLeft);
1216 XtSetArg (arg[2], XtNtop, XawChainTop);
1217 XtSetArg (arg[3], XtNbottom, XawChainTop);
1219 for (i = 0; i < 8; i++)
1225 sprintf (str, "%XX", i);
1226 XtSetArg (arg[n], XtNheight, glyph_height + 5), n++;
1227 XtSetArg (arg[n], XtNlabel, str), n++;
1228 XtSetArg (arg[n], XtNborderWidth, 0), n++;
1230 XtSetArg (arg[n], XtNfromVert, w), n++;
1231 head = XtCreateManagedWidget (str, labelWidgetClass, glyph_area, arg, n);
1232 index_label[i] = head;
1233 for (j = 0; j < 16; j++)
1239 XtSetArg (arg[n], XtNfromVert, w), n++;
1241 XtSetArg (arg[n], XtNfromHoriz, head), n++;
1243 XtSetArg (arg[n], XtNfromHoriz, glyph[k - 1]), n++;
1244 XtSetArg (arg[n], XtNbitmap, none_pixmap), n++;
1245 glyph[k] = XtCreateManagedWidget ("glyph", commandWidgetClass,
1246 glyph_area, arg, n);
1247 XtAddCallback (glyph[k], XtNcallback, RenderProc, (XtPointer) k);
1251 /* 10 = (1 (border_width) + 4 (inner_width)) * 2 */
1252 XtSetArg(arg[4], XtNwidth, glyph_width + 10);
1253 XtSetArg (arg[5], XtNfromVert, glyph[112]);
1254 XtSetArg (arg[6], XtNfromHoriz, w);
1255 XtSetArg (arg[7], XtNborderWidth, 0);
1257 for (j = 0; j < 16; j++)
1261 sprintf (str, "X%X", j);
1262 XtSetArg (arg[8], XtNlabel, str);
1263 w = XtCreateManagedWidget ("idx", labelWidgetClass, glyph_area, arg, 9);
1264 XtSetArg (arg[6], XtNfromHoriz, w);
1267 XtSetArg (arg[0], XtNleft, XawChainLeft);
1268 XtSetArg (arg[1], XtNright, XawChainLeft);
1269 XtSetArg (arg[2], XtNtop, XawChainTop);
1270 XtSetArg (arg[3], XtNbottom, XawChainTop);
1271 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1272 XtSetArg (arg[5], XtNborderWidth, 0);
1273 w = XtCreateManagedWidget ("clear-box", boxWidgetClass, render_area, arg, 6);
1274 clear = XtCreateManagedWidget ("clear", commandWidgetClass, w, arg, 0);
1275 XtAddCallback (clear, XtNcallback, RenderProc, (XtPointer) -1);
1276 del = XtCreateManagedWidget ("delete", commandWidgetClass, w, arg, 0);
1277 XtAddCallback (del, XtNcallback, RenderProc, (XtPointer) -2);
1278 bidi = XtCreateManagedWidget ("L->R", toggleWidgetClass, w, arg, 0);
1279 XtAddCallback (bidi, XtNcallback, BidiProc, NULL);
1280 alt_subst = XtCreateManagedWidget ("AltSubst", toggleWidgetClass, w, arg, 0);
1281 XtAddCallback (alt_subst, XtNcallback, AltSubstProc, NULL);
1283 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1284 XtSetArg (arg[5], XtNborderWidth, 0);
1285 XtSetArg (arg[6], XtNfromVert, w);
1286 raw = XtCreateManagedWidget ("raw", boxWidgetClass, render_area, arg, 7);
1288 XtSetArg (arg[0], XtNborderWidth, 0);
1289 XtSetArg (arg[1], XtNlabel, "raw: ");
1290 raw_label = XtCreateManagedWidget ("raw-label", labelWidgetClass,
1292 XtSetArg (arg[1], XtNbitmap, raw_pixmap);
1293 raw_image = XtCreateManagedWidget ("raw-image", labelWidgetClass,
1298 OTF_get_table (otf, "GSUB");
1299 OTF_get_table (otf, "GPOS");
1300 w = create_otf_script_widgets (w);
1303 gsub.label = "GSUB";
1304 gsub.gsub_gpos = otf->gsub;
1305 w = create_otf_widgets (w, &gsub);
1309 gpos.label = "GPOS";
1310 gpos.gsub_gpos = otf->gpos;
1311 w = create_otf_widgets (w, &gpos);
1315 XtSetArg (arg[6], XtNfromVert, w);
1316 seq = XtCreateManagedWidget ("seq", boxWidgetClass, render_area, arg, 7);
1317 XtSetArg (arg[0], XtNborderWidth, 0);
1318 XtSetArg (arg[1], XtNlabel, "seq: ");
1319 seq_label = XtCreateManagedWidget ("seq-label", labelWidgetClass,
1321 XtSetArg (arg[1], XtNbitmap, seq_pixmap);
1322 seq_image = XtCreateManagedWidget ("seq-image", labelWidgetClass,
1324 XtInstallAllAccelerators (shell, shell);
1328 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1330 XTextProperty text_prop;
1331 char *pname = "otfview";
1332 char *fname = basename (filename);
1333 char *name = alloca (strlen (fname) + 3 + strlen (pname) + 1);
1335 sprintf (name, "%s - %s", pname, fname);
1336 text_prop.value = (unsigned char *) name;
1337 text_prop.encoding = XA_STRING;
1338 text_prop.format = 8;
1339 text_prop.nitems = strlen (name);
1340 XSetWMName (display, XtWindow (shell), &text_prop);
1343 /* Format MSG by FMT and print the result to the stderr, and exit. */
1345 #define FATAL_ERROR(fmt, arg) \
1347 fprintf (stderr, fmt, arg); \
1352 x_error_handler (Display *display, XErrorEvent *error)
1358 help (char **argv, int err)
1360 FILE *fp = err ? stderr : stdout;
1362 fprintf (fp, "Usage: %s [ X-OPTION ... ] OTF-FILE [INDEX]\n",
1363 basename (argv[0]));
1364 fprintf (fp, " Environment variable PIXEL_SIZE specifies the pixel size.\n");
1365 fprintf (fp, " The default pixel size is %d, but is reduced\n",
1366 DEFAULT_PIXEL_SIZE);
1367 fprintf (fp, " if your screen is not that wide.\n");
1372 main (int argc, char **argv)
1374 XtActionsRec actions[] = { {"Expose", ExposeProc} };
1378 OTF_GlyphString gstring;
1383 int fixed_pixel_size = 0;
1386 pixel_size = DEFAULT_PIXEL_SIZE;
1388 char *str = getenv ("PIXEL_SIZE");
1390 if (str && (i = atoi (str)) > 0)
1393 fixed_pixel_size = 1;
1397 gstring.size = gstring.used = 256;
1398 g = calloc (256, sizeof (OTF_Glyph));
1401 shell = XtOpenApplication (&context, "OTFView", NULL, 0, &argc, argv, NULL,
1402 shellWidgetClass, arg, 0);
1403 display = XtDisplay (shell);
1404 /*XSynchronize (display, True);*/
1405 XSetErrorHandler (x_error_handler);
1406 display_width = DisplayWidth (display,
1407 XScreenNumberOfScreen (XtScreen (shell)));
1408 font = XLoadQueryFont (display, DEFAULT_FONT_NAME);
1410 font = XLoadQueryFont (display, "fixed");
1414 if (!strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
1419 fontindex = atoi (argv[2]);
1421 FATAL_ERROR ("Invalid font index: %d\n", fontindex);
1424 if ((err = FT_Init_FreeType (&library)))
1425 FATAL_ERROR ("%s\n", "FT_Init_FreeType: error");
1426 err = FT_New_Face (library, filename, fontindex, &face);
1427 if (err == FT_Err_Unknown_File_Format)
1428 FATAL_ERROR ("%s\n", "FT_New_Face: unknown file format");
1430 FATAL_ERROR ("%s\n", "FT_New_Face: unknown error (invalid face index?)");
1431 if ((err = FT_Set_Pixel_Sizes (face, 0, pixel_size)))
1432 FATAL_ERROR ("%s\n", "FT_Set_Pixel_Sizes: error");
1434 if (strstr (filename, ".ttf")
1435 || strstr (filename, ".TTF")
1436 || strstr (filename, ".otf")
1437 || strstr (filename, ".OTF"))
1439 otf = OTF_open_ft_face (face);
1441 || OTF_get_table (otf, "head") < 0
1442 || OTF_get_table (otf, "cmap") < 0
1443 || (OTF_check_table (otf, "GSUB") < 0
1444 && OTF_check_table (otf, "GPOS") < 0))
1452 filename = basename (filename);
1453 sprintf (title, "%s family:%s style:%s",
1454 filename, face->family_name, face->style_name);
1455 XtSetArg (arg[0], XtNtitle, title);
1456 XtSetValues (shell, arg, 1);
1459 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1460 * pixel_size / face->units_per_EM);
1461 if (! fixed_pixel_size && glyph_width * 16 > display_width * 0.8)
1463 pixel_size = (pixel_size * display_width * 0.8 / 16 / glyph_width);
1464 FT_Set_Pixel_Sizes (face, 0, pixel_size);
1465 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1466 * pixel_size / face->units_per_EM);
1468 if (glyph_width < FONT_WIDTH * 4)
1469 glyph_width = FONT_WIDTH * 4;
1471 glyph_height = ((face->bbox.yMax - face->bbox.yMin)
1472 * pixel_size / face->units_per_EM);
1474 glyph_x = - (face->bbox.xMin * pixel_size / face->units_per_EM);
1475 glyph_y = face->bbox.yMax * pixel_size / face->units_per_EM;
1476 none_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1477 glyph_width, glyph_height, 1);
1480 unsigned long valuemask = GCFunction | GCLineWidth;
1483 gc = XCreateGC (display, none_pixmap, (unsigned long) 0, NULL);
1484 values.function = GXset;
1485 values.line_width = 1;
1486 gc_set = XCreateGC (display, none_pixmap, valuemask, &values);
1487 values.function = GXor;
1488 gc_or = XCreateGC (display, none_pixmap, valuemask, &values);
1489 values.function = GXcopyInverted;
1490 gc_inv = XCreateGC (display, none_pixmap, valuemask, &values);
1493 XFillRectangle (display, none_pixmap, gc, 0, 0,
1494 glyph_width, glyph_height);
1495 XDrawString (display, none_pixmap, gc_inv,
1496 (glyph_width - XTextWidth (font, "none", 4)) / 2,
1497 glyph_height / 2, "none", 4);
1499 render_width = (glyph_width + 4) * 15 + 1;
1500 render_height = glyph_height + 2;
1502 charmap_rec[0].platform_id = -1;
1503 charmap_rec[0].encoding_id = -1;
1504 strcpy (charmap_rec[0].name, "no charmap");
1506 for (i = 0; i < face->num_charmaps; i++)
1508 charmap_rec[i + 1].platform_id = face->charmaps[i]->platform_id;
1509 charmap_rec[i + 1].encoding_id = face->charmaps[i]->encoding_id;
1510 sprintf (charmap_rec[i + 1].name, "%d-%d",
1511 charmap_rec[i + 1].platform_id, charmap_rec[i + 1].encoding_id);
1512 if (face->charmaps[i]->platform_id == 0
1513 || (face->charmaps[i]->platform_id == 3
1514 && face->charmaps[i]->encoding_id == 1))
1515 strcat (charmap_rec[i + 1].name, " (unicode)");
1516 else if (face->charmaps[i]->platform_id == 1
1517 && face->charmaps[i]->encoding_id == 0)
1518 strcat (charmap_rec[i + 1].name, " (apple-roman)");
1521 raw_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1522 render_width, render_height, 1);
1523 seq_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1524 render_width, render_height, 1);
1526 memset (bitmap, 0, sizeof (bitmap));
1530 update_glyph_area ();
1531 update_render_area ();
1533 XtAppAddActions (context, actions, XtNumber (actions));
1534 XtRealizeWidget (shell);
1535 XtAppMainLoop (context);
1540 #else /* not HAVE_X11_XAW_COMMAND_H */
1543 main (int argc, char **argv)
1546 "Building of this program failed (lack of some header files)\n");