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 | +---- uvs_area (box) (optional) -------+ |
77 | +--------------------------------------+ |
78 | +--- render_area (form) ---------------+ |
79 | | clear del bidi alt_subst | |
80 | | +--- raw (box) --------------------+ | |
81 | | | raw_label raw_image | | |
82 | | +----------------------------------+ | |
83 | | GSUB all none features... | |
84 | | GPOS all none features... | |
85 | | +--- seq (box) --------------------+ | |
86 | | | seq_label seq_image | | |
87 | | +----------------------------------+ | |
88 | +--------------------------------------+ |
89 +------------------------------------------+ */
91 Widget command_area, quit, dump, *charmap;
92 Widget navi_area, FIRST, PREV, prev, range, next, NEXT, LAST;
93 Widget glyph_area, glyph[128], index_label[8];
94 Widget uvs_area, uvs_label;
95 Widget render_area, clear, del, bidi, alt_subst, raw, seq;
96 Widget raw_label, raw_image, seq_label, seq_image;
97 unsigned long foreground, background;
109 OTF_GSUB_GPOS *gsub_gpos;
110 OTF_LangSys *langsys;
112 FeatureElement *features;
116 FeatureRec gsub, gpos;
118 /* Currently selected script and langsys. */
119 OTF_Tag script_tag, langsys_tag;
124 GC gc, gc_set, gc_or, gc_inv;
128 unsigned width, height;
133 BitmapRec bitmap[0x110000];
135 int render_width, render_height;
136 Pixmap raw_pixmap, seq_pixmap, gsub_pixmap, gpos_pixmap;
150 int do_alternate_subst;
151 unsigned glyph_width, glyph_height;
152 int glyph_x, glyph_y;
161 OTF_EncodingSubtable14 *sub14 = NULL;
173 create_pixmap (int index)
175 int err = FT_Load_Glyph (face, index, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
181 bitmap[index].pixmap = none_pixmap;
184 ximage.height = face->glyph->bitmap.rows;
185 ximage.width = face->glyph->bitmap.width;
187 ximage.bits_per_pixel = 1;
189 ximage.format = XYPixmap;
190 ximage.data = (char *) face->glyph->bitmap.buffer;
191 ximage.byte_order = MSBFirst;
192 ximage.bitmap_unit = 8;
193 ximage.bitmap_bit_order = MSBFirst;
194 ximage.bitmap_pad = 8;
195 ximage.bytes_per_line = face->glyph->bitmap.pitch;
196 XInitImage (&ximage);
197 pixmap = XCreatePixmap (display, DefaultRootWindow (display),
198 glyph_width, glyph_height, 1);
199 XFillRectangle (display, pixmap, gc, 0, 0, glyph_width, glyph_height);
200 XPutImage (display, pixmap, gc, &ximage, 0, 0,
201 glyph_x + face->glyph->bitmap_left,
202 glyph_y - face->glyph->bitmap_top,
203 ximage.width, ximage.height);
204 bitmap[index].pixmap = pixmap;
205 bitmap[index].width = ximage.width;
206 bitmap[index].height = ximage.height;
207 bitmap[index].x = face->glyph->bitmap_left;
208 bitmap[index].y = - face->glyph->bitmap_top;
209 bitmap[index].advance = face->glyph->metrics.horiAdvance >> 6;
220 for (i = 0; i < 128; i++)
222 int index = glyph_index + i;
224 if (charmap_index >= 0)
225 index = FT_Get_Char_Index (face, (FT_ULong) index);
226 if (charmap_index >= 0 && ! index)
227 XtSetArg (arg[0], XtNbitmap, none_pixmap);
230 if (! bitmap[index].pixmap)
231 create_pixmap (index);
232 XtSetArg (arg[0], XtNbitmap, bitmap[index].pixmap);
234 XtSetValues (glyph[i], arg, 1);
237 msb = (glyph_index >> 7) % 2 ? 8 : 0;
238 for (i = 0; i < 8; i++)
242 sprintf (str, "%XX", i | msb );
243 XtSetArg (arg[0], XtNheight, glyph_height + 5);
244 XtSetArg (arg[1], XtNlabel, str);
245 XtSetValues (index_label[i], arg, 2);
248 if (glyph_index < 0x10000)
249 sprintf (buf, " %04X-%04X ", glyph_index, glyph_index + 0x7F);
251 sprintf (buf, "%06X-%06X", glyph_index, glyph_index + 0x7F);
252 XtSetArg (arg[0], XtNlabel, buf);
253 XtSetValues (range, arg, 1);
257 update_uvs_area (int c)
259 OTF_GlyphID code[256];
263 OTF_get_variation_glyphs (otf, c, code);
265 for (i = 0; i < 256; i++)
269 XtSetArg (arg[0], XtNsensitive, True);
271 XtSetArg (arg[0], XtNsensitive, False);
272 XtSetValues (uvs[i].w, arg, 1);
278 get_features (OTF_FeatureList *list, FeatureRec *rec)
283 if (! rec->langsys || ! rec->features || ! rec->features[0].on)
285 for (i = n = 0; i < rec->langsys->FeatureCount; i++)
287 if (rec->features[i].on)
292 str = malloc (n * 5);
293 for (i = 0, p = str; i < n; i++, p += 5)
295 OTF_tag_name (rec->features[i].tag, p);
303 #define DEVICE_DELTA(table, size) \
304 (((table).DeltaValue \
305 && ((size) >= (table).StartSize && (size) <= (table).EndSize)) \
306 ? (table).DeltaValue[(size) >= (table).StartSize] \
310 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
311 OTF_Glyph *g, int *x, int *y)
313 if (anchor->AnchorFormat == 2)
316 int ap = anchor->f.f1.AnchorPoint;
318 FT_Load_Glyph (ft_face, (FT_UInt) g->glyph_id, FT_LOAD_MONOCHROME);
319 outline = &ft_face->glyph->outline;
320 if (ap < outline->n_points)
322 *x = outline->points[ap].x;
323 *y = outline->points[ap].y;
326 else if (anchor->AnchorFormat == 3)
328 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, pixel_size);
329 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, pixel_size);
337 OTF_GlyphString gstring;
338 OTF_Glyph *g, *prev, *base, *mark;
340 int len = glyph_rec.n_glyphs;
342 int unitsPerEm = face->units_per_EM;
344 gstring.size = gstring.used = len;
345 gstring.glyphs = malloc (sizeof (OTF_Glyph) * len);
346 memset (gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
347 for (i = 0; i < len; i++)
349 gstring.glyphs[i].c = glyph_rec.codes[i];
350 if (charmap_index < 0)
351 gstring.glyphs[i].glyph_id = glyph_rec.glyphs[i];
354 XFillRectangle (display, seq_pixmap, gc, 0, 0, render_width, render_height);
355 XDrawLine (display, seq_pixmap, gc_set, 0, glyph_y, render_width, glyph_y);
360 OTF_drive_gdef (otf, &gstring);
361 OTF_drive_cmap (otf, &gstring);
364 str = get_features (&otf->gsub->FeatureList, &gsub);
367 if (do_alternate_subst)
368 OTF_drive_gsub_alternate (otf, &gstring, NULL, NULL, str);
370 OTF_drive_gsub (otf, &gstring, NULL, NULL, str);
376 str = get_features (&otf->gpos->FeatureList, &gpos);
379 OTF_drive_gpos2 (otf, &gstring, NULL, NULL, str);
390 for (prev = gstring.glyphs, g = gstring.glyphs + gstring.used - 1;
391 prev < g; prev++, g--)
392 temp = *prev, *prev = *g, *g = temp;
393 for (g = gstring.glyphs; g < gstring.glyphs + gstring.used; g++)
394 if (g->GlyphClass == 3)
398 while (g < gstring.glyphs + gstring.used && g->GlyphClass == 3)
400 for (g0 = g; prev < g0; prev++, g0--)
401 temp = *prev, *prev = *g, *g = temp;
407 for (i = 0, x = glyph_x, prev = NULL, g = gstring.glyphs;
408 i < gstring.used; i++, prev = g++)
410 BitmapRec *bmp = bitmap + gstring.glyphs[i].glyph_id;
411 int xoff = 0, yoff = 0;
413 int advance = bmp->advance;
415 if (gstring.glyphs[i].glyph_id && ! bmp->pixmap)
417 create_pixmap (gstring.glyphs[i].glyph_id);
420 advance = bmp->advance;
422 if (g->positioning_type)
426 switch (g->positioning_type)
430 int format = g->f.f1.format;
432 if (format & OTF_XPlacement)
433 xoff = g->f.f1.value->XPlacement * pixel_size / unitsPerEm;
434 if (format & OTF_XPlaDevice)
435 xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, pixel_size);
436 if (format & OTF_YPlacement)
437 yoff = g->f.f1.value->YPlacement * pixel_size / unitsPerEm;
438 if (format & OTF_YPlaDevice)
439 yoff += DEVICE_DELTA (g->f.f1.value->YPlaDevice, pixel_size);
440 if (format & OTF_XAdvance)
441 advance += g->f.f1.value->XAdvance * pixel_size / unitsPerEm;
442 if (format & OTF_XAdvDevice)
443 advance += DEVICE_DELTA (g->f.f1.value->XAdvDevice,
449 /* Not yet supported. */
455 prev_width = base_width;
456 goto label_adjust_anchor;
457 default: /* i.e. case 6 */
464 int base_x, base_y, mark_x, mark_y;
466 base_x = g->f.f4.base_anchor->XCoordinate * pixel_size / unitsPerEm;
467 base_y = g->f.f4.base_anchor->YCoordinate * pixel_size / unitsPerEm;
468 mark_x = g->f.f4.mark_anchor->XCoordinate * pixel_size / unitsPerEm;
469 mark_y = g->f.f4.mark_anchor->YCoordinate * pixel_size / unitsPerEm;
471 if (g->f.f4.base_anchor->AnchorFormat != 1)
472 adjust_anchor (g->f.f4.base_anchor, face, prev, &base_x, &base_y);
473 if (g->f.f4.mark_anchor->AnchorFormat != 1)
474 adjust_anchor (g->f.f4.mark_anchor, face, g, &mark_x, &mark_y);
475 xoff = (base_x - prev_width) - mark_x;
476 yoff = base_y - mark_y;
479 if (i + 1 == gstring.used
480 || gstring.glyphs[i + 1].glyph_id
481 || ! gstring.glyphs[i + 1].positioning_type)
487 XCopyArea (display, bmp->pixmap, seq_pixmap, gc_or,
488 glyph_x + bmp->x, glyph_y + bmp->y, bmp->width, bmp->height,
489 x + bmp->x + xoff, glyph_y + bmp->y - yoff);
492 if (g->GlyphClass == OTF_GlyphClass0)
493 base = mark = g, base_width = advance;
494 else if (g->GlyphClass == OTF_GlyphClassMark)
497 base = g, base_width = advance;
499 free (gstring.glyphs);
501 XtSetArg (arg[0], XtNbitmap, seq_pixmap);
502 XtSetValues (seq_image, arg, 1);
507 update_render_area ()
513 XFillRectangle (display, raw_pixmap, gc, 0, 0, render_width, render_height);
514 for (i = 0, x = glyph_x; i < glyph_rec.n_glyphs; i++)
516 if (glyph_rec.glyphs[i] >= 0)
518 BitmapRec *bmp = bitmap + glyph_rec.glyphs[i];
521 XCopyArea (display, bmp->pixmap, raw_pixmap, gc,
522 0, 0, glyph_width, glyph_height,
523 (glyph_width + 4) * i + 1, 1);
524 XDrawRectangle (display, raw_pixmap, gc_set,
525 (glyph_width + 4) * i, 0,
526 glyph_width + 1, glyph_height + 1);
527 XDrawLine (display, raw_pixmap, gc_set,
528 (glyph_width + 4) * i + 1 + glyph_x, 1,
529 (glyph_width + 4) * i + 1 + glyph_x, glyph_height + 1);
530 XDrawLine (display, raw_pixmap, gc_set,
531 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance, 1,
532 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance,
535 sprintf (buf, "%04X", glyph_rec.codes[i]);
536 XDrawString (display, raw_pixmap, gc_inv,
537 (glyph_width + 4) * i + 1
538 + (glyph_width - XTextWidth (font, buf, 4)) / 2,
539 glyph_height + 2 + FONT_HEIGHT, buf, 4);
543 /* Variation Selector */
544 int idx = - glyph_rec.glyphs[i];
547 sprintf (buf, "%03d", idx);
548 XDrawRectangle (display, raw_pixmap, gc_set,
549 (glyph_width + 4) * i, 0,
550 glyph_width + 1, glyph_height + 1);
551 XDrawString (display, raw_pixmap, gc_set,
552 (glyph_width + 4) * i + 1
553 + (glyph_width - XTextWidth (font, "VS", 2)) / 2,
554 1 + glyph_height / 2, "VS", 2);
555 XDrawString (display, raw_pixmap, gc_set,
556 (glyph_width + 4) * i + 1
557 + (glyph_width - XTextWidth (font, buf, 3)) / 2,
558 1 + glyph_height / 2 + FONT_ASCENT, buf, 3);
561 XtSetArg (arg[0], XtNbitmap, raw_pixmap);
562 XtSetValues (raw_image, arg, 1);
567 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
569 XtAppSetExitFlag (XtWidgetToApplicationContext (w));
573 DumpProc (Widget w, XtPointer client_data, XtPointer call_data)
575 int g_width, g_height;
577 /* unit in points (1/72 inch); to fit in both US-letter and A4 */
578 static int xoff = 30, yoff = 30;
579 static int unit = 30;
580 static int margin = 2;
581 static int title_height = 20, label_height = 10;
582 int total_width = (unit + margin * 2) * 16;
583 int total_height = (unit + margin * 2 + label_height) * 16 + title_height;
584 /* pixel size (dots) */
587 char *name = alloca (strlen (filename) + 10);
589 int index = (glyph_index / 0x100) * 0x100;
592 g_width = face->bbox.xMax - face->bbox.xMin;
593 g_height = face->bbox.yMax - face->bbox.yMin;
594 if (g_width > g_height)
596 scale = g_width * size;
597 g_x = face->bbox.xMin * unit / g_width;
598 g_y = face->bbox.yMin * unit / g_width;
602 scale = g_height * size;
603 g_x = face->bbox.xMin * unit / g_height;
604 g_y = face->bbox.yMin * unit / g_height;
606 scale /= face->units_per_EM;
608 FT_Set_Pixel_Sizes (face, 0, size);
610 sprintf (name, "%s-%04X.ps", face->family_name, index);
611 printf ("Writing %s ... ", name);
613 fp = fopen (name, "w");
615 fprintf (fp, "%s\n", "%!PS-Adobe-2.0 EPSF-2.0");
616 fprintf (fp, "%s\n", "%%Creater: otfview");
617 fprintf (fp, "%s %s(%s)-%04X\n", "%%Title:",
618 face->family_name, face->style_name, index);
619 fprintf (fp, "%s\n", "%%Pages: 1");
620 fprintf (fp, "%s %d %d %d %d\n", "%%BoundingBox:",
621 xoff, yoff, xoff + total_width, yoff + total_height);
622 fprintf (fp, "%s\n", "%%EndComments");
623 fprintf (fp, "%s\n", "%%BeginProlog");
624 fprintf (fp, "/W %d def\n", unit + margin * 2);
625 fprintf (fp, "/H %d def\n", unit + margin * 2 + label_height);
626 fprintf (fp, "/STR 10 string def\n");
627 fprintf (fp, "/DrawIndex {\n");
628 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");
629 fprintf (fp, "} def\n");
630 fprintf (fp, "/DrawTitle {\n");
631 fprintf (fp, " /Courier findfont 20 scalefont setfont\n");
632 fprintf (fp, " %d %d 4 add moveto\n", xoff + total_width / 2,
633 yoff + total_height - title_height + 2);
634 fprintf (fp, " (%s(%s)-%04X) dup stringwidth pop 2 div neg 0 rmoveto show\n",
635 face->family_name, face->style_name, index);
636 fprintf (fp, "} def\n");
637 fprintf (fp, "/DrawFrame { gsave %d %d translate 0 setlinewidth\n",
639 fprintf (fp, " /Courier findfont 10 scalefont setfont\n");
640 fprintf (fp, " /I %d def\n", index);
641 fprintf (fp, " 0 1 16 { W mul 0 moveto 0 H 16 mul rlineto stroke } for\n");
642 fprintf (fp, " 0 1 16 { H mul 0 exch moveto W 16 mul 0 rlineto stroke } for\n");
643 fprintf (fp, " 0 1 15 { H mul %d add 0 exch moveto W 16 mul 0 rlineto stroke } for\n", label_height);
644 fprintf (fp, " 15 -1 0 { gsave H mul 0 exch translate 0 0 moveto\n");
645 fprintf (fp, " 0 1 15 { gsave W mul 0 moveto\n");
646 fprintf (fp, " 4 2 rmoveto DrawIndex /I I 1 add def grestore} for\n");
647 fprintf (fp, " grestore } for grestore } def\n");
648 fprintf (fp, "%s\n", "%%EndProlog");
649 fprintf (fp, "DrawTitle DrawFrame\n");
651 for (i = 0; i < 16; i++)
652 for (j = 0; j < 16; j++, index++)
656 if (charmap_index >= 0)
657 idx = FT_Get_Char_Index (face, (FT_ULong) index);
661 && FT_Load_Glyph (face, idx, FT_LOAD_RENDER | FT_LOAD_MONOCHROME) == 0
662 && face->glyph->bitmap.rows > 0
663 && face->glyph->bitmap.width > 0)
665 unsigned char *p = face->glyph->bitmap.buffer;
666 int width = (face->glyph->bitmap.width - 1) / 8 + 1;
668 fprintf (fp, "gsave %f %f translate %d %d scale 0 0 moveto\n",
669 xoff + (unit + margin * 2) * j + margin - g_x,
670 yoff + (unit + label_height + margin * 2) * (15 - i) + label_height + margin - g_y,
672 fprintf (fp, "%d %d true [%f 0 0 %f %d %d]\n",
673 width * 8, face->glyph->bitmap.rows,
674 scale, -scale, -face->glyph->bitmap_left,
675 face->glyph->bitmap_top);
677 for (k = 0; k < face->glyph->bitmap.rows;
678 k++, p += face->glyph->bitmap.pitch)
680 for (l = 0; l < width; l++)
681 fprintf (fp, "%02X", p[l]);
684 fprintf (fp, ">} imagemask grestore\n");
688 int boxsize = unit + margin * 2;
690 fprintf (fp, "gsave 0 setlinewidth %d %d translate\n",
692 yoff + (boxsize + label_height) * (15 - i) + label_height);
693 fprintf (fp, "0 0 moveto %d %d lineto stroke\n",
695 fprintf (fp, "0 %d moveto %d 0 lineto stroke grestore\n",
699 fprintf (fp, "showpage\n");
703 FT_Set_Pixel_Sizes (face, 0, (int) pixel_size);
708 GlyphProc (Widget w, XtPointer client_data, XtPointer call_data)
710 int old_glyph_index = glyph_index;
712 if ((int) client_data == -3 && glyph_index > 0)
714 else if ((int) client_data == -2 && glyph_index > 0)
715 glyph_index = (glyph_index - 1) & 0x1FF000;
716 else if ((int) client_data == -1 && glyph_index > 0)
718 else if ((int) client_data == 1 && glyph_index < 0x10FF80)
720 else if ((int) client_data == 2 && glyph_index < 0x10F000)
721 glyph_index = (glyph_index + 0x1000) & 0x1FF000;
722 else if ((int) client_data == 3 && glyph_index < 0x10F000)
723 glyph_index = 0x10FF80;
724 if (glyph_index != old_glyph_index)
725 update_glyph_area ();
729 CharmapProc (Widget w, XtPointer client_data, XtPointer call_data)
731 if (charmap_index == (int) client_data)
733 charmap_index = (int) client_data;
734 if (charmap_index >= 0)
735 FT_Set_Charmap (face, face->charmaps[charmap_index]);
736 update_glyph_area ();
740 UVSProc (Widget w, XtPointer client_data, XtPointer call_data)
742 unsigned idx = (unsigned) client_data;
743 int selector = uvs[idx].c;
744 OTF_VariationSelectorRecord *record;
747 if (glyph_rec.n_glyphs >= 64)
749 for (i = 0; i < sub14->nRecords; i++)
751 record = sub14->Records + i;
752 if (record->varSelector == selector)
755 if (i < sub14->nRecords)
757 if (glyph_rec.n_glyphs > 0
758 && glyph_rec.glyphs[glyph_rec.n_glyphs - 1] < 0)
759 glyph_rec.n_glyphs--;
760 glyph_rec.codes[glyph_rec.n_glyphs] = selector;
761 glyph_rec.glyphs[glyph_rec.n_glyphs++] = - idx - 1;
762 update_render_area ();
767 RenderProc (Widget w, XtPointer client_data, XtPointer call_data)
769 if ((int) client_data < 0)
771 if (glyph_rec.n_glyphs > 0)
773 if ((int) client_data == -2)
774 glyph_rec.n_glyphs--;
776 glyph_rec.n_glyphs = 0;
777 update_render_area ();
780 else if (glyph_rec.n_glyphs < 64)
782 int index = glyph_index + (int) client_data;
784 if (charmap_index >= 0)
785 index = FT_Get_Char_Index (face, (FT_ULong) index);
786 if (bitmap[index].pixmap)
788 glyph_rec.codes[glyph_rec.n_glyphs] = glyph_index + (int) client_data;
789 glyph_rec.glyphs[glyph_rec.n_glyphs++] = index;
791 update_uvs_area (glyph_index + (int) client_data);
792 update_render_area ();
798 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
802 reversed = ! reversed;
804 XtSetArg (arg[0], XtNlabel, "L<-R");
806 XtSetArg (arg[0], XtNlabel, "L->R");
807 XtSetValues (w, arg, 1);
812 AltSubstProc (Widget w, XtPointer client_data, XtPointer call_data)
814 do_alternate_subst = ! do_alternate_subst;
819 FeatureProc (Widget w, XtPointer client_data, XtPointer call_data)
821 FeatureRec *rec = (FeatureRec *) client_data;
828 XtSetArg (arg[0], XtNlabel, &label);
829 XtGetValues (w, arg, 1);
830 if (! strcmp (label, "all"))
832 else if (! strcmp (label, "none"))
836 for (idx = 0; idx < rec->langsys->FeatureCount; idx++)
837 if (rec->features[idx].w == w)
839 if (idx == rec->langsys->FeatureCount)
846 for (i = j = 0; j < rec->langsys->FeatureCount; j++)
848 int index = rec->langsys->FeatureIndex[j];
851 = rec->gsub_gpos->FeatureList.Feature[index].FeatureTag;
852 rec->features[j].on = on;
857 OTF_Tag tag = rec->features[idx].tag;
860 if (rec->features[i].on)
863 j < rec->langsys->FeatureCount && rec->features[j].on; j++)
864 rec->features[j - 1].tag = rec->features[j].tag;
865 rec->features[j - 1].tag = tag;
866 rec->features[j - 1].on = 0;
870 for (j = i + 1; i > 0 && ! rec->features[i - 1].on; i--)
871 rec->features[i].tag = rec->features[i - 1].tag;
872 rec->features[i].tag = tag;
873 rec->features[i].on = 1;
881 if (rec->features[i].on)
883 XtSetArg (arg[0], XtNborderWidth, 3);
884 XtSetArg (arg[1], XtNinternalHeight, 2);
885 XtSetArg (arg[2], XtNinternalWidth, 2);
889 XtSetArg (arg[0], XtNborderWidth, 1);
890 XtSetArg (arg[1], XtNinternalHeight, 4);
891 XtSetArg (arg[2], XtNinternalWidth, 4);
893 OTF_tag_name (rec->features[i].tag, str);
894 XtSetArg (arg[3], XtNlabel, str);
895 XtSetValues (rec->features[i].w, arg, 4);
901 setup_feature_rec (FeatureRec *rec)
907 if (! rec->gsub_gpos)
909 for (i = 0; i < rec->gsub_gpos->ScriptList.ScriptCount; i++)
910 if (rec->gsub_gpos->ScriptList.Script[i].ScriptTag == script_tag)
912 OTF_Script *script = rec->gsub_gpos->ScriptList.Script + i;
916 for (j = 0; j < script->LangSysCount; j++)
917 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
919 rec->langsys = script->LangSys + j;
924 rec->langsys = &rec->gsub_gpos->ScriptList.Script[i].DefaultLangSys;
932 XtSetArg (arg[0], XtNborderWidth, 1);
933 XtSetArg (arg[1], XtNinternalHeight, 4);
934 XtSetArg (arg[2], XtNinternalWidth, 4);
935 XtSetArg (arg[3], XtNborderColor, foreground);
936 XtSetArg (arg[4], XtNsensitive, True);
937 for (i = 0; i < rec->langsys->FeatureCount; i++)
939 OTF_Feature *feature = rec->gsub_gpos->FeatureList.Feature;
940 int index = rec->langsys->FeatureIndex[i];
943 if (! rec->features[i].w)
945 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
946 rec->parent, arg, 0);
947 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
948 rec->features[i].w = w;
951 rec->features[i].tag = feature[index].FeatureTag;
952 rec->features[i].on = 0;
953 OTF_tag_name (rec->features[i].tag, label);
954 XtSetArg (arg[5], XtNlabel, label);
955 XtSetValues (rec->features[i].w, arg, 6);
958 XtSetArg (arg[0], XtNborderColor, background);
959 XtSetArg (arg[1], XtNsensitive, False);
960 XtSetArg (arg[2], XtNlabel, " ");
961 for (; i < rec->num_features; i++)
963 if (! rec->features[i].w)
965 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
966 rec->parent, arg, 0);
967 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
968 rec->features[i].w = w;
970 XtSetValues (rec->features[i].w, arg, 3);
975 compose_script_langsys (OTF_Tag script, OTF_Tag langsys, char *name)
977 OTF_tag_name (script, name);
981 OTF_tag_name (langsys, name + 5);
988 decompose_script_langsys (OTF_Tag *script, OTF_Tag *langsys, char *name)
990 *script = OTF_tag (name);
992 *langsys = OTF_tag (name + 5);
998 ScriptProc (Widget w, XtPointer client_data, XtPointer call_data)
1001 OTF_Tag script, langsys;
1004 XtSetArg (arg[0], XtNlabel, &name);
1005 XtGetValues (w, arg, 1);
1006 decompose_script_langsys (&script, &langsys, name);
1007 if (script_tag == script && langsys_tag == langsys)
1009 script_tag = script;
1010 langsys_tag = langsys;
1011 setup_feature_rec (&gsub);
1012 setup_feature_rec (&gpos);
1017 create_otf_script_widgets (Widget prev)
1021 int n, prev_n, i, j;
1029 XtSetArg (arg[0], XtNborderWidth, 0);
1030 XtSetArg (arg[1], XtNleft, XawChainLeft);
1031 XtSetArg (arg[2], XtNright, XawChainLeft);
1032 XtSetArg (arg[3], XtNtop, XawChainTop);
1033 XtSetArg (arg[4], XtNbottom, XawChainTop);
1034 XtSetArg (arg[5], XtNfromVert, prev);
1035 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1036 prev = XtCreateManagedWidget ("Script", boxWidgetClass, render_area, arg, 7);
1037 XtCreateManagedWidget ("script(langsys)", labelWidgetClass, prev, arg, 1);
1041 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
1042 n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
1044 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
1045 n += otf->gpos->ScriptList.Script[i].LangSysCount + 1;
1046 script_langsys = alloca ((sizeof script_langsys[0]) * n);
1050 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
1052 OTF_Tag tag = otf->gsub->ScriptList.Script[i].ScriptTag;
1054 script_langsys[n].script = tag;
1055 script_langsys[n++].langsys = 0;
1057 < otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount)
1059 = otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount;
1060 for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
1062 script_langsys[n].script = tag;
1063 script_langsys[n++].langsys
1064 = otf->gsub->ScriptList.Script[i].LangSysRecord[j].LangSysTag;
1066 < otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount)
1068 = otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount;
1071 gsub.num_features = nfeatures;
1074 gsub.num_features = nfeatures;
1075 gsub.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1076 memset (gsub.features, 0, (sizeof (FeatureElement)) * nfeatures);
1081 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
1083 OTF_Tag tag = otf->gpos->ScriptList.Script[i].ScriptTag;
1087 < otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount)
1089 = otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount;
1090 for (k = 0; k < prev_n; k++)
1091 if (tag == script_langsys[k].script)
1095 script_langsys[n].script = tag;
1096 script_langsys[n++].langsys = 0;
1098 for (j = 0; j < otf->gpos->ScriptList.Script[i].LangSysCount; j++)
1104 OTF_Script *script = otf->gpos->ScriptList.Script + i;
1106 for (l = k; l < prev_n && tag == script_langsys[l].script; l++)
1107 if (script->LangSysRecord[j].LangSysTag
1108 == script_langsys[l].langsys)
1115 script_langsys[n].script = tag;
1116 script_langsys[n++].langsys = 0;
1119 < otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount)
1121 = otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount;
1127 gpos.num_features = nfeatures;
1128 gpos.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1129 memset (gpos.features, 0, (sizeof (FeatureElement)) * nfeatures);
1135 script_tag = script_langsys[0].script;
1136 langsys_tag = script_langsys[0].langsys;
1137 compose_script_langsys (script_tag, langsys_tag, name);
1141 XtSetArg (arg[0], XtNforeground, background);
1142 XtSetArg (arg[1], XtNbackground, foreground);
1143 XtCreateManagedWidget (name, labelWidgetClass, prev, arg, 2);
1147 XtSetArg (arg[0], XtNstate, True);
1148 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1149 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1150 XtSetArg (arg[0], XtNradioGroup, w);
1151 for (i = 1; i < n; i++)
1153 compose_script_langsys (script_langsys[i].script,
1154 script_langsys[i].langsys, name);
1155 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1156 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1164 create_otf_widgets (Widget prev, FeatureRec *rec)
1169 XtSetArg (arg[0], XtNborderWidth, 0);
1170 XtSetArg (arg[1], XtNleft, XawChainLeft);
1171 XtSetArg (arg[2], XtNright, XawChainLeft);
1172 XtSetArg (arg[3], XtNtop, XawChainTop);
1173 XtSetArg (arg[4], XtNbottom, XawChainTop);
1174 XtSetArg (arg[5], XtNfromVert, prev);
1175 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1176 prev = XtCreateManagedWidget (rec->label, boxWidgetClass, render_area,
1178 XtCreateManagedWidget (rec->label, labelWidgetClass, prev, arg, 1);
1179 XtSetArg (arg[0], XtNborderWidth, 1);
1180 XtSetArg (arg[1], XtNinternalHeight, 4);
1181 XtSetArg (arg[2], XtNinternalWidth, 4);
1182 w = XtCreateManagedWidget ("all", commandWidgetClass, prev, arg, 3);
1183 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1184 w = XtCreateManagedWidget ("none", commandWidgetClass, prev, arg, 3);
1185 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1188 setup_feature_rec (rec);
1195 String quit_action = "<KeyPress>q: set() notify() unset()";
1196 String FIRST_action = "<KeyPress>f: set() notify() unset()\n\
1197 <KeyPress>Home: set() notify() unset()";
1198 String PREV_action = "Shift<KeyPress>p: set() notify() unset()\n\
1199 <KeyPress>Up: set() notify() unset()";
1200 String prev_action = "~Shift<KeyPress>p: set() notify() unset()\n\
1201 <KeyPress>Left: set() notify() unset()";
1202 String next_action = "~Shift<KeyPress>n: set() notify() unset()\n\
1203 <KeyPress>Right: set() notify() unset()";
1204 String NEXT_action = "Shift<KeyPress>n: set() notify() unset()\n\
1205 <KeyPress>Down: set() notify() unset()";
1206 String LAST_action = "<KeyPress>l: set() notify() unset()\n\
1207 <KeyPress>End: set() notify() unset()";
1211 String trans = "<Expose>: Expose()";
1213 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans));
1214 frame = XtCreateManagedWidget ("frame", formWidgetClass, shell, arg, 1);
1216 XtSetArg (arg[0], XtNleft, XawChainLeft);
1217 XtSetArg (arg[1], XtNright, XawChainLeft);
1218 XtSetArg (arg[2], XtNtop, XawChainTop);
1219 XtSetArg (arg[3], XtNbottom, XawChainTop);
1220 XtSetArg (arg[4], XtNborderWidth, 0);
1221 XtSetArg (arg[5], XtNorientation, XtorientHorizontal);
1222 command_area = XtCreateManagedWidget ("command-area", boxWidgetClass,
1224 XtSetArg (arg[6], XtNfromVert, command_area);
1225 navi_area = XtCreateManagedWidget ("navi-area", boxWidgetClass,
1227 XtSetArg (arg[4], XtNborderWidth, 0);
1228 XtSetArg (arg[5], XtNfromVert, navi_area);
1229 XtSetArg (arg[6], XtNdefaultDistance, 0);
1230 glyph_area = XtCreateManagedWidget ("glyph-area", formWidgetClass,
1233 XtSetArg (arg[5], XtNfromVert, glyph_area);
1238 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1239 uvs_area = XtCreateManagedWidget ("uvs-area", boxWidgetClass,
1241 XtSetArg (arg2[0], XtNborderWidth, 0);
1242 XtSetArg (arg2[1], XtNlabel, "Variation Selector: ");
1243 uvs_label = XtCreateManagedWidget ("uvs-label", labelWidgetClass,
1245 XtSetArg (arg2[0], XtNborderWidth, 1);
1246 for (i = 0; i < sub14->nRecords; i++)
1248 OTF_VariationSelectorRecord *record = sub14->Records + i;;
1249 unsigned selector = record->varSelector;
1253 idx = (selector <= 0xFE0F ? selector - 0xFE00
1254 : selector - 0xE0100 + 16);
1257 uvs[idx].c = selector;
1258 sprintf (lbl, "%03d", idx + 1);
1259 XtSetArg (arg2[1], XtNlabel, lbl);
1260 XtSetArg (arg2[2], XtNsensitive, False);
1261 uvs[idx].w = XtCreateManagedWidget ("lbl", commandWidgetClass,
1263 XtAddCallback (uvs[idx].w, XtNcallback, UVSProc, (XtPointer) idx);
1265 XtSetArg (arg[5], XtNfromVert, uvs_area);
1267 render_area = XtCreateManagedWidget ("render-area", formWidgetClass,
1270 XtSetArg (arg[0], XtNaccelerators, XtParseAcceleratorTable (quit_action));
1271 quit = XtCreateManagedWidget ("Quit", commandWidgetClass,
1272 command_area, arg, 1);
1273 XtAddCallback (quit, XtNcallback, QuitProc, NULL);
1275 dump = XtCreateManagedWidget ("DumpImage", commandWidgetClass,
1276 command_area, arg, 1);
1277 XtAddCallback (dump, XtNcallback, DumpProc, NULL);
1279 XtSetArg (arg[0], XtNborderWidth, 0);
1280 XtSetArg (arg[1], XtNwidth, 10);
1281 XtCreateManagedWidget ("spacer", boxWidgetClass, command_area, arg, 2);
1283 charmap = alloca (sizeof (Widget) * (face->num_charmaps + 1));
1284 XtSetArg (arg[0], XtNstate, True);
1285 charmap[0] = XtCreateManagedWidget (charmap_rec[0].name, toggleWidgetClass,
1286 command_area, arg, 1);
1287 XtAddCallback (charmap[0], XtNcallback, CharmapProc, (XtPointer) -1);
1288 XtSetArg (arg[0], XtNradioGroup, charmap[0]);
1289 for (i = 0; i < face->num_charmaps; i++)
1291 charmap[i + 1] = XtCreateManagedWidget (charmap_rec[i + 1].name,
1293 command_area, arg, 1);
1294 XtAddCallback (charmap[i + 1], XtNcallback, CharmapProc, (XtPointer) i);
1297 XtSetArg (arg[0], XtNlabel, " |< (f)");
1298 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (FIRST_action));
1299 FIRST = XtCreateManagedWidget ("FIRST", commandWidgetClass,
1301 XtAddCallback (FIRST, XtNcallback, GlyphProc, (XtPointer) -3);
1302 XtSetArg (arg[0], XtNlabel, "<< (P)");
1303 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (PREV_action));
1304 PREV = XtCreateManagedWidget ("PREV", commandWidgetClass,
1306 XtAddCallback (PREV, XtNcallback, GlyphProc, (XtPointer) -2);
1307 XtSetArg (arg[0], XtNlabel, "< (p)");
1308 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (prev_action));
1309 prev = XtCreateManagedWidget ("prev", commandWidgetClass,
1311 XtAddCallback (prev, XtNcallback, GlyphProc, (XtPointer) -1);
1312 XtSetArg (arg[0], XtNlabel, " 0000 ");
1313 range = XtCreateManagedWidget ("range", labelWidgetClass,
1315 XtSetArg (arg[0], XtNforeground, &foreground);
1316 XtSetArg (arg[1], XtNbackground, &background);
1317 XtGetValues (range, arg, 2);
1319 XtSetArg (arg[0], XtNlabel, "> (n)");
1320 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (next_action));
1321 next = XtCreateManagedWidget ("next", commandWidgetClass,
1323 XtAddCallback (next, XtNcallback, GlyphProc, (XtPointer) 1);
1324 XtSetArg (arg[0], XtNlabel, ">> (N)");
1325 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (NEXT_action));
1326 NEXT = XtCreateManagedWidget ("NEXT", commandWidgetClass,
1328 XtAddCallback (NEXT, XtNcallback, GlyphProc, (XtPointer) 2);
1329 XtSetArg (arg[0], XtNlabel, ">| (l)");
1330 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (LAST_action));
1331 LAST = XtCreateManagedWidget ("LAST", commandWidgetClass,
1333 XtAddCallback (LAST, XtNcallback, GlyphProc, (XtPointer) 3);
1335 XtSetArg (arg[0], XtNleft, XawChainLeft);
1336 XtSetArg (arg[1], XtNright, XawChainLeft);
1337 XtSetArg (arg[2], XtNtop, XawChainTop);
1338 XtSetArg (arg[3], XtNbottom, XawChainTop);
1340 for (i = 0; i < 8; i++)
1346 sprintf (str, "%XX", i);
1347 XtSetArg (arg[n], XtNheight, glyph_height + 5), n++;
1348 XtSetArg (arg[n], XtNlabel, str), n++;
1349 XtSetArg (arg[n], XtNborderWidth, 0), n++;
1351 XtSetArg (arg[n], XtNfromVert, w), n++;
1352 head = XtCreateManagedWidget (str, labelWidgetClass, glyph_area, arg, n);
1353 index_label[i] = head;
1354 for (j = 0; j < 16; j++)
1360 XtSetArg (arg[n], XtNfromVert, w), n++;
1362 XtSetArg (arg[n], XtNfromHoriz, head), n++;
1364 XtSetArg (arg[n], XtNfromHoriz, glyph[k - 1]), n++;
1365 XtSetArg (arg[n], XtNbitmap, none_pixmap), n++;
1366 glyph[k] = XtCreateManagedWidget ("glyph", commandWidgetClass,
1367 glyph_area, arg, n);
1368 XtAddCallback (glyph[k], XtNcallback, RenderProc, (XtPointer) k);
1372 /* 10 = (1 (border_width) + 4 (inner_width)) * 2 */
1373 XtSetArg(arg[4], XtNwidth, glyph_width + 10);
1374 XtSetArg (arg[5], XtNfromVert, glyph[112]);
1375 XtSetArg (arg[6], XtNfromHoriz, w);
1376 XtSetArg (arg[7], XtNborderWidth, 0);
1378 for (j = 0; j < 16; j++)
1382 sprintf (str, "X%X", j);
1383 XtSetArg (arg[8], XtNlabel, str);
1384 w = XtCreateManagedWidget ("idx", labelWidgetClass, glyph_area, arg, 9);
1385 XtSetArg (arg[6], XtNfromHoriz, w);
1388 XtSetArg (arg[0], XtNleft, XawChainLeft);
1389 XtSetArg (arg[1], XtNright, XawChainLeft);
1390 XtSetArg (arg[2], XtNtop, XawChainTop);
1391 XtSetArg (arg[3], XtNbottom, XawChainTop);
1392 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1393 XtSetArg (arg[5], XtNborderWidth, 0);
1394 w = XtCreateManagedWidget ("clear-box", boxWidgetClass, render_area, arg, 6);
1395 clear = XtCreateManagedWidget ("clear", commandWidgetClass, w, arg, 0);
1396 XtAddCallback (clear, XtNcallback, RenderProc, (XtPointer) -1);
1397 del = XtCreateManagedWidget ("delete", commandWidgetClass, w, arg, 0);
1398 XtAddCallback (del, XtNcallback, RenderProc, (XtPointer) -2);
1399 bidi = XtCreateManagedWidget ("L->R", toggleWidgetClass, w, arg, 0);
1400 XtAddCallback (bidi, XtNcallback, BidiProc, NULL);
1401 alt_subst = XtCreateManagedWidget ("AltSubst", toggleWidgetClass, w, arg, 0);
1402 XtAddCallback (alt_subst, XtNcallback, AltSubstProc, NULL);
1404 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1405 XtSetArg (arg[5], XtNborderWidth, 0);
1406 XtSetArg (arg[6], XtNfromVert, w);
1407 raw = XtCreateManagedWidget ("raw", boxWidgetClass, render_area, arg, 7);
1409 XtSetArg (arg[0], XtNborderWidth, 0);
1410 XtSetArg (arg[1], XtNlabel, "raw: ");
1411 raw_label = XtCreateManagedWidget ("raw-label", labelWidgetClass,
1413 XtSetArg (arg[1], XtNbitmap, raw_pixmap);
1414 raw_image = XtCreateManagedWidget ("raw-image", labelWidgetClass,
1419 OTF_get_table (otf, "GSUB");
1420 OTF_get_table (otf, "GPOS");
1421 w = create_otf_script_widgets (w);
1424 gsub.label = "GSUB";
1425 gsub.gsub_gpos = otf->gsub;
1426 w = create_otf_widgets (w, &gsub);
1430 gpos.label = "GPOS";
1431 gpos.gsub_gpos = otf->gpos;
1432 w = create_otf_widgets (w, &gpos);
1436 XtSetArg (arg[6], XtNfromVert, w);
1437 seq = XtCreateManagedWidget ("seq", boxWidgetClass, render_area, arg, 7);
1438 XtSetArg (arg[0], XtNborderWidth, 0);
1439 XtSetArg (arg[1], XtNlabel, "seq: ");
1440 seq_label = XtCreateManagedWidget ("seq-label", labelWidgetClass,
1442 XtSetArg (arg[1], XtNbitmap, seq_pixmap);
1443 seq_image = XtCreateManagedWidget ("seq-image", labelWidgetClass,
1445 XtInstallAllAccelerators (shell, shell);
1449 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1451 XTextProperty text_prop;
1452 char *pname = "otfview";
1453 char *fname = basename (filename);
1454 char *name = alloca (strlen (fname) + 3 + strlen (pname) + 1);
1456 sprintf (name, "%s - %s", pname, fname);
1457 text_prop.value = (unsigned char *) name;
1458 text_prop.encoding = XA_STRING;
1459 text_prop.format = 8;
1460 text_prop.nitems = strlen (name);
1461 XSetWMName (display, XtWindow (shell), &text_prop);
1464 /* Format MSG by FMT and print the result to the stderr, and exit. */
1466 #define FATAL_ERROR(fmt, arg) \
1468 fprintf (stderr, fmt, arg); \
1473 x_error_handler (Display *display, XErrorEvent *error)
1479 help (char **argv, int err)
1481 FILE *fp = err ? stderr : stdout;
1483 fprintf (fp, "Usage: %s [ X-OPTION ... ] OTF-FILE [INDEX]\n",
1484 basename (argv[0]));
1485 fprintf (fp, " Environment variable PIXEL_SIZE specifies the pixel size.\n");
1486 fprintf (fp, " The default pixel size is %d, but is reduced\n",
1487 DEFAULT_PIXEL_SIZE);
1488 fprintf (fp, " if your screen is not that wide.\n");
1493 main (int argc, char **argv)
1495 XtActionsRec actions[] = { {"Expose", ExposeProc} };
1499 OTF_GlyphString gstring;
1504 int fixed_pixel_size = 0;
1507 pixel_size = DEFAULT_PIXEL_SIZE;
1509 char *str = getenv ("PIXEL_SIZE");
1511 if (str && (i = atoi (str)) > 0)
1514 fixed_pixel_size = 1;
1518 gstring.size = gstring.used = 256;
1519 g = calloc (256, sizeof (OTF_Glyph));
1522 shell = XtOpenApplication (&context, "OTFView", NULL, 0, &argc, argv, NULL,
1523 shellWidgetClass, arg, 0);
1524 display = XtDisplay (shell);
1525 /*XSynchronize (display, True);*/
1526 XSetErrorHandler (x_error_handler);
1527 display_width = DisplayWidth (display,
1528 XScreenNumberOfScreen (XtScreen (shell)));
1529 font = XLoadQueryFont (display, DEFAULT_FONT_NAME);
1531 font = XLoadQueryFont (display, "fixed");
1535 if (!strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
1540 fontindex = atoi (argv[2]);
1542 FATAL_ERROR ("Invalid font index: %d\n", fontindex);
1545 if ((err = FT_Init_FreeType (&library)))
1546 FATAL_ERROR ("%s\n", "FT_Init_FreeType: error");
1547 err = FT_New_Face (library, filename, fontindex, &face);
1548 if (err == FT_Err_Unknown_File_Format)
1549 FATAL_ERROR ("%s\n", "FT_New_Face: unknown file format");
1551 FATAL_ERROR ("%s\n", "FT_New_Face: unknown error (invalid face index?)");
1552 if ((err = FT_Set_Pixel_Sizes (face, 0, pixel_size)))
1553 FATAL_ERROR ("%s\n", "FT_Set_Pixel_Sizes: error");
1555 if (strstr (filename, ".ttf")
1556 || strstr (filename, ".TTF")
1557 || strstr (filename, ".otf")
1558 || strstr (filename, ".OTF"))
1560 otf = OTF_open_ft_face (face);
1562 || OTF_get_table (otf, "head") < 0
1563 || OTF_get_table (otf, "cmap") < 0
1564 || (OTF_check_table (otf, "GSUB") < 0
1565 && OTF_check_table (otf, "GPOS") < 0))
1567 for (i = 0; i < otf->cmap->numTables; i++)
1568 if (otf->cmap->EncodingRecord[i].subtable.format == 14)
1570 sub14 = otf->cmap->EncodingRecord[i].subtable.f.f14;
1579 filename = basename (filename);
1580 sprintf (title, "%s family:%s style:%s",
1581 filename, face->family_name, face->style_name);
1582 XtSetArg (arg[0], XtNtitle, title);
1583 XtSetValues (shell, arg, 1);
1586 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1587 * pixel_size / face->units_per_EM);
1588 if (! fixed_pixel_size && glyph_width * 16 > display_width * 0.8)
1590 pixel_size = (pixel_size * display_width * 0.8 / 16 / glyph_width);
1591 FT_Set_Pixel_Sizes (face, 0, pixel_size);
1592 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1593 * pixel_size / face->units_per_EM);
1595 if (glyph_width < FONT_WIDTH * 4)
1596 glyph_width = FONT_WIDTH * 4;
1598 glyph_height = ((face->bbox.yMax - face->bbox.yMin)
1599 * pixel_size / face->units_per_EM);
1601 glyph_x = - (face->bbox.xMin * pixel_size / face->units_per_EM);
1602 glyph_y = face->bbox.yMax * pixel_size / face->units_per_EM;
1603 none_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1604 glyph_width, glyph_height, 1);
1607 unsigned long valuemask = GCFunction | GCLineWidth;
1610 gc = XCreateGC (display, none_pixmap, (unsigned long) 0, NULL);
1611 XSetFont (display, gc, font->fid);
1612 values.function = GXset;
1613 values.line_width = 1;
1614 gc_set = XCreateGC (display, none_pixmap, valuemask, &values);
1615 XSetFont (display, gc_set, font->fid);
1616 values.function = GXor;
1617 gc_or = XCreateGC (display, none_pixmap, valuemask, &values);
1618 values.function = GXcopyInverted;
1619 gc_inv = XCreateGC (display, none_pixmap, valuemask, &values);
1622 XFillRectangle (display, none_pixmap, gc, 0, 0,
1623 glyph_width, glyph_height);
1624 XDrawString (display, none_pixmap, gc_inv,
1625 (glyph_width - XTextWidth (font, "none", 4)) / 2,
1626 glyph_height / 2, "none", 4);
1628 render_width = (glyph_width + 4) * 15 + 1;
1629 render_height = glyph_height + 2;
1631 charmap_rec[0].platform_id = -1;
1632 charmap_rec[0].encoding_id = -1;
1633 strcpy (charmap_rec[0].name, "no charmap");
1635 for (i = 0; i < face->num_charmaps; i++)
1637 charmap_rec[i + 1].platform_id = face->charmaps[i]->platform_id;
1638 charmap_rec[i + 1].encoding_id = face->charmaps[i]->encoding_id;
1639 sprintf (charmap_rec[i + 1].name, "%d-%d",
1640 charmap_rec[i + 1].platform_id, charmap_rec[i + 1].encoding_id);
1641 if (face->charmaps[i]->platform_id == 0
1642 || (face->charmaps[i]->platform_id == 3
1643 && face->charmaps[i]->encoding_id == 1))
1644 strcat (charmap_rec[i + 1].name, " (unicode)");
1645 else if (face->charmaps[i]->platform_id == 1
1646 && face->charmaps[i]->encoding_id == 0)
1647 strcat (charmap_rec[i + 1].name, " (apple-roman)");
1650 raw_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1651 render_width, render_height, 1);
1652 seq_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1653 render_width, render_height, 1);
1655 memset (bitmap, 0, sizeof (bitmap));
1659 update_glyph_area ();
1660 update_render_area ();
1662 XtAppAddActions (context, actions, XtNumber (actions));
1663 XtRealizeWidget (shell);
1664 XtAppMainLoop (context);
1669 #else /* not HAVE_X11_XAW_COMMAND_H */
1672 main (int argc, char **argv)
1675 "Building of this program failed (lack of some header files)\n");