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);
327 str = get_features (&otf->gsub->FeatureList, &gsub);
330 if (do_alternate_subst)
331 OTF_drive_gsub_alternate (otf, &gstring, NULL, NULL, str);
333 OTF_drive_gsub (otf, &gstring, NULL, NULL, str);
339 str = get_features (&otf->gpos->FeatureList, &gpos);
342 OTF_drive_gpos2 (otf, &gstring, NULL, NULL, str);
353 for (prev = gstring.glyphs, g = gstring.glyphs + gstring.used - 1;
354 prev < g; prev++, g--)
355 temp = *prev, *prev = *g, *g = temp;
356 for (g = gstring.glyphs; g < gstring.glyphs + gstring.used; g++)
357 if (g->GlyphClass == 3)
361 while (g < gstring.glyphs + gstring.used && g->GlyphClass == 3)
363 for (g0 = g; prev < g0; prev++, g0--)
364 temp = *prev, *prev = *g, *g = temp;
370 for (i = 0, x = glyph_x, prev = NULL, g = gstring.glyphs;
371 i < gstring.used; i++, prev = g++)
373 BitmapRec *bmp = bitmap + gstring.glyphs[i].glyph_id;
374 int xoff = 0, yoff = 0;
376 int advance = bmp->advance;
378 if (gstring.glyphs[i].glyph_id && ! bmp->pixmap)
380 create_pixmap (gstring.glyphs[i].glyph_id);
383 advance = bmp->advance;
385 if (g->positioning_type)
389 switch (g->positioning_type)
393 int format = g->f.f1.format;
395 if (format & OTF_XPlacement)
396 xoff = g->f.f1.value->XPlacement * pixel_size / unitsPerEm;
397 if (format & OTF_XPlaDevice)
398 xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, pixel_size);
399 if (format & OTF_YPlacement)
400 yoff = g->f.f1.value->YPlacement * pixel_size / unitsPerEm;
401 if (format & OTF_YPlaDevice)
402 yoff += DEVICE_DELTA (g->f.f1.value->YPlaDevice, pixel_size);
403 if (format & OTF_XAdvance)
404 advance += g->f.f1.value->XAdvance * pixel_size / unitsPerEm;
405 if (format & OTF_XAdvDevice)
406 advance += DEVICE_DELTA (g->f.f1.value->XAdvDevice,
412 /* Not yet supported. */
418 prev_width = base_width;
419 goto label_adjust_anchor;
420 default: /* i.e. case 6 */
427 int base_x, base_y, mark_x, mark_y;
429 base_x = g->f.f4.base_anchor->XCoordinate * pixel_size / unitsPerEm;
430 base_y = g->f.f4.base_anchor->YCoordinate * pixel_size / unitsPerEm;
431 mark_x = g->f.f4.mark_anchor->XCoordinate * pixel_size / unitsPerEm;
432 mark_y = g->f.f4.mark_anchor->YCoordinate * pixel_size / unitsPerEm;
434 if (g->f.f4.base_anchor->AnchorFormat != 1)
435 adjust_anchor (g->f.f4.base_anchor, face, prev, &base_x, &base_y);
436 if (g->f.f4.mark_anchor->AnchorFormat != 1)
437 adjust_anchor (g->f.f4.mark_anchor, face, g, &mark_x, &mark_y);
438 xoff = (base_x - prev_width) - mark_x;
439 yoff = base_y - mark_y;
442 if (i + 1 == gstring.used
443 || gstring.glyphs[i + 1].glyph_id
444 || ! gstring.glyphs[i + 1].positioning_type)
450 XCopyArea (display, bmp->pixmap, seq_pixmap, gc_or,
451 glyph_x + bmp->x, glyph_y + bmp->y, bmp->width, bmp->height,
452 x + bmp->x + xoff, glyph_y + bmp->y - yoff);
455 if (g->GlyphClass == OTF_GlyphClass0)
456 base = mark = g, base_width = advance;
457 else if (g->GlyphClass == OTF_GlyphClassMark)
460 base = g, base_width = advance;
462 free (gstring.glyphs);
464 XtSetArg (arg[0], XtNbitmap, seq_pixmap);
465 XtSetValues (seq_image, arg, 1);
470 update_render_area ()
476 XFillRectangle (display, raw_pixmap, gc, 0, 0, render_width, render_height);
477 for (i = 0, x = glyph_x; i < glyph_rec.n_glyphs; i++)
479 BitmapRec *bmp = bitmap + glyph_rec.glyphs[i];
482 XCopyArea (display, bmp->pixmap, raw_pixmap, gc,
483 0, 0, glyph_width, glyph_height,
484 (glyph_width + 4) * i + 1, 1);
485 XDrawRectangle (display, raw_pixmap, gc_set,
486 (glyph_width + 4) * i, 0,
487 glyph_width + 1, glyph_height + 1);
488 XDrawLine (display, raw_pixmap, gc_set,
489 (glyph_width + 4) * i + 1 + glyph_x, 1,
490 (glyph_width + 4) * i + 1 + glyph_x, glyph_height + 1);
491 XDrawLine (display, raw_pixmap, gc_set,
492 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance, 1,
493 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance,
496 sprintf (buf, "%04X", glyph_rec.codes[i]);
497 XDrawString (display, raw_pixmap, gc_inv,
498 (glyph_width + 1) * i + 1
499 + (glyph_width - XTextWidth (font, buf, 4)) / 2,
500 glyph_height + 2 + FONT_HEIGHT, buf, 4);
502 XtSetArg (arg[0], XtNbitmap, raw_pixmap);
503 XtSetValues (raw_image, arg, 1);
508 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
510 XtAppSetExitFlag (XtWidgetToApplicationContext (w));
514 DumpProc (Widget w, XtPointer client_data, XtPointer call_data)
516 int g_width, g_height;
518 /* unit in points (1/72 inch); to fit in both US-letter and A4 */
519 static int xoff = 30, yoff = 30;
520 static int unit = 30;
521 static int margin = 2;
522 static int title_height = 20, label_height = 10;
523 int total_width = (unit + margin * 2) * 16;
524 int total_height = (unit + margin * 2 + label_height) * 16 + title_height;
525 /* pixel size (dots) */
528 char *name = alloca (strlen (filename) + 10);
530 int index = (glyph_index / 0x100) * 0x100;
533 g_width = face->bbox.xMax - face->bbox.xMin;
534 g_height = face->bbox.yMax - face->bbox.yMin;
535 if (g_width > g_height)
537 scale = g_width * size;
538 g_x = face->bbox.xMin * unit / g_width;
539 g_y = face->bbox.yMin * unit / g_width;
543 scale = g_height * size;
544 g_x = face->bbox.xMin * unit / g_height;
545 g_y = face->bbox.yMin * unit / g_height;
547 scale /= face->units_per_EM;
549 FT_Set_Pixel_Sizes (face, 0, size);
551 sprintf (name, "%s-%04X.ps", face->family_name, index);
552 printf ("Writing %s ... ", name);
554 fp = fopen (name, "w");
556 fprintf (fp, "%s\n", "%!PS-Adobe-2.0 EPSF-2.0");
557 fprintf (fp, "%s\n", "%%Creater: otfview");
558 fprintf (fp, "%s %s(%s)-%04X\n", "%%Title:",
559 face->family_name, face->style_name, index);
560 fprintf (fp, "%s\n", "%%Pages: 1");
561 fprintf (fp, "%s %d %d %d %d\n", "%%BoundingBox:",
562 xoff, yoff, xoff + total_width, yoff + total_height);
563 fprintf (fp, "%s\n", "%%EndComments");
564 fprintf (fp, "%s\n", "%%BeginProlog");
565 fprintf (fp, "/W %d def\n", unit + margin * 2);
566 fprintf (fp, "/H %d def\n", unit + margin * 2 + label_height);
567 fprintf (fp, "/STR 10 string def\n");
568 fprintf (fp, "/DrawIndex {\n");
569 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");
570 fprintf (fp, "} def\n");
571 fprintf (fp, "/DrawTitle {\n");
572 fprintf (fp, " /Courier findfont 20 scalefont setfont\n");
573 fprintf (fp, " %d %d 4 add moveto\n", xoff + total_width / 2,
574 yoff + total_height - title_height + 2);
575 fprintf (fp, " (%s(%s)-%04X) dup stringwidth pop 2 div neg 0 rmoveto show\n",
576 face->family_name, face->style_name, index);
577 fprintf (fp, "} def\n");
578 fprintf (fp, "/DrawFrame { gsave %d %d translate 0 setlinewidth\n",
580 fprintf (fp, " /Courier findfont 10 scalefont setfont\n");
581 fprintf (fp, " /I %d def\n", index);
582 fprintf (fp, " 0 1 16 { W mul 0 moveto 0 H 16 mul rlineto stroke } for\n");
583 fprintf (fp, " 0 1 16 { H mul 0 exch moveto W 16 mul 0 rlineto stroke } for\n");
584 fprintf (fp, " 0 1 15 { H mul %d add 0 exch moveto W 16 mul 0 rlineto stroke } for\n", label_height);
585 fprintf (fp, " 15 -1 0 { gsave H mul 0 exch translate 0 0 moveto\n");
586 fprintf (fp, " 0 1 15 { gsave W mul 0 moveto\n");
587 fprintf (fp, " 4 2 rmoveto DrawIndex /I I 1 add def grestore} for\n");
588 fprintf (fp, " grestore } for grestore } def\n");
589 fprintf (fp, "%s\n", "%%EndProlog");
590 fprintf (fp, "DrawTitle DrawFrame\n");
592 for (i = 0; i < 16; i++)
593 for (j = 0; j < 16; j++, index++)
597 if (charmap_index >= 0)
598 idx = FT_Get_Char_Index (face, (FT_ULong) index);
602 && FT_Load_Glyph (face, idx, FT_LOAD_RENDER | FT_LOAD_MONOCHROME) == 0
603 && face->glyph->bitmap.rows > 0
604 && face->glyph->bitmap.width > 0)
606 unsigned char *p = face->glyph->bitmap.buffer;
607 int width = (face->glyph->bitmap.width - 1) / 8 + 1;
609 fprintf (fp, "gsave %f %f translate %d %d scale 0 0 moveto\n",
610 xoff + (unit + margin * 2) * j + margin - g_x,
611 yoff + (unit + label_height + margin * 2) * (15 - i) + label_height + margin - g_y,
613 fprintf (fp, "%d %d true [%f 0 0 %f %d %d]\n",
614 width * 8, face->glyph->bitmap.rows,
615 scale, -scale, -face->glyph->bitmap_left,
616 face->glyph->bitmap_top);
618 for (k = 0; k < face->glyph->bitmap.rows;
619 k++, p += face->glyph->bitmap.pitch)
621 for (l = 0; l < width; l++)
622 fprintf (fp, "%02X", p[l]);
625 fprintf (fp, ">} imagemask grestore\n");
629 int boxsize = unit + margin * 2;
631 fprintf (fp, "gsave 0 setlinewidth %d %d translate\n",
633 yoff + (boxsize + label_height) * (15 - i) + label_height);
634 fprintf (fp, "0 0 moveto %d %d lineto stroke\n",
636 fprintf (fp, "0 %d moveto %d 0 lineto stroke grestore\n",
640 fprintf (fp, "showpage\n");
644 FT_Set_Pixel_Sizes (face, 0, (int) pixel_size);
649 GlyphProc (Widget w, XtPointer client_data, XtPointer call_data)
651 int old_glyph_index = glyph_index;
653 if ((int) client_data == -3 && glyph_index > 0)
655 else if ((int) client_data == -2 && glyph_index > 0)
656 glyph_index = (glyph_index - 1) & 0x1FF000;
657 else if ((int) client_data == -1 && glyph_index > 0)
659 else if ((int) client_data == 1 && glyph_index < 0x10FF80)
661 else if ((int) client_data == 2 && glyph_index < 0x10F000)
662 glyph_index = (glyph_index + 0x1000) & 0x1FF000;
663 else if ((int) client_data == 3 && glyph_index < 0x10F000)
664 glyph_index = 0x10FF80;
665 if (glyph_index != old_glyph_index)
666 update_glyph_area ();
670 CharmapProc (Widget w, XtPointer client_data, XtPointer call_data)
672 if (charmap_index == (int) client_data)
674 charmap_index = (int) client_data;
675 if (charmap_index >= 0)
676 FT_Set_Charmap (face, face->charmaps[charmap_index]);
677 update_glyph_area ();
681 RenderProc (Widget w, XtPointer client_data, XtPointer call_data)
683 if ((int) client_data < 0)
685 if (glyph_rec.n_glyphs > 0)
687 if ((int) client_data == -2)
688 glyph_rec.n_glyphs--;
690 glyph_rec.n_glyphs = 0;
691 update_render_area ();
694 else if (glyph_rec.n_glyphs < 64)
696 int index = glyph_index + (int) client_data;
698 if (charmap_index >= 0)
699 index = FT_Get_Char_Index (face, (FT_ULong) index);
700 if (bitmap[index].pixmap)
702 glyph_rec.codes[glyph_rec.n_glyphs] = glyph_index + (int) client_data;
703 glyph_rec.glyphs[glyph_rec.n_glyphs++] = index;
704 update_render_area ();
710 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
714 reversed = ! reversed;
716 XtSetArg (arg[0], XtNlabel, "L<-R");
718 XtSetArg (arg[0], XtNlabel, "L->R");
719 XtSetValues (w, arg, 1);
724 AltSubstProc (Widget w, XtPointer client_data, XtPointer call_data)
726 do_alternate_subst = ! do_alternate_subst;
731 FeatureProc (Widget w, XtPointer client_data, XtPointer call_data)
733 FeatureRec *rec = (FeatureRec *) client_data;
740 XtSetArg (arg[0], XtNlabel, &label);
741 XtGetValues (w, arg, 1);
742 if (! strcmp (label, "all"))
744 else if (! strcmp (label, "none"))
748 for (idx = 0; idx < rec->langsys->FeatureCount; idx++)
749 if (rec->features[idx].w == w)
751 if (idx == rec->langsys->FeatureCount)
758 for (i = j = 0; j < rec->langsys->FeatureCount; j++)
760 int index = rec->langsys->FeatureIndex[j];
763 = rec->gsub_gpos->FeatureList.Feature[index].FeatureTag;
764 rec->features[j].on = on;
769 OTF_Tag tag = rec->features[idx].tag;
772 if (rec->features[i].on)
775 j < rec->langsys->FeatureCount && rec->features[j].on; j++)
776 rec->features[j - 1].tag = rec->features[j].tag;
777 rec->features[j - 1].tag = tag;
778 rec->features[j - 1].on = 0;
782 for (j = i + 1; i > 0 && ! rec->features[i - 1].on; i--)
783 rec->features[i].tag = rec->features[i - 1].tag;
784 rec->features[i].tag = tag;
785 rec->features[i].on = 1;
793 if (rec->features[i].on)
795 XtSetArg (arg[0], XtNborderWidth, 3);
796 XtSetArg (arg[1], XtNinternalHeight, 2);
797 XtSetArg (arg[2], XtNinternalWidth, 2);
801 XtSetArg (arg[0], XtNborderWidth, 1);
802 XtSetArg (arg[1], XtNinternalHeight, 4);
803 XtSetArg (arg[2], XtNinternalWidth, 4);
805 OTF_tag_name (rec->features[i].tag, str);
806 XtSetArg (arg[3], XtNlabel, str);
807 XtSetValues (rec->features[i].w, arg, 4);
813 setup_feature_rec (FeatureRec *rec)
819 if (! rec->gsub_gpos)
821 for (i = 0; i < rec->gsub_gpos->ScriptList.ScriptCount; i++)
822 if (rec->gsub_gpos->ScriptList.Script[i].ScriptTag == script_tag)
824 OTF_Script *script = rec->gsub_gpos->ScriptList.Script + i;
828 for (j = 0; j < script->LangSysCount; j++)
829 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
831 rec->langsys = script->LangSys + j;
836 rec->langsys = &rec->gsub_gpos->ScriptList.Script[i].DefaultLangSys;
844 XtSetArg (arg[0], XtNborderWidth, 1);
845 XtSetArg (arg[1], XtNinternalHeight, 4);
846 XtSetArg (arg[2], XtNinternalWidth, 4);
847 XtSetArg (arg[3], XtNborderColor, foreground);
848 XtSetArg (arg[4], XtNsensitive, True);
849 for (i = 0; i < rec->langsys->FeatureCount; i++)
851 OTF_Feature *feature = rec->gsub_gpos->FeatureList.Feature;
852 int index = rec->langsys->FeatureIndex[i];
855 if (! rec->features[i].w)
857 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
858 rec->parent, arg, 0);
859 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
860 rec->features[i].w = w;
863 rec->features[i].tag = feature[index].FeatureTag;
864 rec->features[i].on = 0;
865 OTF_tag_name (rec->features[i].tag, label);
866 XtSetArg (arg[5], XtNlabel, label);
867 XtSetValues (rec->features[i].w, arg, 6);
870 XtSetArg (arg[0], XtNborderColor, background);
871 XtSetArg (arg[1], XtNsensitive, False);
872 XtSetArg (arg[2], XtNlabel, " ");
873 for (; i < rec->num_features; i++)
875 if (! rec->features[i].w)
877 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
878 rec->parent, arg, 0);
879 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
880 rec->features[i].w = w;
882 XtSetValues (rec->features[i].w, arg, 3);
887 compose_script_langsys (OTF_Tag script, OTF_Tag langsys, char *name)
889 OTF_tag_name (script, name);
893 OTF_tag_name (langsys, name + 5);
900 decompose_script_langsys (OTF_Tag *script, OTF_Tag *langsys, char *name)
902 *script = OTF_tag (name);
904 *langsys = OTF_tag (name + 5);
910 ScriptProc (Widget w, XtPointer client_data, XtPointer call_data)
913 OTF_Tag script, langsys;
916 XtSetArg (arg[0], XtNlabel, &name);
917 XtGetValues (w, arg, 1);
918 decompose_script_langsys (&script, &langsys, name);
919 if (script_tag == script && langsys_tag == langsys)
922 langsys_tag = langsys;
923 setup_feature_rec (&gsub);
924 setup_feature_rec (&gpos);
929 create_otf_script_widgets (Widget prev)
941 XtSetArg (arg[0], XtNborderWidth, 0);
942 XtSetArg (arg[1], XtNleft, XawChainLeft);
943 XtSetArg (arg[2], XtNright, XawChainLeft);
944 XtSetArg (arg[3], XtNtop, XawChainTop);
945 XtSetArg (arg[4], XtNbottom, XawChainTop);
946 XtSetArg (arg[5], XtNfromVert, prev);
947 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
948 prev = XtCreateManagedWidget ("Script", boxWidgetClass, render_area, arg, 7);
949 XtCreateManagedWidget ("script(langsys)", labelWidgetClass, prev, arg, 1);
953 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
954 n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
956 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
957 n += otf->gpos->ScriptList.Script[i].LangSysCount + 1;
958 script_langsys = alloca ((sizeof script_langsys[0]) * n);
962 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
964 OTF_Tag tag = otf->gsub->ScriptList.Script[i].ScriptTag;
966 script_langsys[n].script = tag;
967 script_langsys[n++].langsys = 0;
969 < otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount)
971 = otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount;
972 for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
974 script_langsys[n].script = tag;
975 script_langsys[n++].langsys
976 = otf->gsub->ScriptList.Script[i].LangSysRecord[j].LangSysTag;
978 < otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount)
980 = otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount;
983 gsub.num_features = nfeatures;
986 gsub.num_features = nfeatures;
987 gsub.features = malloc ((sizeof (FeatureElement)) * nfeatures);
988 memset (gsub.features, 0, (sizeof (FeatureElement)) * nfeatures);
993 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
995 OTF_Tag tag = otf->gpos->ScriptList.Script[i].ScriptTag;
999 < otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount)
1001 = otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount;
1002 for (k = 0; k < prev_n; k++)
1003 if (tag == script_langsys[k].script)
1007 script_langsys[n].script = tag;
1008 script_langsys[n++].langsys = 0;
1010 for (j = 0; j < otf->gpos->ScriptList.Script[i].LangSysCount; j++)
1016 OTF_Script *script = otf->gpos->ScriptList.Script + i;
1018 for (l = k; l < prev_n && tag == script_langsys[l].script; l++)
1019 if (script->LangSysRecord[j].LangSysTag
1020 == script_langsys[l].langsys)
1027 script_langsys[n].script = tag;
1028 script_langsys[n++].langsys = 0;
1031 < otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount)
1033 = otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount;
1039 gpos.num_features = nfeatures;
1040 gpos.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1041 memset (gpos.features, 0, (sizeof (FeatureElement)) * nfeatures);
1047 script_tag = script_langsys[0].script;
1048 langsys_tag = script_langsys[0].langsys;
1049 compose_script_langsys (script_tag, langsys_tag, name);
1053 XtSetArg (arg[0], XtNforeground, background);
1054 XtSetArg (arg[1], XtNbackground, foreground);
1055 XtCreateManagedWidget (name, labelWidgetClass, prev, arg, 2);
1059 XtSetArg (arg[0], XtNstate, True);
1060 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1061 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1062 XtSetArg (arg[0], XtNradioGroup, w);
1063 for (i = 1; i < n; i++)
1065 compose_script_langsys (script_langsys[i].script,
1066 script_langsys[i].langsys, name);
1067 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1068 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1076 create_otf_widgets (Widget prev, FeatureRec *rec)
1081 XtSetArg (arg[0], XtNborderWidth, 0);
1082 XtSetArg (arg[1], XtNleft, XawChainLeft);
1083 XtSetArg (arg[2], XtNright, XawChainLeft);
1084 XtSetArg (arg[3], XtNtop, XawChainTop);
1085 XtSetArg (arg[4], XtNbottom, XawChainTop);
1086 XtSetArg (arg[5], XtNfromVert, prev);
1087 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1088 prev = XtCreateManagedWidget (rec->label, boxWidgetClass, render_area,
1090 XtCreateManagedWidget (rec->label, labelWidgetClass, prev, arg, 1);
1091 XtSetArg (arg[0], XtNborderWidth, 1);
1092 XtSetArg (arg[1], XtNinternalHeight, 4);
1093 XtSetArg (arg[2], XtNinternalWidth, 4);
1094 w = XtCreateManagedWidget ("all", commandWidgetClass, prev, arg, 3);
1095 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1096 w = XtCreateManagedWidget ("none", commandWidgetClass, prev, arg, 3);
1097 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1100 setup_feature_rec (rec);
1107 String quit_action = "<KeyPress>q: set() notify() unset()";
1108 String FIRST_action = "<KeyPress>f: set() notify() unset()\n\
1109 <KeyPress>Home: set() notify() unset()";
1110 String PREV_action = "Shift<KeyPress>p: set() notify() unset()\n\
1111 <KeyPress>Up: set() notify() unset()";
1112 String prev_action = "~Shift<KeyPress>p: set() notify() unset()\n\
1113 <KeyPress>Left: set() notify() unset()";
1114 String next_action = "~Shift<KeyPress>n: set() notify() unset()\n\
1115 <KeyPress>Right: set() notify() unset()";
1116 String NEXT_action = "Shift<KeyPress>n: set() notify() unset()\n\
1117 <KeyPress>Down: set() notify() unset()";
1118 String LAST_action = "<KeyPress>l: set() notify() unset()\n\
1119 <KeyPress>End: set() notify() unset()";
1123 String trans = "<Expose>: Expose()";
1125 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans));
1126 frame = XtCreateManagedWidget ("frame", formWidgetClass, shell, arg, 1);
1128 XtSetArg (arg[0], XtNleft, XawChainLeft);
1129 XtSetArg (arg[1], XtNright, XawChainLeft);
1130 XtSetArg (arg[2], XtNtop, XawChainTop);
1131 XtSetArg (arg[3], XtNbottom, XawChainTop);
1132 XtSetArg (arg[4], XtNborderWidth, 0);
1133 XtSetArg (arg[5], XtNorientation, XtorientHorizontal);
1134 command_area = XtCreateManagedWidget ("command-area", boxWidgetClass,
1136 XtSetArg (arg[6], XtNfromVert, command_area);
1137 navi_area = XtCreateManagedWidget ("navi-area", boxWidgetClass,
1139 XtSetArg (arg[4], XtNborderWidth, 0);
1140 XtSetArg (arg[5], XtNfromVert, navi_area);
1141 XtSetArg (arg[6], XtNdefaultDistance, 0);
1142 glyph_area = XtCreateManagedWidget ("glyph-area", formWidgetClass,
1144 XtSetArg (arg[5], XtNfromVert, glyph_area);
1145 render_area = XtCreateManagedWidget ("render-area", formWidgetClass,
1148 XtSetArg (arg[0], XtNaccelerators, XtParseAcceleratorTable (quit_action));
1149 quit = XtCreateManagedWidget ("Quit", commandWidgetClass,
1150 command_area, arg, 1);
1151 XtAddCallback (quit, XtNcallback, QuitProc, NULL);
1153 dump = XtCreateManagedWidget ("DumpImage", commandWidgetClass,
1154 command_area, arg, 1);
1155 XtAddCallback (dump, XtNcallback, DumpProc, NULL);
1157 XtSetArg (arg[0], XtNborderWidth, 0);
1158 XtSetArg (arg[1], XtNwidth, 10);
1159 XtCreateManagedWidget ("spacer", boxWidgetClass, command_area, arg, 2);
1161 charmap = alloca (sizeof (Widget) * (face->num_charmaps + 1));
1162 XtSetArg (arg[0], XtNstate, True);
1163 charmap[0] = XtCreateManagedWidget (charmap_rec[0].name, toggleWidgetClass,
1164 command_area, arg, 1);
1165 XtAddCallback (charmap[0], XtNcallback, CharmapProc, (XtPointer) -1);
1166 XtSetArg (arg[0], XtNradioGroup, charmap[0]);
1167 for (i = 0; i < face->num_charmaps; i++)
1169 charmap[i + 1] = XtCreateManagedWidget (charmap_rec[i + 1].name,
1171 command_area, arg, 1);
1172 XtAddCallback (charmap[i + 1], XtNcallback, CharmapProc, (XtPointer) i);
1175 XtSetArg (arg[0], XtNlabel, " |< (f)");
1176 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (FIRST_action));
1177 FIRST = XtCreateManagedWidget ("FIRST", commandWidgetClass,
1179 XtAddCallback (FIRST, XtNcallback, GlyphProc, (XtPointer) -3);
1180 XtSetArg (arg[0], XtNlabel, "<< (P)");
1181 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (PREV_action));
1182 PREV = XtCreateManagedWidget ("PREV", commandWidgetClass,
1184 XtAddCallback (PREV, XtNcallback, GlyphProc, (XtPointer) -2);
1185 XtSetArg (arg[0], XtNlabel, "< (p)");
1186 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (prev_action));
1187 prev = XtCreateManagedWidget ("prev", commandWidgetClass,
1189 XtAddCallback (prev, XtNcallback, GlyphProc, (XtPointer) -1);
1190 XtSetArg (arg[0], XtNlabel, " 0000 ");
1191 range = XtCreateManagedWidget ("range", labelWidgetClass,
1193 XtSetArg (arg[0], XtNforeground, &foreground);
1194 XtSetArg (arg[1], XtNbackground, &background);
1195 XtGetValues (range, arg, 2);
1197 XtSetArg (arg[0], XtNlabel, "> (n)");
1198 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (next_action));
1199 next = XtCreateManagedWidget ("next", commandWidgetClass,
1201 XtAddCallback (next, XtNcallback, GlyphProc, (XtPointer) 1);
1202 XtSetArg (arg[0], XtNlabel, ">> (N)");
1203 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (NEXT_action));
1204 NEXT = XtCreateManagedWidget ("NEXT", commandWidgetClass,
1206 XtAddCallback (NEXT, XtNcallback, GlyphProc, (XtPointer) 2);
1207 XtSetArg (arg[0], XtNlabel, ">| (l)");
1208 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (LAST_action));
1209 LAST = XtCreateManagedWidget ("LAST", commandWidgetClass,
1211 XtAddCallback (LAST, XtNcallback, GlyphProc, (XtPointer) 3);
1213 XtSetArg (arg[0], XtNleft, XawChainLeft);
1214 XtSetArg (arg[1], XtNright, XawChainLeft);
1215 XtSetArg (arg[2], XtNtop, XawChainTop);
1216 XtSetArg (arg[3], XtNbottom, XawChainTop);
1218 for (i = 0; i < 8; i++)
1224 sprintf (str, "%XX", i);
1225 XtSetArg (arg[n], XtNheight, glyph_height + 5), n++;
1226 XtSetArg (arg[n], XtNlabel, str), n++;
1227 XtSetArg (arg[n], XtNborderWidth, 0), n++;
1229 XtSetArg (arg[n], XtNfromVert, w), n++;
1230 head = XtCreateManagedWidget (str, labelWidgetClass, glyph_area, arg, n);
1231 index_label[i] = head;
1232 for (j = 0; j < 16; j++)
1238 XtSetArg (arg[n], XtNfromVert, w), n++;
1240 XtSetArg (arg[n], XtNfromHoriz, head), n++;
1242 XtSetArg (arg[n], XtNfromHoriz, glyph[k - 1]), n++;
1243 XtSetArg (arg[n], XtNbitmap, none_pixmap), n++;
1244 glyph[k] = XtCreateManagedWidget ("glyph", commandWidgetClass,
1245 glyph_area, arg, n);
1246 XtAddCallback (glyph[k], XtNcallback, RenderProc, (XtPointer) k);
1250 /* 10 = (1 (border_width) + 4 (inner_width)) * 2 */
1251 XtSetArg(arg[4], XtNwidth, glyph_width + 10);
1252 XtSetArg (arg[5], XtNfromVert, glyph[112]);
1253 XtSetArg (arg[6], XtNfromHoriz, w);
1254 XtSetArg (arg[7], XtNborderWidth, 0);
1256 for (j = 0; j < 16; j++)
1260 sprintf (str, "X%X", j);
1261 XtSetArg (arg[8], XtNlabel, str);
1262 w = XtCreateManagedWidget ("idx", labelWidgetClass, glyph_area, arg, 9);
1263 XtSetArg (arg[6], XtNfromHoriz, w);
1266 XtSetArg (arg[0], XtNleft, XawChainLeft);
1267 XtSetArg (arg[1], XtNright, XawChainLeft);
1268 XtSetArg (arg[2], XtNtop, XawChainTop);
1269 XtSetArg (arg[3], XtNbottom, XawChainTop);
1270 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1271 XtSetArg (arg[5], XtNborderWidth, 0);
1272 w = XtCreateManagedWidget ("clear-box", boxWidgetClass, render_area, arg, 6);
1273 clear = XtCreateManagedWidget ("clear", commandWidgetClass, w, arg, 0);
1274 XtAddCallback (clear, XtNcallback, RenderProc, (XtPointer) -1);
1275 del = XtCreateManagedWidget ("delete", commandWidgetClass, w, arg, 0);
1276 XtAddCallback (del, XtNcallback, RenderProc, (XtPointer) -2);
1277 bidi = XtCreateManagedWidget ("L->R", toggleWidgetClass, w, arg, 0);
1278 XtAddCallback (bidi, XtNcallback, BidiProc, NULL);
1279 alt_subst = XtCreateManagedWidget ("AltSubst", toggleWidgetClass, w, arg, 0);
1280 XtAddCallback (alt_subst, XtNcallback, AltSubstProc, NULL);
1282 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1283 XtSetArg (arg[5], XtNborderWidth, 0);
1284 XtSetArg (arg[6], XtNfromVert, w);
1285 raw = XtCreateManagedWidget ("raw", boxWidgetClass, render_area, arg, 7);
1287 XtSetArg (arg[0], XtNborderWidth, 0);
1288 XtSetArg (arg[1], XtNlabel, "raw: ");
1289 raw_label = XtCreateManagedWidget ("raw-label", labelWidgetClass,
1291 XtSetArg (arg[1], XtNbitmap, raw_pixmap);
1292 raw_image = XtCreateManagedWidget ("raw-image", labelWidgetClass,
1297 OTF_get_table (otf, "GSUB");
1298 OTF_get_table (otf, "GPOS");
1299 w = create_otf_script_widgets (w);
1302 gsub.label = "GSUB";
1303 gsub.gsub_gpos = otf->gsub;
1304 w = create_otf_widgets (w, &gsub);
1308 gpos.label = "GPOS";
1309 gpos.gsub_gpos = otf->gpos;
1310 w = create_otf_widgets (w, &gpos);
1314 XtSetArg (arg[6], XtNfromVert, w);
1315 seq = XtCreateManagedWidget ("seq", boxWidgetClass, render_area, arg, 7);
1316 XtSetArg (arg[0], XtNborderWidth, 0);
1317 XtSetArg (arg[1], XtNlabel, "seq: ");
1318 seq_label = XtCreateManagedWidget ("seq-label", labelWidgetClass,
1320 XtSetArg (arg[1], XtNbitmap, seq_pixmap);
1321 seq_image = XtCreateManagedWidget ("seq-image", labelWidgetClass,
1323 XtInstallAllAccelerators (shell, shell);
1327 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1329 XTextProperty text_prop;
1330 char *pname = "otfview";
1331 char *fname = basename (filename);
1332 char *name = alloca (strlen (fname) + 3 + strlen (pname) + 1);
1334 sprintf (name, "%s - %s", pname, fname);
1335 text_prop.value = (unsigned char *) name;
1336 text_prop.encoding = XA_STRING;
1337 text_prop.format = 8;
1338 text_prop.nitems = strlen (name);
1339 XSetWMName (display, XtWindow (shell), &text_prop);
1342 /* Format MSG by FMT and print the result to the stderr, and exit. */
1344 #define FATAL_ERROR(fmt, arg) \
1346 fprintf (stderr, fmt, arg); \
1351 x_error_handler (Display *display, XErrorEvent *error)
1357 help (char **argv, int err)
1359 FILE *fp = err ? stderr : stdout;
1361 fprintf (fp, "Usage: %s [ X-OPTION ... ] OTF-FILE [INDEX]\n",
1362 basename (argv[0]));
1363 fprintf (fp, " Environment variable PIXEL_SIZE specifies the pixel size.\n");
1364 fprintf (fp, " The default pixel size is %d, but is reduced\n",
1365 DEFAULT_PIXEL_SIZE);
1366 fprintf (fp, " if your screen is not that wide.\n");
1371 main (int argc, char **argv)
1373 XtActionsRec actions[] = { {"Expose", ExposeProc} };
1377 OTF_GlyphString gstring;
1382 int fixed_pixel_size = 0;
1385 pixel_size = DEFAULT_PIXEL_SIZE;
1387 char *str = getenv ("PIXEL_SIZE");
1389 if (str && (i = atoi (str)) > 0)
1392 fixed_pixel_size = 1;
1396 gstring.size = gstring.used = 256;
1397 g = calloc (256, sizeof (OTF_Glyph));
1400 shell = XtOpenApplication (&context, "OTFView", NULL, 0, &argc, argv, NULL,
1401 shellWidgetClass, arg, 0);
1402 display = XtDisplay (shell);
1403 /*XSynchronize (display, True);*/
1404 XSetErrorHandler (x_error_handler);
1405 display_width = DisplayWidth (display,
1406 XScreenNumberOfScreen (XtScreen (shell)));
1407 font = XLoadQueryFont (display, DEFAULT_FONT_NAME);
1409 font = XLoadQueryFont (display, "fixed");
1413 if (!strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
1418 fontindex = atoi (argv[2]);
1420 FATAL_ERROR ("Invalid font index: %d\n", fontindex);
1423 if ((err = FT_Init_FreeType (&library)))
1424 FATAL_ERROR ("%s\n", "FT_Init_FreeType: error");
1425 err = FT_New_Face (library, filename, fontindex, &face);
1426 if (err == FT_Err_Unknown_File_Format)
1427 FATAL_ERROR ("%s\n", "FT_New_Face: unknown file format");
1429 FATAL_ERROR ("%s\n", "FT_New_Face: unknown error (invalid face index?)");
1430 if ((err = FT_Set_Pixel_Sizes (face, 0, pixel_size)))
1431 FATAL_ERROR ("%s\n", "FT_Set_Pixel_Sizes: error");
1433 if (strstr (filename, ".ttf")
1434 || strstr (filename, ".TTF")
1435 || strstr (filename, ".otf")
1436 || strstr (filename, ".OTF"))
1438 otf = OTF_open_ft_face (face);
1440 || OTF_get_table (otf, "head") < 0
1441 || OTF_get_table (otf, "cmap") < 0
1442 || (OTF_check_table (otf, "GSUB") < 0
1443 && OTF_check_table (otf, "GPOS") < 0))
1451 filename = basename (filename);
1452 sprintf (title, "%s family:%s style:%s",
1453 filename, face->family_name, face->style_name);
1454 XtSetArg (arg[0], XtNtitle, title);
1455 XtSetValues (shell, arg, 1);
1458 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1459 * pixel_size / face->units_per_EM);
1460 if (! fixed_pixel_size && glyph_width * 16 > display_width * 0.8)
1462 pixel_size = (pixel_size * display_width * 0.8 / 16 / glyph_width);
1463 FT_Set_Pixel_Sizes (face, 0, pixel_size);
1464 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1465 * pixel_size / face->units_per_EM);
1467 if (glyph_width < FONT_WIDTH * 4)
1468 glyph_width = FONT_WIDTH * 4;
1470 glyph_height = ((face->bbox.yMax - face->bbox.yMin)
1471 * pixel_size / face->units_per_EM);
1473 glyph_x = - (face->bbox.xMin * pixel_size / face->units_per_EM);
1474 glyph_y = face->bbox.yMax * pixel_size / face->units_per_EM;
1475 none_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1476 glyph_width, glyph_height, 1);
1479 unsigned long valuemask = GCFunction | GCLineWidth;
1482 gc = XCreateGC (display, none_pixmap, (unsigned long) 0, NULL);
1483 values.function = GXset;
1484 values.line_width = 1;
1485 gc_set = XCreateGC (display, none_pixmap, valuemask, &values);
1486 values.function = GXor;
1487 gc_or = XCreateGC (display, none_pixmap, valuemask, &values);
1488 values.function = GXcopyInverted;
1489 gc_inv = XCreateGC (display, none_pixmap, valuemask, &values);
1492 XFillRectangle (display, none_pixmap, gc, 0, 0,
1493 glyph_width, glyph_height);
1494 XDrawString (display, none_pixmap, gc_inv,
1495 (glyph_width - XTextWidth (font, "none", 4)) / 2,
1496 glyph_height / 2, "none", 4);
1498 render_width = (glyph_width + 4) * 15 + 1;
1499 render_height = glyph_height + 2;
1501 charmap_rec[0].platform_id = -1;
1502 charmap_rec[0].encoding_id = -1;
1503 strcpy (charmap_rec[0].name, "no charmap");
1505 for (i = 0; i < face->num_charmaps; i++)
1507 charmap_rec[i + 1].platform_id = face->charmaps[i]->platform_id;
1508 charmap_rec[i + 1].encoding_id = face->charmaps[i]->encoding_id;
1509 sprintf (charmap_rec[i + 1].name, "%d-%d",
1510 charmap_rec[i + 1].platform_id, charmap_rec[i + 1].encoding_id);
1511 if (face->charmaps[i]->platform_id == 0
1512 || (face->charmaps[i]->platform_id == 3
1513 && face->charmaps[i]->encoding_id == 1))
1514 strcat (charmap_rec[i + 1].name, " (unicode)");
1515 else if (face->charmaps[i]->platform_id == 1
1516 && face->charmaps[i]->encoding_id == 0)
1517 strcat (charmap_rec[i + 1].name, " (apple-roman)");
1520 raw_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1521 render_width, render_height, 1);
1522 seq_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1523 render_width, render_height, 1);
1525 memset (bitmap, 0, sizeof (bitmap));
1529 update_glyph_area ();
1530 update_render_area ();
1532 XtAppAddActions (context, actions, XtNumber (actions));
1533 XtRealizeWidget (shell);
1534 XtAppMainLoop (context);
1539 #else /* not HAVE_X11_XAW_COMMAND_H */
1542 main (int argc, char **argv)
1545 "Building of this program failed (lack of some header files)\n");