1 /* otfview.c -- View glyphs of OpenType fonts.
3 Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009
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 CAST_FROM_XTPOINTER(TYPE, DATA, VAR) \
52 long TYPE temp = (long TYPE) (DATA); \
56 #define XtAddCallbackWithCast(TYPE, W, PROC, VAR) \
58 long TYPE temp = (long TYPE) (VAR); \
59 XtAddCallback (W, XtNcallback, PROC, (XtPointer) temp); \
63 #define DEFAULT_PIXEL_SIZE 30
66 #define DEFAULT_FONT_NAME "6x13"
68 #define FONT_HEIGHT (font->ascent + font->descent)
69 #define FONT_ASCENT (font->ascent)
70 #define FONT_DESCENT (font->descent)
71 #define FONT_WIDTH (font->max_bounds.width)
75 +--- frame (form) -------------------------+
76 | +--- command_area (box) ---------------+ |
77 | | quit dump charmap ... | |
78 | +--------------------------------------+ |
79 | +---- navi_area (box) -----------------+ |
80 | | FIRST PREV prev range next NEXT LAST | |
81 | +--------------------------------------+ |
82 | +--- glyph_area (form) ----------------+ |
83 | | idxh[0] glyph[0] ... glyph[15] | |
85 | | idxh[7] glyph[112] ... glyph[127]| |
86 | | idxl[0] ... idxl[15] | |
87 | +--------------------------------------+ |
88 | +---- uvs_area (box) (optional) -------+ |
90 | +--------------------------------------+ |
91 | +--- render_area (form) ---------------+ |
92 | | clear del bidi alt_subst | |
93 | | +--- raw (box) --------------------+ | |
94 | | | raw_label raw_image | | |
95 | | +----------------------------------+ | |
96 | | GSUB all none features... | |
97 | | GPOS all none features... | |
98 | | +--- seq (box) --------------------+ | |
99 | | | seq_label seq_image | | |
100 | | +----------------------------------+ | |
101 | | +--- code (box) -------------------+ | |
102 | | | code_label code_list ... | | |
103 | | +----------------------------------+ | |
104 | +--------------------------------------+ |
105 +------------------------------------------+ */
107 Widget command_area, quit, dump, *charmap;
108 Widget navi_area, FIRST, PREV, prev, range, next, NEXT, LAST;
109 Widget glyph_area, glyph[128], index_label[8];
110 Widget uvs_area, uvs_label;
111 Widget render_area, clear, del, bidi, alt_subst, raw, seq, code;
112 Widget raw_label, raw_image, seq_label, seq_image, code_label, code_list;
113 unsigned long foreground, background;
125 OTF_GSUB_GPOS *gsub_gpos;
126 OTF_LangSys *langsys;
128 FeatureElement *features;
132 FeatureRec gsub, gpos;
134 /* Currently selected script and langsys. */
135 OTF_Tag script_tag, langsys_tag;
140 GC gc, gc_set, gc_or, gc_inv;
144 unsigned width, height;
149 BitmapRec bitmap[0x110000];
151 int render_width, render_height;
152 Pixmap raw_pixmap, seq_pixmap, gsub_pixmap, gpos_pixmap;
166 int do_alternate_subst;
167 unsigned glyph_width, glyph_height;
168 int glyph_x, glyph_y;
177 OTF_EncodingSubtable14 *sub14 = NULL;
189 create_pixmap (int index)
191 int err = FT_Load_Glyph (face, index, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
197 bitmap[index].pixmap = none_pixmap;
200 ximage.height = face->glyph->bitmap.rows;
201 ximage.width = face->glyph->bitmap.width;
203 ximage.bits_per_pixel = 1;
205 ximage.format = XYPixmap;
206 ximage.data = (char *) face->glyph->bitmap.buffer;
207 ximage.byte_order = MSBFirst;
208 ximage.bitmap_unit = 8;
209 ximage.bitmap_bit_order = MSBFirst;
210 ximage.bitmap_pad = 8;
211 ximage.bytes_per_line = face->glyph->bitmap.pitch;
212 XInitImage (&ximage);
213 pixmap = XCreatePixmap (display, DefaultRootWindow (display),
214 glyph_width, glyph_height, 1);
215 XFillRectangle (display, pixmap, gc, 0, 0, glyph_width, glyph_height);
216 XPutImage (display, pixmap, gc, &ximage, 0, 0,
217 glyph_x + face->glyph->bitmap_left,
218 glyph_y - face->glyph->bitmap_top,
219 ximage.width, ximage.height);
220 bitmap[index].pixmap = pixmap;
221 bitmap[index].width = ximage.width;
222 bitmap[index].height = ximage.height;
223 bitmap[index].x = face->glyph->bitmap_left;
224 bitmap[index].y = - face->glyph->bitmap_top;
225 bitmap[index].advance = face->glyph->metrics.horiAdvance >> 6;
236 for (i = 0; i < 128; i++)
238 int index = glyph_index + i;
240 if (charmap_index >= 0)
241 index = FT_Get_Char_Index (face, (FT_ULong) index);
242 if (charmap_index >= 0 && ! index)
243 XtSetArg (arg[0], XtNbitmap, none_pixmap);
246 if (! bitmap[index].pixmap)
247 create_pixmap (index);
248 XtSetArg (arg[0], XtNbitmap, bitmap[index].pixmap);
250 XtSetValues (glyph[i], arg, 1);
253 msb = (glyph_index >> 7) % 2 ? 8 : 0;
254 for (i = 0; i < 8; i++)
258 sprintf (str, "%XX", i | msb );
259 XtSetArg (arg[0], XtNheight, glyph_height + 5);
260 XtSetArg (arg[1], XtNlabel, str);
261 XtSetValues (index_label[i], arg, 2);
264 if (glyph_index < 0x10000)
265 sprintf (buf, " %04X-%04X ", glyph_index, glyph_index + 0x7F);
267 sprintf (buf, "%06X-%06X", glyph_index, glyph_index + 0x7F);
268 XtSetArg (arg[0], XtNlabel, buf);
269 XtSetValues (range, arg, 1);
273 update_uvs_area (int c)
275 OTF_GlyphID code[256];
279 OTF_get_variation_glyphs (otf, c, code);
281 for (i = 0; i < 256; i++)
285 XtSetArg (arg[0], XtNsensitive, True);
287 XtSetArg (arg[0], XtNsensitive, False);
288 XtSetValues (uvs[i].w, arg, 1);
294 get_features (OTF_FeatureList *list, FeatureRec *rec)
299 if (! rec->langsys || ! rec->features || ! rec->features[0].on)
301 for (i = n = 0; i < rec->langsys->FeatureCount; i++)
302 if (rec->features[i].on)
304 str = malloc (n * 5);
305 for (i = 0, p = str; i < n; i++, p += 5)
306 if (rec->features[i].on)
308 OTF_tag_name (rec->features[i].tag, p);
316 #define DEVICE_DELTA(table, size) \
317 (((table).DeltaValue \
318 && ((size) >= (table).StartSize && (size) <= (table).EndSize)) \
319 ? (table).DeltaValue[(size) >= (table).StartSize] \
323 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
324 OTF_Glyph *g, int *x, int *y)
326 if (anchor->AnchorFormat == 2)
329 int ap = anchor->f.f1.AnchorPoint;
331 FT_Load_Glyph (ft_face, (FT_UInt) g->glyph_id, FT_LOAD_MONOCHROME);
332 outline = &ft_face->glyph->outline;
333 if (ap < outline->n_points)
335 *x = outline->points[ap].x;
336 *y = outline->points[ap].y;
339 else if (anchor->AnchorFormat == 3)
341 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, pixel_size);
342 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, pixel_size);
350 OTF_GlyphString gstring;
351 OTF_Glyph *g, *prev, *base, *mark;
353 int len = glyph_rec.n_glyphs;
355 int unitsPerEm = face->units_per_EM;
357 gstring.size = gstring.used = len;
358 gstring.glyphs = malloc (sizeof (OTF_Glyph) * len);
359 memset (gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
360 for (i = 0; i < len; i++)
362 gstring.glyphs[i].c = glyph_rec.codes[i];
363 if (charmap_index < 0)
364 gstring.glyphs[i].glyph_id = glyph_rec.glyphs[i];
367 XFillRectangle (display, seq_pixmap, gc, 0, 0, render_width, render_height);
368 XDrawLine (display, seq_pixmap, gc_set, 0, glyph_y, render_width, glyph_y);
371 char *script_name = NULL, *langsys_name = NULL, buf[10];
377 OTF_tag_name (script_tag, script_name);
381 langsys_name = buf + 5;
382 OTF_tag_name (langsys_tag, langsys_name);
385 OTF_drive_cmap (otf, &gstring);
386 OTF_drive_gdef (otf, &gstring);
389 str = get_features (&otf->gsub->FeatureList, &gsub);
392 if (do_alternate_subst)
393 OTF_drive_gsub_alternate (otf, &gstring,
394 script_name, langsys_name, str);
396 OTF_drive_gsub (otf, &gstring, script_name, langsys_name, str);
402 str = get_features (&otf->gpos->FeatureList, &gpos);
405 OTF_drive_gpos2 (otf, &gstring, script_name, langsys_name, str);
416 for (prev = gstring.glyphs, g = gstring.glyphs + gstring.used - 1;
417 prev < g; prev++, g--)
418 temp = *prev, *prev = *g, *g = temp;
419 for (g = gstring.glyphs; g < gstring.glyphs + gstring.used; g++)
420 if (g->GlyphClass == 3)
424 while (g < gstring.glyphs + gstring.used && g->GlyphClass == 3)
426 for (g0 = g; prev < g0; prev++, g0--)
427 temp = *prev, *prev = *g, *g = temp;
433 for (i = 0, x = glyph_x, prev = NULL, g = gstring.glyphs;
434 i < gstring.used; i++, prev = g++)
436 BitmapRec *bmp = bitmap + gstring.glyphs[i].glyph_id;
437 int xoff = 0, yoff = 0;
439 int advance = bmp->advance;
441 if (gstring.glyphs[i].glyph_id && ! bmp->pixmap)
443 create_pixmap (gstring.glyphs[i].glyph_id);
446 advance = bmp->advance;
448 if (g->positioning_type)
452 switch (g->positioning_type)
456 int format = g->f.f1.format;
458 if (format & OTF_XPlacement)
459 xoff += g->f.f1.value->XPlacement * pixel_size / unitsPerEm;
460 if (format & OTF_XPlaDevice)
461 xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, pixel_size);
462 if (format & OTF_YPlacement)
463 yoff += g->f.f1.value->YPlacement * pixel_size / unitsPerEm;
464 if (format & OTF_YPlaDevice)
465 yoff += DEVICE_DELTA (g->f.f1.value->YPlaDevice, pixel_size);
466 if (format & OTF_XAdvance)
467 advance += g->f.f1.value->XAdvance * pixel_size / unitsPerEm;
468 if (format & OTF_XAdvDevice)
469 advance += DEVICE_DELTA (g->f.f1.value->XAdvDevice,
475 /* Not yet supported. */
481 prev_width = base_width;
482 goto label_adjust_anchor;
483 default: /* i.e. case 6 */
490 int base_x, base_y, mark_x, mark_y;
492 base_x = g->f.f4.base_anchor->XCoordinate * pixel_size / unitsPerEm;
493 base_y = g->f.f4.base_anchor->YCoordinate * pixel_size / unitsPerEm;
494 mark_x = g->f.f4.mark_anchor->XCoordinate * pixel_size / unitsPerEm;
495 mark_y = g->f.f4.mark_anchor->YCoordinate * pixel_size / unitsPerEm;
497 if (g->f.f4.base_anchor->AnchorFormat != 1)
498 adjust_anchor (g->f.f4.base_anchor, face, prev, &base_x, &base_y);
499 if (g->f.f4.mark_anchor->AnchorFormat != 1)
500 adjust_anchor (g->f.f4.mark_anchor, face, g, &mark_x, &mark_y);
501 xoff = (base_x - prev_width) - mark_x;
502 yoff = base_y - mark_y;
505 if (i + 1 == gstring.used
506 || gstring.glyphs[i + 1].glyph_id
507 || ! gstring.glyphs[i + 1].positioning_type)
513 XCopyArea (display, bmp->pixmap, seq_pixmap, gc_or,
514 glyph_x + bmp->x, glyph_y + bmp->y, bmp->width, bmp->height,
515 x + bmp->x + xoff, glyph_y + bmp->y - yoff);
518 if (g->GlyphClass == OTF_GlyphClass0)
519 base = mark = g, base_width = advance;
520 else if (g->GlyphClass == OTF_GlyphClassMark)
523 base = g, base_width = advance;
526 XtSetArg (arg[0], XtNbitmap, seq_pixmap);
527 XtSetValues (seq_image, arg, 1);
529 if (gstring.used > 0)
531 int size = render_width / FONT_WIDTH;
532 char *buf = alloca (size + 1);
534 sprintf (buf, "%04X", gstring.glyphs[0].glyph_id);
535 for (i = 1, x = 4; i < gstring.used; i++, x += 5)
536 sprintf (buf + x, " %04X", gstring.glyphs[i].glyph_id);
540 XtSetArg (arg[0], XtNlabel, buf);
541 XtSetValues (code_list, arg, 1);
544 free (gstring.glyphs);
549 update_render_area ()
555 XFillRectangle (display, raw_pixmap, gc, 0, 0, render_width, render_height);
556 for (i = 0, x = glyph_x; i < glyph_rec.n_glyphs; i++)
558 if (glyph_rec.glyphs[i] >= 0)
560 BitmapRec *bmp = bitmap + glyph_rec.glyphs[i];
563 XCopyArea (display, bmp->pixmap, raw_pixmap, gc,
564 0, 0, glyph_width, glyph_height,
565 (glyph_width + 4) * i + 1, 1);
566 XDrawRectangle (display, raw_pixmap, gc_set,
567 (glyph_width + 4) * i, 0,
568 glyph_width + 1, glyph_height + 1);
569 XDrawLine (display, raw_pixmap, gc_set,
570 (glyph_width + 4) * i + 1 + glyph_x, 1,
571 (glyph_width + 4) * i + 1 + glyph_x, glyph_height + 1);
572 XDrawLine (display, raw_pixmap, gc_set,
573 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance, 1,
574 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance,
577 sprintf (buf, "%04X", glyph_rec.codes[i]);
578 XDrawString (display, raw_pixmap, gc_inv,
579 (glyph_width + 4) * i + 1
580 + (glyph_width - XTextWidth (font, buf, 4)) / 2,
581 glyph_height + 2 + FONT_HEIGHT, buf, 4);
585 /* Variation Selector */
586 int idx = - glyph_rec.glyphs[i];
589 sprintf (buf, "%03d", idx);
590 XDrawRectangle (display, raw_pixmap, gc_set,
591 (glyph_width + 4) * i, 0,
592 glyph_width + 1, glyph_height + 1);
593 XDrawString (display, raw_pixmap, gc_set,
594 (glyph_width + 4) * i + 1
595 + (glyph_width - XTextWidth (font, "VS", 2)) / 2,
596 1 + glyph_height / 2, "VS", 2);
597 XDrawString (display, raw_pixmap, gc_set,
598 (glyph_width + 4) * i + 1
599 + (glyph_width - XTextWidth (font, buf, 3)) / 2,
600 1 + glyph_height / 2 + FONT_ASCENT, buf, 3);
603 XtSetArg (arg[0], XtNbitmap, raw_pixmap);
604 XtSetValues (raw_image, arg, 1);
609 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
611 XtAppSetExitFlag (XtWidgetToApplicationContext (w));
615 DumpProc (Widget w, XtPointer client_data, XtPointer call_data)
617 int g_width, g_height;
619 /* unit in points (1/72 inch); to fit in both US-letter and A4 */
620 static int xoff = 30, yoff = 30;
621 static int unit = 30;
622 static int margin = 2;
623 static int title_height = 20, label_height = 10;
624 int total_width = (unit + margin * 2) * 16;
625 int total_height = (unit + margin * 2 + label_height) * 16 + title_height;
626 /* pixel size (dots) */
629 char *name = alloca (strlen (filename) + 10);
631 int index = (glyph_index / 0x100) * 0x100;
634 g_width = face->bbox.xMax - face->bbox.xMin;
635 g_height = face->bbox.yMax - face->bbox.yMin;
636 if (g_width > g_height)
638 scale = g_width * size;
639 g_x = face->bbox.xMin * unit / g_width;
640 g_y = face->bbox.yMin * unit / g_width;
644 scale = g_height * size;
645 g_x = face->bbox.xMin * unit / g_height;
646 g_y = face->bbox.yMin * unit / g_height;
648 scale /= face->units_per_EM;
650 FT_Set_Pixel_Sizes (face, 0, size);
652 sprintf (name, "%s-%04X.ps", face->family_name, index);
653 printf ("Writing %s ... ", name);
655 fp = fopen (name, "w");
657 fprintf (fp, "%s\n", "%!PS-Adobe-2.0 EPSF-2.0");
658 fprintf (fp, "%s\n", "%%Creater: otfview");
659 fprintf (fp, "%s %s(%s)-%04X\n", "%%Title:",
660 face->family_name, face->style_name, index);
661 fprintf (fp, "%s\n", "%%Pages: 1");
662 fprintf (fp, "%s %d %d %d %d\n", "%%BoundingBox:",
663 xoff, yoff, xoff + total_width, yoff + total_height);
664 fprintf (fp, "%s\n", "%%EndComments");
665 fprintf (fp, "%s\n", "%%BeginProlog");
666 fprintf (fp, "/W %d def\n", unit + margin * 2);
667 fprintf (fp, "/H %d def\n", unit + margin * 2 + label_height);
668 fprintf (fp, "/STR 10 string def\n");
669 fprintf (fp, "/DrawIndex {\n");
670 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");
671 fprintf (fp, "} def\n");
672 fprintf (fp, "/DrawTitle {\n");
673 fprintf (fp, " /Courier findfont 20 scalefont setfont\n");
674 fprintf (fp, " %d %d 4 add moveto\n", xoff + total_width / 2,
675 yoff + total_height - title_height + 2);
676 fprintf (fp, " (%s(%s)-%04X) dup stringwidth pop 2 div neg 0 rmoveto show\n",
677 face->family_name, face->style_name, index);
678 fprintf (fp, "} def\n");
679 fprintf (fp, "/DrawFrame { gsave %d %d translate 0 setlinewidth\n",
681 fprintf (fp, " /Courier findfont 10 scalefont setfont\n");
682 fprintf (fp, " /I %d def\n", index);
683 fprintf (fp, " 0 1 16 { W mul 0 moveto 0 H 16 mul rlineto stroke } for\n");
684 fprintf (fp, " 0 1 16 { H mul 0 exch moveto W 16 mul 0 rlineto stroke } for\n");
685 fprintf (fp, " 0 1 15 { H mul %d add 0 exch moveto W 16 mul 0 rlineto stroke } for\n", label_height);
686 fprintf (fp, " 15 -1 0 { gsave H mul 0 exch translate 0 0 moveto\n");
687 fprintf (fp, " 0 1 15 { gsave W mul 0 moveto\n");
688 fprintf (fp, " 4 2 rmoveto DrawIndex /I I 1 add def grestore} for\n");
689 fprintf (fp, " grestore } for grestore } def\n");
690 fprintf (fp, "%s\n", "%%EndProlog");
691 fprintf (fp, "DrawTitle DrawFrame\n");
693 for (i = 0; i < 16; i++)
694 for (j = 0; j < 16; j++, index++)
698 if (charmap_index >= 0)
699 idx = FT_Get_Char_Index (face, (FT_ULong) index);
703 && FT_Load_Glyph (face, idx, FT_LOAD_RENDER | FT_LOAD_MONOCHROME) == 0
704 && face->glyph->bitmap.rows > 0
705 && face->glyph->bitmap.width > 0)
707 unsigned char *p = face->glyph->bitmap.buffer;
708 int width = (face->glyph->bitmap.width - 1) / 8 + 1;
710 fprintf (fp, "gsave %f %f translate %d %d scale 0 0 moveto\n",
711 xoff + (unit + margin * 2) * j + margin - g_x,
712 yoff + (unit + label_height + margin * 2) * (15 - i) + label_height + margin - g_y,
714 fprintf (fp, "%d %d true [%f 0 0 %f %d %d]\n",
715 width * 8, face->glyph->bitmap.rows,
716 scale, -scale, -face->glyph->bitmap_left,
717 face->glyph->bitmap_top);
719 for (k = 0; k < face->glyph->bitmap.rows;
720 k++, p += face->glyph->bitmap.pitch)
722 for (l = 0; l < width; l++)
723 fprintf (fp, "%02X", p[l]);
726 fprintf (fp, ">} imagemask grestore\n");
730 int boxsize = unit + margin * 2;
732 fprintf (fp, "gsave 0 setlinewidth %d %d translate\n",
734 yoff + (boxsize + label_height) * (15 - i) + label_height);
735 fprintf (fp, "0 0 moveto %d %d lineto stroke\n",
737 fprintf (fp, "0 %d moveto %d 0 lineto stroke grestore\n",
741 fprintf (fp, "showpage\n");
745 FT_Set_Pixel_Sizes (face, 0, (int) pixel_size);
750 GlyphProc (Widget w, XtPointer client_data, XtPointer call_data)
752 int old_glyph_index = glyph_index;
755 CAST_FROM_XTPOINTER (int, client_data, data);
757 if (data == -3 && glyph_index > 0)
759 else if (data == -2 && glyph_index > 0)
760 glyph_index = (glyph_index - 1) & 0x1FF000;
761 else if (data == -1 && glyph_index > 0)
763 else if (data == 1 && glyph_index < 0x10FF80)
765 else if (data == 2 && glyph_index < 0x10F000)
766 glyph_index = (glyph_index + 0x1000) & 0x1FF000;
767 else if (data == 3 && glyph_index < 0x10F000)
768 glyph_index = 0x10FF80;
769 if (glyph_index != old_glyph_index)
770 update_glyph_area ();
774 CharmapProc (Widget w, XtPointer client_data, XtPointer call_data)
778 CAST_FROM_XTPOINTER (int, client_data, data);
780 if (charmap_index == data)
782 charmap_index = data;
783 if (charmap_index >= 0)
784 FT_Set_Charmap (face, face->charmaps[charmap_index]);
785 update_glyph_area ();
789 UVSProc (Widget w, XtPointer client_data, XtPointer call_data)
793 OTF_VariationSelectorRecord *record;
796 CAST_FROM_XTPOINTER (unsigned, client_data, idx);
797 selector = uvs[idx].c;
799 if (glyph_rec.n_glyphs >= 64)
801 for (i = 0; i < sub14->nRecords; i++)
803 record = sub14->Records + i;
804 if (record->varSelector == selector)
807 if (i < sub14->nRecords)
809 if (glyph_rec.n_glyphs > 0
810 && glyph_rec.glyphs[glyph_rec.n_glyphs - 1] < 0)
811 glyph_rec.n_glyphs--;
812 glyph_rec.codes[glyph_rec.n_glyphs] = selector;
813 glyph_rec.glyphs[glyph_rec.n_glyphs++] = - idx - 1;
814 update_render_area ();
819 RenderProc (Widget w, XtPointer client_data, XtPointer call_data)
823 CAST_FROM_XTPOINTER (int, client_data, data);
827 if (glyph_rec.n_glyphs > 0)
830 glyph_rec.n_glyphs--;
832 glyph_rec.n_glyphs = 0;
833 update_render_area ();
836 else if (glyph_rec.n_glyphs < 64)
838 int index = glyph_index + data;
840 if (charmap_index >= 0)
841 index = FT_Get_Char_Index (face, (FT_ULong) index);
842 if (bitmap[index].pixmap)
844 glyph_rec.codes[glyph_rec.n_glyphs] = glyph_index + data;
845 glyph_rec.glyphs[glyph_rec.n_glyphs++] = index;
847 update_uvs_area (glyph_index + data);
848 update_render_area ();
854 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
858 reversed = ! reversed;
860 XtSetArg (arg[0], XtNlabel, "L<-R");
862 XtSetArg (arg[0], XtNlabel, "L->R");
863 XtSetValues (w, arg, 1);
868 AltSubstProc (Widget w, XtPointer client_data, XtPointer call_data)
870 do_alternate_subst = ! do_alternate_subst;
875 FeatureProc (Widget w, XtPointer client_data, XtPointer call_data)
877 FeatureRec *rec = (FeatureRec *) client_data;
884 XtSetArg (arg[0], XtNlabel, &label);
885 XtGetValues (w, arg, 1);
886 if (! strcmp (label, "all"))
888 else if (! strcmp (label, "none"))
892 for (idx = 0; idx < rec->langsys->FeatureCount; idx++)
893 if (rec->features[idx].w == w)
895 if (idx == rec->langsys->FeatureCount)
903 for (i = 0; i < rec->langsys->FeatureCount; i++)
904 if (rec->features[i].on != on)
906 rec->features[i].on = on;
909 XtSetArg (arg[0], XtNborderWidth, 3);
910 XtSetArg (arg[1], XtNinternalHeight, 2);
911 XtSetArg (arg[2], XtNinternalWidth, 2);
915 XtSetArg (arg[0], XtNborderWidth, 1);
916 XtSetArg (arg[1], XtNinternalHeight, 4);
917 XtSetArg (arg[2], XtNinternalWidth, 4);
919 OTF_tag_name (rec->features[i].tag, str);
920 XtSetArg (arg[3], XtNlabel, str);
921 XtSetValues (rec->features[i].w, arg, 4);
928 rec->features[idx].on = ! rec->features[idx].on;
929 if (rec->features[idx].on)
931 XtSetArg (arg[0], XtNborderWidth, 3);
932 XtSetArg (arg[1], XtNinternalHeight, 2);
933 XtSetArg (arg[2], XtNinternalWidth, 2);
937 XtSetArg (arg[0], XtNborderWidth, 1);
938 XtSetArg (arg[1], XtNinternalHeight, 4);
939 XtSetArg (arg[2], XtNinternalWidth, 4);
941 OTF_tag_name (rec->features[idx].tag, str);
942 XtSetArg (arg[3], XtNlabel, str);
943 XtSetValues (rec->features[idx].w, arg, 4);
949 setup_feature_rec (FeatureRec *rec)
955 if (! rec->gsub_gpos)
957 for (i = 0; i < rec->gsub_gpos->ScriptList.ScriptCount; i++)
958 if (rec->gsub_gpos->ScriptList.Script[i].ScriptTag == script_tag)
960 OTF_Script *script = rec->gsub_gpos->ScriptList.Script + i;
964 for (j = 0; j < script->LangSysCount; j++)
965 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
967 rec->langsys = script->LangSys + j;
972 rec->langsys = &rec->gsub_gpos->ScriptList.Script[i].DefaultLangSys;
980 XtSetArg (arg[0], XtNborderWidth, 1);
981 XtSetArg (arg[1], XtNinternalHeight, 4);
982 XtSetArg (arg[2], XtNinternalWidth, 4);
983 XtSetArg (arg[3], XtNborderColor, foreground);
984 XtSetArg (arg[4], XtNsensitive, True);
985 for (i = 0; i < rec->langsys->FeatureCount; i++)
987 OTF_Feature *feature = rec->gsub_gpos->FeatureList.Feature;
988 int index = rec->langsys->FeatureIndex[i];
991 if (! rec->features[i].w)
993 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
994 rec->parent, arg, 0);
995 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
996 rec->features[i].w = w;
999 rec->features[i].tag = feature[index].FeatureTag;
1000 rec->features[i].on = 0;
1001 OTF_tag_name (rec->features[i].tag, label);
1002 XtSetArg (arg[5], XtNlabel, label);
1003 XtSetValues (rec->features[i].w, arg, 6);
1006 XtSetArg (arg[0], XtNborderColor, background);
1007 XtSetArg (arg[1], XtNsensitive, False);
1008 XtSetArg (arg[2], XtNlabel, " ");
1009 for (; i < rec->num_features; i++)
1011 if (! rec->features[i].w)
1013 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
1014 rec->parent, arg, 0);
1015 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1016 rec->features[i].w = w;
1018 XtSetValues (rec->features[i].w, arg, 3);
1023 compose_script_langsys (OTF_Tag script, OTF_Tag langsys, char *name)
1025 OTF_tag_name (script, name);
1029 OTF_tag_name (langsys, name + 5);
1036 decompose_script_langsys (OTF_Tag *script, OTF_Tag *langsys, char *name)
1038 *script = OTF_tag (name);
1040 *langsys = OTF_tag (name + 5);
1046 ScriptProc (Widget w, XtPointer client_data, XtPointer call_data)
1049 OTF_Tag script, langsys;
1052 XtSetArg (arg[0], XtNlabel, &name);
1053 XtGetValues (w, arg, 1);
1054 decompose_script_langsys (&script, &langsys, name);
1055 if (script_tag == script && langsys_tag == langsys)
1057 script_tag = script;
1058 langsys_tag = langsys;
1059 setup_feature_rec (&gsub);
1060 setup_feature_rec (&gpos);
1065 create_otf_script_widgets (Widget prev)
1069 int n, prev_n, i, j;
1077 XtSetArg (arg[0], XtNborderWidth, 0);
1078 XtSetArg (arg[1], XtNleft, XawChainLeft);
1079 XtSetArg (arg[2], XtNright, XawChainLeft);
1080 XtSetArg (arg[3], XtNtop, XawChainTop);
1081 XtSetArg (arg[4], XtNbottom, XawChainTop);
1082 XtSetArg (arg[5], XtNfromVert, prev);
1083 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1084 prev = XtCreateManagedWidget ("Script", boxWidgetClass, render_area, arg, 7);
1085 XtCreateManagedWidget ("script(langsys)", labelWidgetClass, prev, arg, 1);
1089 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
1090 n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
1092 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
1093 n += otf->gpos->ScriptList.Script[i].LangSysCount + 1;
1094 script_langsys = alloca ((sizeof script_langsys[0]) * n);
1098 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
1100 OTF_Tag tag = otf->gsub->ScriptList.Script[i].ScriptTag;
1102 script_langsys[n].script = tag;
1103 script_langsys[n++].langsys = 0;
1105 < otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount)
1107 = otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount;
1108 for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
1110 script_langsys[n].script = tag;
1111 script_langsys[n++].langsys
1112 = otf->gsub->ScriptList.Script[i].LangSysRecord[j].LangSysTag;
1114 < otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount)
1116 = otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount;
1119 gsub.num_features = nfeatures;
1122 gsub.num_features = nfeatures;
1123 gsub.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1124 memset (gsub.features, 0, (sizeof (FeatureElement)) * nfeatures);
1129 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
1131 OTF_Tag tag = otf->gpos->ScriptList.Script[i].ScriptTag;
1135 < otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount)
1137 = otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount;
1138 for (k = 0; k < prev_n; k++)
1139 if (tag == script_langsys[k].script)
1143 script_langsys[n].script = tag;
1144 script_langsys[n++].langsys = 0;
1146 for (j = 0; j < otf->gpos->ScriptList.Script[i].LangSysCount; j++)
1152 OTF_Script *script = otf->gpos->ScriptList.Script + i;
1154 for (l = k; l < prev_n && tag == script_langsys[l].script; l++)
1155 if (script->LangSysRecord[j].LangSysTag
1156 == script_langsys[l].langsys)
1163 script_langsys[n].script = tag;
1164 script_langsys[n++].langsys = 0;
1167 < otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount)
1169 = otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount;
1175 gpos.num_features = nfeatures;
1176 gpos.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1177 memset (gpos.features, 0, (sizeof (FeatureElement)) * nfeatures);
1183 script_tag = script_langsys[0].script;
1184 langsys_tag = script_langsys[0].langsys;
1185 compose_script_langsys (script_tag, langsys_tag, name);
1189 XtSetArg (arg[0], XtNforeground, background);
1190 XtSetArg (arg[1], XtNbackground, foreground);
1191 XtCreateManagedWidget (name, labelWidgetClass, prev, arg, 2);
1195 XtSetArg (arg[0], XtNstate, True);
1196 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1197 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1198 XtSetArg (arg[0], XtNradioGroup, w);
1199 for (i = 1; i < n; i++)
1201 compose_script_langsys (script_langsys[i].script,
1202 script_langsys[i].langsys, name);
1203 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1204 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1212 create_otf_widgets (Widget prev, FeatureRec *rec)
1217 XtSetArg (arg[0], XtNborderWidth, 0);
1218 XtSetArg (arg[1], XtNleft, XawChainLeft);
1219 XtSetArg (arg[2], XtNright, XawChainLeft);
1220 XtSetArg (arg[3], XtNtop, XawChainTop);
1221 XtSetArg (arg[4], XtNbottom, XawChainTop);
1222 XtSetArg (arg[5], XtNfromVert, prev);
1223 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1224 prev = XtCreateManagedWidget (rec->label, boxWidgetClass, render_area,
1226 XtCreateManagedWidget (rec->label, labelWidgetClass, prev, arg, 1);
1227 XtSetArg (arg[0], XtNborderWidth, 1);
1228 XtSetArg (arg[1], XtNinternalHeight, 4);
1229 XtSetArg (arg[2], XtNinternalWidth, 4);
1230 w = XtCreateManagedWidget ("all", commandWidgetClass, prev, arg, 3);
1231 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1232 w = XtCreateManagedWidget ("none", commandWidgetClass, prev, arg, 3);
1233 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1236 setup_feature_rec (rec);
1243 String quit_action = "<KeyPress>q: set() notify() unset()";
1244 String FIRST_action = "<KeyPress>f: set() notify() unset()\n\
1245 <KeyPress>Home: set() notify() unset()";
1246 String PREV_action = "Shift<KeyPress>p: set() notify() unset()\n\
1247 <KeyPress>Up: set() notify() unset()";
1248 String prev_action = "~Shift<KeyPress>p: set() notify() unset()\n\
1249 <KeyPress>Left: set() notify() unset()";
1250 String next_action = "~Shift<KeyPress>n: set() notify() unset()\n\
1251 <KeyPress>Right: set() notify() unset()";
1252 String NEXT_action = "Shift<KeyPress>n: set() notify() unset()\n\
1253 <KeyPress>Down: set() notify() unset()";
1254 String LAST_action = "<KeyPress>l: set() notify() unset()\n\
1255 <KeyPress>End: set() notify() unset()";
1259 String trans = "<Expose>: Expose()";
1261 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans));
1262 frame = XtCreateManagedWidget ("frame", formWidgetClass, shell, arg, 1);
1264 XtSetArg (arg[0], XtNleft, XawChainLeft);
1265 XtSetArg (arg[1], XtNright, XawChainLeft);
1266 XtSetArg (arg[2], XtNtop, XawChainTop);
1267 XtSetArg (arg[3], XtNbottom, XawChainTop);
1268 XtSetArg (arg[4], XtNborderWidth, 0);
1269 XtSetArg (arg[5], XtNorientation, XtorientHorizontal);
1270 command_area = XtCreateManagedWidget ("command-area", boxWidgetClass,
1272 XtSetArg (arg[6], XtNfromVert, command_area);
1273 navi_area = XtCreateManagedWidget ("navi-area", boxWidgetClass,
1275 XtSetArg (arg[4], XtNborderWidth, 0);
1276 XtSetArg (arg[5], XtNfromVert, navi_area);
1277 XtSetArg (arg[6], XtNdefaultDistance, 0);
1278 glyph_area = XtCreateManagedWidget ("glyph-area", formWidgetClass,
1281 XtSetArg (arg[5], XtNfromVert, glyph_area);
1286 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1287 uvs_area = XtCreateManagedWidget ("uvs-area", boxWidgetClass,
1289 XtSetArg (arg2[0], XtNborderWidth, 0);
1290 XtSetArg (arg2[1], XtNlabel, "Variation Selector: ");
1291 uvs_label = XtCreateManagedWidget ("uvs-label", labelWidgetClass,
1293 XtSetArg (arg2[0], XtNborderWidth, 1);
1294 for (i = 0; i < sub14->nRecords; i++)
1296 OTF_VariationSelectorRecord *record = sub14->Records + i;
1297 unsigned selector = record->varSelector;
1301 idx = (selector <= 0xFE0F ? selector - 0xFE00
1302 : selector - 0xE0100 + 16);
1305 uvs[idx].c = selector;
1306 sprintf (lbl, "%03d", idx + 1);
1307 XtSetArg (arg2[1], XtNlabel, lbl);
1308 XtSetArg (arg2[2], XtNsensitive, False);
1309 uvs[idx].w = XtCreateManagedWidget ("lbl", commandWidgetClass,
1311 XtAddCallbackWithCast (unsigned, uvs[idx].w, UVSProc, idx);
1313 XtSetArg (arg[5], XtNfromVert, uvs_area);
1315 render_area = XtCreateManagedWidget ("render-area", formWidgetClass,
1318 XtSetArg (arg[0], XtNaccelerators, XtParseAcceleratorTable (quit_action));
1319 quit = XtCreateManagedWidget ("Quit", commandWidgetClass,
1320 command_area, arg, 1);
1321 XtAddCallback (quit, XtNcallback, QuitProc, NULL);
1323 dump = XtCreateManagedWidget ("DumpImage", commandWidgetClass,
1324 command_area, arg, 1);
1325 XtAddCallback (dump, XtNcallback, DumpProc, NULL);
1327 XtSetArg (arg[0], XtNborderWidth, 0);
1328 XtSetArg (arg[1], XtNwidth, 10);
1329 XtCreateManagedWidget ("spacer", boxWidgetClass, command_area, arg, 2);
1331 charmap = alloca (sizeof (Widget) * (face->num_charmaps + 1));
1332 XtSetArg (arg[0], XtNstate, True);
1333 charmap[0] = XtCreateManagedWidget (charmap_rec[0].name, toggleWidgetClass,
1334 command_area, arg, 1);
1335 XtAddCallback (charmap[0], XtNcallback, CharmapProc, (XtPointer) -1);
1336 XtSetArg (arg[0], XtNradioGroup, charmap[0]);
1337 for (i = 0; i < face->num_charmaps; i++)
1339 charmap[i + 1] = XtCreateManagedWidget (charmap_rec[i + 1].name,
1341 command_area, arg, 1);
1342 XtAddCallbackWithCast (int, charmap[i + 1], CharmapProc, i);
1345 XtSetArg (arg[0], XtNlabel, " |< (f)");
1346 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (FIRST_action));
1347 FIRST = XtCreateManagedWidget ("FIRST", commandWidgetClass,
1349 XtAddCallback (FIRST, XtNcallback, GlyphProc, (XtPointer) -3);
1350 XtSetArg (arg[0], XtNlabel, "<< (P)");
1351 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (PREV_action));
1352 PREV = XtCreateManagedWidget ("PREV", commandWidgetClass,
1354 XtAddCallback (PREV, XtNcallback, GlyphProc, (XtPointer) -2);
1355 XtSetArg (arg[0], XtNlabel, "< (p)");
1356 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (prev_action));
1357 prev = XtCreateManagedWidget ("prev", commandWidgetClass,
1359 XtAddCallback (prev, XtNcallback, GlyphProc, (XtPointer) -1);
1360 XtSetArg (arg[0], XtNlabel, " 0000 ");
1361 range = XtCreateManagedWidget ("range", labelWidgetClass,
1363 XtSetArg (arg[0], XtNforeground, &foreground);
1364 XtSetArg (arg[1], XtNbackground, &background);
1365 XtGetValues (range, arg, 2);
1367 XtSetArg (arg[0], XtNlabel, "> (n)");
1368 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (next_action));
1369 next = XtCreateManagedWidget ("next", commandWidgetClass,
1371 XtAddCallback (next, XtNcallback, GlyphProc, (XtPointer) 1);
1372 XtSetArg (arg[0], XtNlabel, ">> (N)");
1373 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (NEXT_action));
1374 NEXT = XtCreateManagedWidget ("NEXT", commandWidgetClass,
1376 XtAddCallback (NEXT, XtNcallback, GlyphProc, (XtPointer) 2);
1377 XtSetArg (arg[0], XtNlabel, ">| (l)");
1378 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (LAST_action));
1379 LAST = XtCreateManagedWidget ("LAST", commandWidgetClass,
1381 XtAddCallback (LAST, XtNcallback, GlyphProc, (XtPointer) 3);
1383 XtSetArg (arg[0], XtNleft, XawChainLeft);
1384 XtSetArg (arg[1], XtNright, XawChainLeft);
1385 XtSetArg (arg[2], XtNtop, XawChainTop);
1386 XtSetArg (arg[3], XtNbottom, XawChainTop);
1388 for (i = 0; i < 8; i++)
1394 sprintf (str, "%XX", i);
1395 XtSetArg (arg[n], XtNheight, glyph_height + 5), n++;
1396 XtSetArg (arg[n], XtNlabel, str), n++;
1397 XtSetArg (arg[n], XtNborderWidth, 0), n++;
1399 XtSetArg (arg[n], XtNfromVert, w), n++;
1400 head = XtCreateManagedWidget (str, labelWidgetClass, glyph_area, arg, n);
1401 index_label[i] = head;
1402 for (j = 0; j < 16; j++)
1408 XtSetArg (arg[n], XtNfromVert, w), n++;
1410 XtSetArg (arg[n], XtNfromHoriz, head), n++;
1412 XtSetArg (arg[n], XtNfromHoriz, glyph[k - 1]), n++;
1413 XtSetArg (arg[n], XtNbitmap, none_pixmap), n++;
1414 glyph[k] = XtCreateManagedWidget ("glyph", commandWidgetClass,
1415 glyph_area, arg, n);
1416 XtAddCallbackWithCast (int, glyph[k], RenderProc, k);
1420 /* 10 = (1 (border_width) + 4 (inner_width)) * 2 */
1421 XtSetArg(arg[4], XtNwidth, glyph_width + 10);
1422 XtSetArg (arg[5], XtNfromVert, glyph[112]);
1423 XtSetArg (arg[6], XtNfromHoriz, w);
1424 XtSetArg (arg[7], XtNborderWidth, 0);
1426 for (j = 0; j < 16; j++)
1430 sprintf (str, "X%X", j);
1431 XtSetArg (arg[8], XtNlabel, str);
1432 w = XtCreateManagedWidget ("idx", labelWidgetClass, glyph_area, arg, 9);
1433 XtSetArg (arg[6], XtNfromHoriz, w);
1436 XtSetArg (arg[0], XtNleft, XawChainLeft);
1437 XtSetArg (arg[1], XtNright, XawChainLeft);
1438 XtSetArg (arg[2], XtNtop, XawChainTop);
1439 XtSetArg (arg[3], XtNbottom, XawChainTop);
1440 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1441 XtSetArg (arg[5], XtNborderWidth, 0);
1442 w = XtCreateManagedWidget ("clear-box", boxWidgetClass, render_area, arg, 6);
1443 clear = XtCreateManagedWidget ("clear", commandWidgetClass, w, arg, 0);
1444 XtAddCallback (clear, XtNcallback, RenderProc, (XtPointer) -1);
1445 del = XtCreateManagedWidget ("delete", commandWidgetClass, w, arg, 0);
1446 XtAddCallback (del, XtNcallback, RenderProc, (XtPointer) -2);
1447 bidi = XtCreateManagedWidget ("L->R", toggleWidgetClass, w, arg, 0);
1448 XtAddCallback (bidi, XtNcallback, BidiProc, NULL);
1449 alt_subst = XtCreateManagedWidget ("AltSubst", toggleWidgetClass, w, arg, 0);
1450 XtAddCallback (alt_subst, XtNcallback, AltSubstProc, NULL);
1452 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1453 XtSetArg (arg[5], XtNborderWidth, 0);
1454 XtSetArg (arg[6], XtNfromVert, w);
1455 raw = XtCreateManagedWidget ("raw", boxWidgetClass, render_area, arg, 7);
1457 XtSetArg (arg[0], XtNborderWidth, 0);
1458 XtSetArg (arg[1], XtNlabel, "raw: ");
1459 raw_label = XtCreateManagedWidget ("raw-label", labelWidgetClass,
1461 XtSetArg (arg[1], XtNbitmap, raw_pixmap);
1462 raw_image = XtCreateManagedWidget ("raw-image", labelWidgetClass,
1467 OTF_get_table (otf, "GSUB");
1468 OTF_get_table (otf, "GPOS");
1469 w = create_otf_script_widgets (w);
1472 gsub.label = "GSUB";
1473 gsub.gsub_gpos = otf->gsub;
1474 w = create_otf_widgets (w, &gsub);
1478 gpos.label = "GPOS";
1479 gpos.gsub_gpos = otf->gpos;
1480 w = create_otf_widgets (w, &gpos);
1484 XtSetArg (arg[6], XtNfromVert, w);
1485 seq = XtCreateManagedWidget ("seq", boxWidgetClass, render_area, arg, 7);
1486 XtSetArg (arg[0], XtNborderWidth, 0);
1487 XtSetArg (arg[1], XtNlabel, "seq: ");
1488 seq_label = XtCreateManagedWidget ("seq-label", labelWidgetClass,
1490 XtSetArg (arg[1], XtNbitmap, seq_pixmap);
1491 seq_image = XtCreateManagedWidget ("seq-image", labelWidgetClass,
1493 XtSetArg (arg[6], XtNfromVert, seq);
1494 code = XtCreateManagedWidget ("code", boxWidgetClass, render_area, arg, 7);
1495 XtSetArg (arg[0], XtNborderWidth, 0);
1496 XtSetArg (arg[1], XtNlabel, "code:");
1497 code_label = XtCreateManagedWidget ("code-label", labelWidgetClass,
1499 XtSetArg (arg[1], XtNlabel, "");
1500 XtSetArg (arg[2], XtNwidth, render_width);
1501 code_list = XtCreateManagedWidget ("code-list", labelWidgetClass,
1503 XtInstallAllAccelerators (shell, shell);
1507 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1509 XTextProperty text_prop;
1510 char *pname = "otfview";
1511 char *fname = basename (filename);
1512 char *name = alloca (strlen (fname) + 3 + strlen (pname) + 1);
1514 sprintf (name, "%s - %s", pname, fname);
1515 text_prop.value = (unsigned char *) name;
1516 text_prop.encoding = XA_STRING;
1517 text_prop.format = 8;
1518 text_prop.nitems = strlen (name);
1519 XSetWMName (display, XtWindow (shell), &text_prop);
1522 /* Format MSG by FMT and print the result to the stderr, and exit. */
1524 #define FATAL_ERROR(fmt, arg) \
1526 fprintf (stderr, fmt, arg); \
1531 x_error_handler (Display *display, XErrorEvent *error)
1537 help (char **argv, int err)
1539 FILE *fp = err ? stderr : stdout;
1541 fprintf (fp, "Usage: %s [ X-OPTION ... ] OTF-FILE [INDEX]\n",
1542 basename (argv[0]));
1543 fprintf (fp, " Environment variable PIXEL_SIZE specifies the pixel size.\n");
1544 fprintf (fp, " The default pixel size is %d, but is reduced\n",
1545 DEFAULT_PIXEL_SIZE);
1546 fprintf (fp, " if your screen is not that wide.\n");
1551 main (int argc, char **argv)
1553 XtActionsRec actions[] = { {"Expose", ExposeProc} };
1557 OTF_GlyphString gstring;
1562 int fixed_pixel_size = 0;
1565 pixel_size = DEFAULT_PIXEL_SIZE;
1567 char *str = getenv ("PIXEL_SIZE");
1569 if (str && (i = atoi (str)) > 0)
1572 fixed_pixel_size = 1;
1576 gstring.size = gstring.used = 256;
1577 g = calloc (256, sizeof (OTF_Glyph));
1580 shell = XtOpenApplication (&context, "OTFView", NULL, 0, &argc, argv, NULL,
1581 shellWidgetClass, arg, 0);
1582 display = XtDisplay (shell);
1583 /*XSynchronize (display, True);*/
1584 XSetErrorHandler (x_error_handler);
1585 display_width = DisplayWidth (display,
1586 XScreenNumberOfScreen (XtScreen (shell)));
1587 font = XLoadQueryFont (display, DEFAULT_FONT_NAME);
1589 font = XLoadQueryFont (display, "fixed");
1593 if (!strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
1598 fontindex = atoi (argv[2]);
1600 FATAL_ERROR ("Invalid font index: %d\n", fontindex);
1603 if ((err = FT_Init_FreeType (&library)))
1604 FATAL_ERROR ("%s\n", "FT_Init_FreeType: error");
1605 err = FT_New_Face (library, filename, fontindex, &face);
1606 if (err == FT_Err_Unknown_File_Format)
1607 FATAL_ERROR ("%s\n", "FT_New_Face: unknown file format");
1609 FATAL_ERROR ("%s\n", "FT_New_Face: unknown error (invalid face index?)");
1610 if ((err = FT_Set_Pixel_Sizes (face, 0, pixel_size)))
1611 FATAL_ERROR ("%s\n", "FT_Set_Pixel_Sizes: error");
1613 if (strstr (filename, ".ttf")
1614 || strstr (filename, ".TTF")
1615 || strstr (filename, ".otf")
1616 || strstr (filename, ".OTF"))
1618 otf = OTF_open_ft_face (face);
1621 if (OTF_get_table (otf, "head") < 0
1622 || OTF_get_table (otf, "cmap") < 0
1623 || (OTF_check_table (otf, "GSUB") < 0
1624 && OTF_check_table (otf, "GPOS") < 0))
1631 for (i = 0; i < otf->cmap->numTables; i++)
1632 if (otf->cmap->EncodingRecord[i].subtable.format == 14)
1634 sub14 = otf->cmap->EncodingRecord[i].subtable.f.f14;
1643 filename = basename (filename);
1644 sprintf (title, "%s family:%s style:%s",
1645 filename, face->family_name, face->style_name);
1646 XtSetArg (arg[0], XtNtitle, title);
1647 XtSetValues (shell, arg, 1);
1650 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1651 * pixel_size / face->units_per_EM);
1652 if (! fixed_pixel_size && glyph_width * 16 > display_width * 0.8)
1654 pixel_size = (pixel_size * display_width * 0.8 / 16 / glyph_width);
1655 FT_Set_Pixel_Sizes (face, 0, pixel_size);
1656 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1657 * pixel_size / face->units_per_EM);
1659 if (glyph_width < FONT_WIDTH * 4)
1660 glyph_width = FONT_WIDTH * 4;
1662 glyph_height = ((face->bbox.yMax - face->bbox.yMin)
1663 * pixel_size / face->units_per_EM);
1665 glyph_x = - (face->bbox.xMin * pixel_size / face->units_per_EM);
1666 glyph_y = face->bbox.yMax * pixel_size / face->units_per_EM;
1667 none_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1668 glyph_width, glyph_height, 1);
1671 unsigned long valuemask = GCFunction | GCLineWidth;
1674 gc = XCreateGC (display, none_pixmap, (unsigned long) 0, NULL);
1675 XSetFont (display, gc, font->fid);
1676 values.function = GXset;
1677 values.line_width = 1;
1678 gc_set = XCreateGC (display, none_pixmap, valuemask, &values);
1679 XSetFont (display, gc_set, font->fid);
1680 values.function = GXor;
1681 gc_or = XCreateGC (display, none_pixmap, valuemask, &values);
1682 values.function = GXcopyInverted;
1683 gc_inv = XCreateGC (display, none_pixmap, valuemask, &values);
1686 XFillRectangle (display, none_pixmap, gc, 0, 0,
1687 glyph_width, glyph_height);
1688 XDrawString (display, none_pixmap, gc_inv,
1689 (glyph_width - XTextWidth (font, "none", 4)) / 2,
1690 glyph_height / 2, "none", 4);
1692 render_width = (glyph_width + 4) * 15 + 1;
1693 render_height = glyph_height + 2;
1695 charmap_rec[0].platform_id = -1;
1696 charmap_rec[0].encoding_id = -1;
1697 strcpy (charmap_rec[0].name, "no charmap");
1699 for (i = 0; i < face->num_charmaps; i++)
1701 charmap_rec[i + 1].platform_id = face->charmaps[i]->platform_id;
1702 charmap_rec[i + 1].encoding_id = face->charmaps[i]->encoding_id;
1703 sprintf (charmap_rec[i + 1].name, "%d-%d",
1704 charmap_rec[i + 1].platform_id, charmap_rec[i + 1].encoding_id);
1705 if (face->charmaps[i]->platform_id == 0
1706 || (face->charmaps[i]->platform_id == 3
1707 && face->charmaps[i]->encoding_id == 1))
1708 strcat (charmap_rec[i + 1].name, " (unicode)");
1709 else if (face->charmaps[i]->platform_id == 1
1710 && face->charmaps[i]->encoding_id == 0)
1711 strcat (charmap_rec[i + 1].name, " (apple-roman)");
1714 raw_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1715 render_width, render_height, 1);
1716 seq_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1717 render_width, render_height, 1);
1719 memset (bitmap, 0, sizeof (bitmap));
1723 update_glyph_area ();
1724 update_render_area ();
1726 XtAppAddActions (context, actions, XtNumber (actions));
1727 XtRealizeWidget (shell);
1728 XtAppMainLoop (context);
1733 #else /* not HAVE_X11_XAW_COMMAND_H */
1736 main (int argc, char **argv)
1739 "Building of this program failed (lack of some header files)\n");