1 /* otfview.c -- View glyphs of OpenType fonts.
3 Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010
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)
301 for (i = n = 0; i < rec->langsys->FeatureCount; i++)
302 if (rec->features[i].on)
306 str = malloc (n * 5);
307 for (i = 0, p = str; i < rec->langsys->FeatureCount; i++)
308 if (rec->features[i].on)
310 OTF_tag_name (rec->features[i].tag, p);
319 #define DEVICE_DELTA(table, size) \
320 (((table).DeltaValue \
321 && ((size) >= (table).StartSize && (size) <= (table).EndSize)) \
322 ? (table).DeltaValue[(size) >= (table).StartSize] \
326 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
327 OTF_Glyph *g, int *x, int *y)
329 if (anchor->AnchorFormat == 2)
332 int ap = anchor->f.f1.AnchorPoint;
334 FT_Load_Glyph (ft_face, (FT_UInt) g->glyph_id, FT_LOAD_MONOCHROME);
335 outline = &ft_face->glyph->outline;
336 if (ap < outline->n_points)
338 *x = outline->points[ap].x;
339 *y = outline->points[ap].y;
342 else if (anchor->AnchorFormat == 3)
344 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, pixel_size);
345 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, pixel_size);
353 OTF_GlyphString gstring;
354 OTF_Glyph *g, *prev, *base, *mark;
356 int len = glyph_rec.n_glyphs;
358 int unitsPerEm = face->units_per_EM;
362 gstring.size = gstring.used = len;
363 gstring.glyphs = malloc (sizeof (OTF_Glyph) * len);
364 memset (gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
365 for (i = 0; i < len; i++)
367 gstring.glyphs[i].c = glyph_rec.codes[i];
368 if (charmap_index < 0)
369 gstring.glyphs[i].glyph_id = glyph_rec.glyphs[i];
372 XFillRectangle (display, seq_pixmap, gc, 0, 0, render_width, render_height);
373 XDrawLine (display, seq_pixmap, gc_set, 0, glyph_y, render_width, glyph_y);
376 char *script_name = NULL, *langsys_name = NULL, buf[10];
382 OTF_tag_name (script_tag, script_name);
386 langsys_name = buf + 5;
387 OTF_tag_name (langsys_tag, langsys_name);
390 OTF_drive_cmap (otf, &gstring);
391 OTF_drive_gdef (otf, &gstring);
394 str = get_features (&otf->gsub->FeatureList, &gsub);
397 if (do_alternate_subst)
398 OTF_drive_gsub_alternate (otf, &gstring,
399 script_name, langsys_name, str);
402 OTF_drive_gsub_with_log (otf, &gstring,
403 script_name, langsys_name, str);
404 logsize = gstring.used * 2;
405 log = alloca (sizeof (OTF_Tag) * logsize);
406 for (i = 0; i < gstring.used; i++)
408 int idx = gstring.glyphs[i].positioning_type >> 4;
410 log[i] = otf->gsub->FeatureList.Feature[idx - 1].FeatureTag;
420 str = get_features (&otf->gpos->FeatureList, &gpos);
423 OTF_drive_gpos_with_log (otf, &gstring,
424 script_name, langsys_name, str);
427 if (logsize < gstring.used)
429 OTF_Tag *log2 = alloca (sizeof (OTF_Tag) * gstring.used);
430 memset (log2, 0, sizeof (OTF_Tag) * gstring.used);
431 memcpy (log2, log, sizeof (OTF_Tag) * logsize);
432 logsize = gstring.used;
438 logsize = gstring.used;
439 log = alloca (sizeof (OTF_Tag) * logsize);
440 memset (log, 0, sizeof (OTF_Tag) * logsize);
442 for (i = 0; i < gstring.used; i++)
444 int idx = gstring.glyphs[i].positioning_type >> 4;
446 log[i] = otf->gpos->FeatureList.Feature[idx - 1].FeatureTag;
459 for (prev = gstring.glyphs, g = gstring.glyphs + gstring.used - 1;
460 prev < g; prev++, g--)
461 temp = *prev, *prev = *g, *g = temp;
462 for (g = gstring.glyphs; g < gstring.glyphs + gstring.used; g++)
463 if (g->GlyphClass == 3)
467 while (g < gstring.glyphs + gstring.used && g->GlyphClass == 3)
469 for (g0 = g; prev < g0; prev++, g0--)
470 temp = *prev, *prev = *g, *g = temp;
476 for (i = 0, x = glyph_x, prev = NULL, g = gstring.glyphs;
477 i < gstring.used; i++, prev = g++)
479 BitmapRec *bmp = bitmap + gstring.glyphs[i].glyph_id;
480 int xoff = 0, yoff = 0;
482 int advance = bmp->advance;
484 if (gstring.glyphs[i].glyph_id && ! bmp->pixmap)
486 create_pixmap (gstring.glyphs[i].glyph_id);
489 advance = bmp->advance;
491 if (g->positioning_type & 0xF)
495 switch (g->positioning_type & 0xF)
499 int format = g->f.f1.format;
501 if (format & OTF_XPlacement)
502 xoff += g->f.f1.value->XPlacement * pixel_size / unitsPerEm;
503 if (format & OTF_XPlaDevice)
504 xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, pixel_size);
505 if (format & OTF_YPlacement)
506 yoff += g->f.f1.value->YPlacement * pixel_size / unitsPerEm;
507 if (format & OTF_YPlaDevice)
508 yoff += DEVICE_DELTA (g->f.f1.value->YPlaDevice, pixel_size);
509 if (format & OTF_XAdvance)
510 advance += g->f.f1.value->XAdvance * pixel_size / unitsPerEm;
511 if (format & OTF_XAdvDevice)
512 advance += DEVICE_DELTA (g->f.f1.value->XAdvDevice,
518 /* Not yet supported. */
524 prev_width = base_width;
525 goto label_adjust_anchor;
526 default: /* i.e. case 6 */
533 int base_x, base_y, mark_x, mark_y;
535 base_x = g->f.f4.base_anchor->XCoordinate * pixel_size / unitsPerEm;
536 base_y = g->f.f4.base_anchor->YCoordinate * pixel_size / unitsPerEm;
537 mark_x = g->f.f4.mark_anchor->XCoordinate * pixel_size / unitsPerEm;
538 mark_y = g->f.f4.mark_anchor->YCoordinate * pixel_size / unitsPerEm;
540 if (g->f.f4.base_anchor->AnchorFormat != 1)
541 adjust_anchor (g->f.f4.base_anchor, face, prev, &base_x, &base_y);
542 if (g->f.f4.mark_anchor->AnchorFormat != 1)
543 adjust_anchor (g->f.f4.mark_anchor, face, g, &mark_x, &mark_y);
544 xoff = (base_x - prev_width) - mark_x;
545 yoff = base_y - mark_y;
548 if (i + 1 == gstring.used
549 || gstring.glyphs[i + 1].glyph_id
550 || ! (gstring.glyphs[i + 1].positioning_type & 0xF))
556 XCopyArea (display, bmp->pixmap, seq_pixmap, gc_or,
557 glyph_x + bmp->x, glyph_y + bmp->y, bmp->width, bmp->height,
558 x + bmp->x + xoff, glyph_y + bmp->y - yoff);
561 if (g->GlyphClass == OTF_GlyphClass0)
562 base = mark = g, base_width = advance;
563 else if (g->GlyphClass == OTF_GlyphClassMark)
566 base = g, base_width = advance;
569 XtSetArg (arg[0], XtNbitmap, seq_pixmap);
570 XtSetValues (seq_image, arg, 1);
572 if (gstring.used > 0)
574 int size = render_width / FONT_WIDTH;
575 char *buf = alloca (size + 1);
578 sprintf (buf, "%04X", gstring.glyphs[0].glyph_id);
581 OTF_tag_name (log[0], name);
582 sprintf (buf + 4, " (%s)", name);
587 for (i = 1; i < gstring.used && x + 5 < size; i++, x += 5)
589 sprintf (buf + x, " %04X", gstring.glyphs[i].glyph_id);
590 if (log && log[i] && x + 11 < size)
592 OTF_tag_name (log[i], name);
593 sprintf (buf + x + 5, "(%s)", name);
600 XtSetArg (arg[0], XtNlabel, buf);
601 XtSetValues (code_list, arg, 1);
604 free (gstring.glyphs);
609 update_render_area ()
615 XFillRectangle (display, raw_pixmap, gc, 0, 0, render_width, render_height);
616 for (i = 0, x = glyph_x; i < glyph_rec.n_glyphs; i++)
618 if (glyph_rec.glyphs[i] >= 0)
620 BitmapRec *bmp = bitmap + glyph_rec.glyphs[i];
623 XCopyArea (display, bmp->pixmap, raw_pixmap, gc,
624 0, 0, glyph_width, glyph_height,
625 (glyph_width + 4) * i + 1, 1);
626 XDrawRectangle (display, raw_pixmap, gc_set,
627 (glyph_width + 4) * i, 0,
628 glyph_width + 1, glyph_height + 1);
629 XDrawLine (display, raw_pixmap, gc_set,
630 (glyph_width + 4) * i + 1 + glyph_x, 1,
631 (glyph_width + 4) * i + 1 + glyph_x, glyph_height + 1);
632 XDrawLine (display, raw_pixmap, gc_set,
633 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance, 1,
634 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance,
637 sprintf (buf, "%04X", glyph_rec.codes[i]);
638 XDrawString (display, raw_pixmap, gc_inv,
639 (glyph_width + 4) * i + 1
640 + (glyph_width - XTextWidth (font, buf, 4)) / 2,
641 glyph_height + 2 + FONT_HEIGHT, buf, 4);
645 /* Variation Selector */
646 int idx = - glyph_rec.glyphs[i];
649 sprintf (buf, "%03d", idx);
650 XDrawRectangle (display, raw_pixmap, gc_set,
651 (glyph_width + 4) * i, 0,
652 glyph_width + 1, glyph_height + 1);
653 XDrawString (display, raw_pixmap, gc_set,
654 (glyph_width + 4) * i + 1
655 + (glyph_width - XTextWidth (font, "VS", 2)) / 2,
656 1 + glyph_height / 2, "VS", 2);
657 XDrawString (display, raw_pixmap, gc_set,
658 (glyph_width + 4) * i + 1
659 + (glyph_width - XTextWidth (font, buf, 3)) / 2,
660 1 + glyph_height / 2 + FONT_ASCENT, buf, 3);
663 XtSetArg (arg[0], XtNbitmap, raw_pixmap);
664 XtSetValues (raw_image, arg, 1);
669 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
671 XtAppSetExitFlag (XtWidgetToApplicationContext (w));
675 DumpProc (Widget w, XtPointer client_data, XtPointer call_data)
677 int g_width, g_height;
679 /* unit in points (1/72 inch); to fit in both US-letter and A4 */
680 static int xoff = 30, yoff = 30;
681 static int unit = 30;
682 static int margin = 2;
683 static int title_height = 20, label_height = 10;
684 int total_width = (unit + margin * 2) * 16;
685 int total_height = (unit + margin * 2 + label_height) * 16 + title_height;
686 /* pixel size (dots) */
689 char *name = alloca (strlen (filename) + 10);
691 int index = (glyph_index / 0x100) * 0x100;
694 g_width = face->bbox.xMax - face->bbox.xMin;
695 g_height = face->bbox.yMax - face->bbox.yMin;
696 if (g_width > g_height)
698 scale = g_width * size;
699 g_x = face->bbox.xMin * unit / g_width;
700 g_y = face->bbox.yMin * unit / g_width;
704 scale = g_height * size;
705 g_x = face->bbox.xMin * unit / g_height;
706 g_y = face->bbox.yMin * unit / g_height;
708 scale /= face->units_per_EM;
710 FT_Set_Pixel_Sizes (face, 0, size);
712 sprintf (name, "%s-%04X.ps", face->family_name, index);
713 printf ("Writing %s ... ", name);
715 fp = fopen (name, "w");
717 fprintf (fp, "%s\n", "%!PS-Adobe-2.0 EPSF-2.0");
718 fprintf (fp, "%s\n", "%%Creater: otfview");
719 fprintf (fp, "%s %s(%s)-%04X\n", "%%Title:",
720 face->family_name, face->style_name, index);
721 fprintf (fp, "%s\n", "%%Pages: 1");
722 fprintf (fp, "%s %d %d %d %d\n", "%%BoundingBox:",
723 xoff, yoff, xoff + total_width, yoff + total_height);
724 fprintf (fp, "%s\n", "%%EndComments");
725 fprintf (fp, "%s\n", "%%BeginProlog");
726 fprintf (fp, "/W %d def\n", unit + margin * 2);
727 fprintf (fp, "/H %d def\n", unit + margin * 2 + label_height);
728 fprintf (fp, "/STR 10 string def\n");
729 fprintf (fp, "/DrawIndex {\n");
730 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");
731 fprintf (fp, "} def\n");
732 fprintf (fp, "/DrawTitle {\n");
733 fprintf (fp, " /Courier findfont 20 scalefont setfont\n");
734 fprintf (fp, " %d %d 4 add moveto\n", xoff + total_width / 2,
735 yoff + total_height - title_height + 2);
736 fprintf (fp, " (%s(%s)-%04X) dup stringwidth pop 2 div neg 0 rmoveto show\n",
737 face->family_name, face->style_name, index);
738 fprintf (fp, "} def\n");
739 fprintf (fp, "/DrawFrame { gsave %d %d translate 0 setlinewidth\n",
741 fprintf (fp, " /Courier findfont 10 scalefont setfont\n");
742 fprintf (fp, " /I %d def\n", index);
743 fprintf (fp, " 0 1 16 { W mul 0 moveto 0 H 16 mul rlineto stroke } for\n");
744 fprintf (fp, " 0 1 16 { H mul 0 exch moveto W 16 mul 0 rlineto stroke } for\n");
745 fprintf (fp, " 0 1 15 { H mul %d add 0 exch moveto W 16 mul 0 rlineto stroke } for\n", label_height);
746 fprintf (fp, " 15 -1 0 { gsave H mul 0 exch translate 0 0 moveto\n");
747 fprintf (fp, " 0 1 15 { gsave W mul 0 moveto\n");
748 fprintf (fp, " 4 2 rmoveto DrawIndex /I I 1 add def grestore} for\n");
749 fprintf (fp, " grestore } for grestore } def\n");
750 fprintf (fp, "%s\n", "%%EndProlog");
751 fprintf (fp, "DrawTitle DrawFrame\n");
753 for (i = 0; i < 16; i++)
754 for (j = 0; j < 16; j++, index++)
758 if (charmap_index >= 0)
759 idx = FT_Get_Char_Index (face, (FT_ULong) index);
763 && FT_Load_Glyph (face, idx, FT_LOAD_RENDER | FT_LOAD_MONOCHROME) == 0
764 && face->glyph->bitmap.rows > 0
765 && face->glyph->bitmap.width > 0)
767 unsigned char *p = face->glyph->bitmap.buffer;
768 int width = (face->glyph->bitmap.width - 1) / 8 + 1;
770 fprintf (fp, "gsave %f %f translate %d %d scale 0 0 moveto\n",
771 xoff + (unit + margin * 2) * j + margin - g_x,
772 yoff + (unit + label_height + margin * 2) * (15 - i) + label_height + margin - g_y,
774 fprintf (fp, "%d %d true [%f 0 0 %f %d %d]\n",
775 width * 8, face->glyph->bitmap.rows,
776 scale, -scale, -face->glyph->bitmap_left,
777 face->glyph->bitmap_top);
779 for (k = 0; k < face->glyph->bitmap.rows;
780 k++, p += face->glyph->bitmap.pitch)
782 for (l = 0; l < width; l++)
783 fprintf (fp, "%02X", p[l]);
786 fprintf (fp, ">} imagemask grestore\n");
790 int boxsize = unit + margin * 2;
792 fprintf (fp, "gsave 0 setlinewidth %d %d translate\n",
794 yoff + (boxsize + label_height) * (15 - i) + label_height);
795 fprintf (fp, "0 0 moveto %d %d lineto stroke\n",
797 fprintf (fp, "0 %d moveto %d 0 lineto stroke grestore\n",
801 fprintf (fp, "showpage\n");
805 FT_Set_Pixel_Sizes (face, 0, (int) pixel_size);
810 GlyphProc (Widget w, XtPointer client_data, XtPointer call_data)
812 int old_glyph_index = glyph_index;
815 CAST_FROM_XTPOINTER (int, client_data, data);
817 if (data == -3 && glyph_index > 0)
819 else if (data == -2 && glyph_index > 0)
820 glyph_index = (glyph_index - 1) & 0x1FF000;
821 else if (data == -1 && glyph_index > 0)
823 else if (data == 1 && glyph_index < 0x10FF80)
825 else if (data == 2 && glyph_index < 0x10F000)
826 glyph_index = (glyph_index + 0x1000) & 0x1FF000;
827 else if (data == 3 && glyph_index < 0x10F000)
828 glyph_index = 0x10FF80;
829 if (glyph_index != old_glyph_index)
830 update_glyph_area ();
834 CharmapProc (Widget w, XtPointer client_data, XtPointer call_data)
838 CAST_FROM_XTPOINTER (int, client_data, data);
840 if (charmap_index == data)
842 charmap_index = data;
843 if (charmap_index >= 0)
844 FT_Set_Charmap (face, face->charmaps[charmap_index]);
845 update_glyph_area ();
849 UVSProc (Widget w, XtPointer client_data, XtPointer call_data)
853 OTF_VariationSelectorRecord *record;
856 CAST_FROM_XTPOINTER (unsigned, client_data, idx);
857 selector = uvs[idx].c;
859 if (glyph_rec.n_glyphs >= 64)
861 for (i = 0; i < sub14->nRecords; i++)
863 record = sub14->Records + i;
864 if (record->varSelector == selector)
867 if (i < sub14->nRecords)
869 if (glyph_rec.n_glyphs > 0
870 && glyph_rec.glyphs[glyph_rec.n_glyphs - 1] < 0)
871 glyph_rec.n_glyphs--;
872 glyph_rec.codes[glyph_rec.n_glyphs] = selector;
873 glyph_rec.glyphs[glyph_rec.n_glyphs++] = - idx - 1;
874 update_render_area ();
879 RenderProc (Widget w, XtPointer client_data, XtPointer call_data)
883 CAST_FROM_XTPOINTER (int, client_data, data);
887 if (glyph_rec.n_glyphs > 0)
890 glyph_rec.n_glyphs--;
892 glyph_rec.n_glyphs = 0;
893 update_render_area ();
896 else if (glyph_rec.n_glyphs < 64)
898 int index = glyph_index + data;
900 if (charmap_index >= 0)
901 index = FT_Get_Char_Index (face, (FT_ULong) index);
902 if (bitmap[index].pixmap)
904 glyph_rec.codes[glyph_rec.n_glyphs] = glyph_index + data;
905 glyph_rec.glyphs[glyph_rec.n_glyphs++] = index;
907 update_uvs_area (glyph_index + data);
908 update_render_area ();
914 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
918 reversed = ! reversed;
920 XtSetArg (arg[0], XtNlabel, "L<-R");
922 XtSetArg (arg[0], XtNlabel, "L->R");
923 XtSetValues (w, arg, 1);
928 AltSubstProc (Widget w, XtPointer client_data, XtPointer call_data)
930 do_alternate_subst = ! do_alternate_subst;
935 FeatureProc (Widget w, XtPointer client_data, XtPointer call_data)
937 FeatureRec *rec = (FeatureRec *) client_data;
944 XtSetArg (arg[0], XtNlabel, &label);
945 XtGetValues (w, arg, 1);
946 if (! strcmp (label, "all"))
948 else if (! strcmp (label, "none"))
952 for (idx = 0; idx < rec->langsys->FeatureCount; idx++)
953 if (rec->features[idx].w == w)
955 if (idx == rec->langsys->FeatureCount)
963 for (i = 0; i < rec->langsys->FeatureCount; i++)
964 if (rec->features[i].on != on)
966 rec->features[i].on = on;
969 XtSetArg (arg[0], XtNborderWidth, 3);
970 XtSetArg (arg[1], XtNinternalHeight, 2);
971 XtSetArg (arg[2], XtNinternalWidth, 2);
975 XtSetArg (arg[0], XtNborderWidth, 1);
976 XtSetArg (arg[1], XtNinternalHeight, 4);
977 XtSetArg (arg[2], XtNinternalWidth, 4);
979 OTF_tag_name (rec->features[i].tag, str);
980 XtSetArg (arg[3], XtNlabel, str);
981 XtSetValues (rec->features[i].w, arg, 4);
988 rec->features[idx].on = ! rec->features[idx].on;
989 if (rec->features[idx].on)
991 XtSetArg (arg[0], XtNborderWidth, 3);
992 XtSetArg (arg[1], XtNinternalHeight, 2);
993 XtSetArg (arg[2], XtNinternalWidth, 2);
997 XtSetArg (arg[0], XtNborderWidth, 1);
998 XtSetArg (arg[1], XtNinternalHeight, 4);
999 XtSetArg (arg[2], XtNinternalWidth, 4);
1001 OTF_tag_name (rec->features[idx].tag, str);
1002 XtSetArg (arg[3], XtNlabel, str);
1003 XtSetValues (rec->features[idx].w, arg, 4);
1009 setup_feature_rec (FeatureRec *rec)
1014 rec->langsys = NULL;
1015 if (! rec->gsub_gpos)
1017 for (i = 0; i < rec->gsub_gpos->ScriptList.ScriptCount; i++)
1018 if (rec->gsub_gpos->ScriptList.Script[i].ScriptTag == script_tag)
1020 OTF_Script *script = rec->gsub_gpos->ScriptList.Script + i;
1024 for (j = 0; j < script->LangSysCount; j++)
1025 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
1027 rec->langsys = script->LangSys + j;
1032 rec->langsys = &rec->gsub_gpos->ScriptList.Script[i].DefaultLangSys;
1040 XtSetArg (arg[0], XtNborderWidth, 1);
1041 XtSetArg (arg[1], XtNinternalHeight, 4);
1042 XtSetArg (arg[2], XtNinternalWidth, 4);
1043 XtSetArg (arg[3], XtNborderColor, foreground);
1044 XtSetArg (arg[4], XtNsensitive, True);
1045 for (i = 0; i < rec->langsys->FeatureCount; i++)
1047 OTF_Feature *feature = rec->gsub_gpos->FeatureList.Feature;
1048 int index = rec->langsys->FeatureIndex[i];
1051 if (! rec->features[i].w)
1053 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
1054 rec->parent, arg, 0);
1055 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1056 rec->features[i].w = w;
1059 rec->features[i].tag = feature[index].FeatureTag;
1060 rec->features[i].on = 0;
1061 OTF_tag_name (rec->features[i].tag, label);
1062 XtSetArg (arg[5], XtNlabel, label);
1063 XtSetValues (rec->features[i].w, arg, 6);
1066 XtSetArg (arg[0], XtNborderColor, background);
1067 XtSetArg (arg[1], XtNsensitive, False);
1068 XtSetArg (arg[2], XtNlabel, " ");
1069 for (; i < rec->num_features; i++)
1071 if (! rec->features[i].w)
1073 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
1074 rec->parent, arg, 0);
1075 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1076 rec->features[i].w = w;
1078 XtSetValues (rec->features[i].w, arg, 3);
1083 compose_script_langsys (OTF_Tag script, OTF_Tag langsys, char *name)
1085 OTF_tag_name (script, name);
1089 OTF_tag_name (langsys, name + 5);
1096 decompose_script_langsys (OTF_Tag *script, OTF_Tag *langsys, char *name)
1098 *script = OTF_tag (name);
1100 *langsys = OTF_tag (name + 5);
1106 ScriptProc (Widget w, XtPointer client_data, XtPointer call_data)
1109 OTF_Tag script, langsys;
1112 XtSetArg (arg[0], XtNlabel, &name);
1113 XtGetValues (w, arg, 1);
1114 decompose_script_langsys (&script, &langsys, name);
1115 if (script_tag == script && langsys_tag == langsys)
1117 script_tag = script;
1118 langsys_tag = langsys;
1119 setup_feature_rec (&gsub);
1120 setup_feature_rec (&gpos);
1125 create_otf_script_widgets (Widget prev)
1129 int n, prev_n, i, j;
1137 XtSetArg (arg[0], XtNborderWidth, 0);
1138 XtSetArg (arg[1], XtNleft, XawChainLeft);
1139 XtSetArg (arg[2], XtNright, XawChainLeft);
1140 XtSetArg (arg[3], XtNtop, XawChainTop);
1141 XtSetArg (arg[4], XtNbottom, XawChainTop);
1142 XtSetArg (arg[5], XtNfromVert, prev);
1143 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1144 prev = XtCreateManagedWidget ("Script", boxWidgetClass, render_area, arg, 7);
1145 XtCreateManagedWidget ("script(langsys)", labelWidgetClass, prev, arg, 1);
1149 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
1150 n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
1152 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
1153 n += otf->gpos->ScriptList.Script[i].LangSysCount + 1;
1154 script_langsys = alloca ((sizeof script_langsys[0]) * n);
1158 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
1160 OTF_Tag tag = otf->gsub->ScriptList.Script[i].ScriptTag;
1162 script_langsys[n].script = tag;
1163 script_langsys[n++].langsys = 0;
1165 < otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount)
1167 = otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount;
1168 for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
1170 script_langsys[n].script = tag;
1171 script_langsys[n++].langsys
1172 = otf->gsub->ScriptList.Script[i].LangSysRecord[j].LangSysTag;
1174 < otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount)
1176 = otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount;
1179 gsub.num_features = nfeatures;
1182 gsub.num_features = nfeatures;
1183 gsub.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1184 memset (gsub.features, 0, (sizeof (FeatureElement)) * nfeatures);
1189 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
1191 OTF_Tag tag = otf->gpos->ScriptList.Script[i].ScriptTag;
1195 < otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount)
1197 = otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount;
1198 for (k = 0; k < prev_n; k++)
1199 if (tag == script_langsys[k].script)
1203 script_langsys[n].script = tag;
1204 script_langsys[n++].langsys = 0;
1206 for (j = 0; j < otf->gpos->ScriptList.Script[i].LangSysCount; j++)
1212 OTF_Script *script = otf->gpos->ScriptList.Script + i;
1214 for (l = k; l < prev_n && tag == script_langsys[l].script; l++)
1215 if (script->LangSysRecord[j].LangSysTag
1216 == script_langsys[l].langsys)
1223 script_langsys[n].script = tag;
1224 script_langsys[n++].langsys = 0;
1227 < otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount)
1229 = otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount;
1235 gpos.num_features = nfeatures;
1236 gpos.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1237 memset (gpos.features, 0, (sizeof (FeatureElement)) * nfeatures);
1243 script_tag = script_langsys[0].script;
1244 langsys_tag = script_langsys[0].langsys;
1245 compose_script_langsys (script_tag, langsys_tag, name);
1249 XtSetArg (arg[0], XtNforeground, background);
1250 XtSetArg (arg[1], XtNbackground, foreground);
1251 XtCreateManagedWidget (name, labelWidgetClass, prev, arg, 2);
1255 XtSetArg (arg[0], XtNstate, True);
1256 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1257 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1258 XtSetArg (arg[0], XtNradioGroup, w);
1259 for (i = 1; i < n; i++)
1261 compose_script_langsys (script_langsys[i].script,
1262 script_langsys[i].langsys, name);
1263 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1264 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1272 create_otf_widgets (Widget prev, FeatureRec *rec)
1277 XtSetArg (arg[0], XtNborderWidth, 0);
1278 XtSetArg (arg[1], XtNleft, XawChainLeft);
1279 XtSetArg (arg[2], XtNright, XawChainLeft);
1280 XtSetArg (arg[3], XtNtop, XawChainTop);
1281 XtSetArg (arg[4], XtNbottom, XawChainTop);
1282 XtSetArg (arg[5], XtNfromVert, prev);
1283 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1284 prev = XtCreateManagedWidget (rec->label, boxWidgetClass, render_area,
1286 XtCreateManagedWidget (rec->label, labelWidgetClass, prev, arg, 1);
1287 XtSetArg (arg[0], XtNborderWidth, 1);
1288 XtSetArg (arg[1], XtNinternalHeight, 4);
1289 XtSetArg (arg[2], XtNinternalWidth, 4);
1290 w = XtCreateManagedWidget ("all", commandWidgetClass, prev, arg, 3);
1291 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1292 w = XtCreateManagedWidget ("none", commandWidgetClass, prev, arg, 3);
1293 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1296 setup_feature_rec (rec);
1303 String quit_action = "<KeyPress>q: set() notify() unset()";
1304 String FIRST_action = "<KeyPress>f: set() notify() unset()\n\
1305 <KeyPress>Home: set() notify() unset()";
1306 String PREV_action = "Shift<KeyPress>p: set() notify() unset()\n\
1307 <KeyPress>Up: set() notify() unset()";
1308 String prev_action = "~Shift<KeyPress>p: set() notify() unset()\n\
1309 <KeyPress>Left: set() notify() unset()";
1310 String next_action = "~Shift<KeyPress>n: set() notify() unset()\n\
1311 <KeyPress>Right: set() notify() unset()";
1312 String NEXT_action = "Shift<KeyPress>n: set() notify() unset()\n\
1313 <KeyPress>Down: set() notify() unset()";
1314 String LAST_action = "<KeyPress>l: set() notify() unset()\n\
1315 <KeyPress>End: set() notify() unset()";
1319 String trans = "<Expose>: Expose()";
1321 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans));
1322 frame = XtCreateManagedWidget ("frame", formWidgetClass, shell, arg, 1);
1324 XtSetArg (arg[0], XtNleft, XawChainLeft);
1325 XtSetArg (arg[1], XtNright, XawChainLeft);
1326 XtSetArg (arg[2], XtNtop, XawChainTop);
1327 XtSetArg (arg[3], XtNbottom, XawChainTop);
1328 XtSetArg (arg[4], XtNborderWidth, 0);
1329 XtSetArg (arg[5], XtNorientation, XtorientHorizontal);
1330 command_area = XtCreateManagedWidget ("command-area", boxWidgetClass,
1332 XtSetArg (arg[6], XtNfromVert, command_area);
1333 navi_area = XtCreateManagedWidget ("navi-area", boxWidgetClass,
1335 XtSetArg (arg[4], XtNborderWidth, 0);
1336 XtSetArg (arg[5], XtNfromVert, navi_area);
1337 XtSetArg (arg[6], XtNdefaultDistance, 0);
1338 glyph_area = XtCreateManagedWidget ("glyph-area", formWidgetClass,
1341 XtSetArg (arg[5], XtNfromVert, glyph_area);
1346 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1347 uvs_area = XtCreateManagedWidget ("uvs-area", boxWidgetClass,
1349 XtSetArg (arg2[0], XtNborderWidth, 0);
1350 XtSetArg (arg2[1], XtNlabel, "Variation Selector: ");
1351 uvs_label = XtCreateManagedWidget ("uvs-label", labelWidgetClass,
1353 XtSetArg (arg2[0], XtNborderWidth, 1);
1354 for (i = 0; i < sub14->nRecords; i++)
1356 OTF_VariationSelectorRecord *record = sub14->Records + i;
1357 unsigned selector = record->varSelector;
1361 idx = (selector <= 0xFE0F ? selector - 0xFE00
1362 : selector - 0xE0100 + 16);
1365 uvs[idx].c = selector;
1366 sprintf (lbl, "%03d", idx + 1);
1367 XtSetArg (arg2[1], XtNlabel, lbl);
1368 XtSetArg (arg2[2], XtNsensitive, False);
1369 uvs[idx].w = XtCreateManagedWidget ("lbl", commandWidgetClass,
1371 XtAddCallbackWithCast (unsigned, uvs[idx].w, UVSProc, idx);
1373 XtSetArg (arg[5], XtNfromVert, uvs_area);
1375 render_area = XtCreateManagedWidget ("render-area", formWidgetClass,
1378 XtSetArg (arg[0], XtNaccelerators, XtParseAcceleratorTable (quit_action));
1379 quit = XtCreateManagedWidget ("Quit", commandWidgetClass,
1380 command_area, arg, 1);
1381 XtAddCallback (quit, XtNcallback, QuitProc, NULL);
1383 dump = XtCreateManagedWidget ("DumpImage", commandWidgetClass,
1384 command_area, arg, 1);
1385 XtAddCallback (dump, XtNcallback, DumpProc, NULL);
1387 XtSetArg (arg[0], XtNborderWidth, 0);
1388 XtSetArg (arg[1], XtNwidth, 10);
1389 XtCreateManagedWidget ("spacer", boxWidgetClass, command_area, arg, 2);
1391 charmap = alloca (sizeof (Widget) * (face->num_charmaps + 1));
1392 XtSetArg (arg[0], XtNstate, True);
1393 charmap[0] = XtCreateManagedWidget (charmap_rec[0].name, toggleWidgetClass,
1394 command_area, arg, 1);
1395 XtAddCallback (charmap[0], XtNcallback, CharmapProc, (XtPointer) -1);
1396 XtSetArg (arg[0], XtNradioGroup, charmap[0]);
1397 for (i = 0; i < face->num_charmaps; i++)
1399 charmap[i + 1] = XtCreateManagedWidget (charmap_rec[i + 1].name,
1401 command_area, arg, 1);
1402 XtAddCallbackWithCast (int, charmap[i + 1], CharmapProc, i);
1405 XtSetArg (arg[0], XtNlabel, " |< (f)");
1406 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (FIRST_action));
1407 FIRST = XtCreateManagedWidget ("FIRST", commandWidgetClass,
1409 XtAddCallback (FIRST, XtNcallback, GlyphProc, (XtPointer) -3);
1410 XtSetArg (arg[0], XtNlabel, "<< (P)");
1411 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (PREV_action));
1412 PREV = XtCreateManagedWidget ("PREV", commandWidgetClass,
1414 XtAddCallback (PREV, XtNcallback, GlyphProc, (XtPointer) -2);
1415 XtSetArg (arg[0], XtNlabel, "< (p)");
1416 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (prev_action));
1417 prev = XtCreateManagedWidget ("prev", commandWidgetClass,
1419 XtAddCallback (prev, XtNcallback, GlyphProc, (XtPointer) -1);
1420 XtSetArg (arg[0], XtNlabel, " 0000 ");
1421 range = XtCreateManagedWidget ("range", labelWidgetClass,
1423 XtSetArg (arg[0], XtNforeground, &foreground);
1424 XtSetArg (arg[1], XtNbackground, &background);
1425 XtGetValues (range, arg, 2);
1427 XtSetArg (arg[0], XtNlabel, "> (n)");
1428 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (next_action));
1429 next = XtCreateManagedWidget ("next", commandWidgetClass,
1431 XtAddCallback (next, XtNcallback, GlyphProc, (XtPointer) 1);
1432 XtSetArg (arg[0], XtNlabel, ">> (N)");
1433 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (NEXT_action));
1434 NEXT = XtCreateManagedWidget ("NEXT", commandWidgetClass,
1436 XtAddCallback (NEXT, XtNcallback, GlyphProc, (XtPointer) 2);
1437 XtSetArg (arg[0], XtNlabel, ">| (l)");
1438 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (LAST_action));
1439 LAST = XtCreateManagedWidget ("LAST", commandWidgetClass,
1441 XtAddCallback (LAST, XtNcallback, GlyphProc, (XtPointer) 3);
1443 XtSetArg (arg[0], XtNleft, XawChainLeft);
1444 XtSetArg (arg[1], XtNright, XawChainLeft);
1445 XtSetArg (arg[2], XtNtop, XawChainTop);
1446 XtSetArg (arg[3], XtNbottom, XawChainTop);
1448 for (i = 0; i < 8; i++)
1454 sprintf (str, "%XX", i);
1455 XtSetArg (arg[n], XtNheight, glyph_height + 5), n++;
1456 XtSetArg (arg[n], XtNlabel, str), n++;
1457 XtSetArg (arg[n], XtNborderWidth, 0), n++;
1459 XtSetArg (arg[n], XtNfromVert, w), n++;
1460 head = XtCreateManagedWidget (str, labelWidgetClass, glyph_area, arg, n);
1461 index_label[i] = head;
1462 for (j = 0; j < 16; j++)
1468 XtSetArg (arg[n], XtNfromVert, w), n++;
1470 XtSetArg (arg[n], XtNfromHoriz, head), n++;
1472 XtSetArg (arg[n], XtNfromHoriz, glyph[k - 1]), n++;
1473 XtSetArg (arg[n], XtNbitmap, none_pixmap), n++;
1474 glyph[k] = XtCreateManagedWidget ("glyph", commandWidgetClass,
1475 glyph_area, arg, n);
1476 XtAddCallbackWithCast (int, glyph[k], RenderProc, k);
1480 /* 10 = (1 (border_width) + 4 (inner_width)) * 2 */
1481 XtSetArg(arg[4], XtNwidth, glyph_width + 10);
1482 XtSetArg (arg[5], XtNfromVert, glyph[112]);
1483 XtSetArg (arg[6], XtNfromHoriz, w);
1484 XtSetArg (arg[7], XtNborderWidth, 0);
1486 for (j = 0; j < 16; j++)
1490 sprintf (str, "X%X", j);
1491 XtSetArg (arg[8], XtNlabel, str);
1492 w = XtCreateManagedWidget ("idx", labelWidgetClass, glyph_area, arg, 9);
1493 XtSetArg (arg[6], XtNfromHoriz, w);
1496 XtSetArg (arg[0], XtNleft, XawChainLeft);
1497 XtSetArg (arg[1], XtNright, XawChainLeft);
1498 XtSetArg (arg[2], XtNtop, XawChainTop);
1499 XtSetArg (arg[3], XtNbottom, XawChainTop);
1500 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1501 XtSetArg (arg[5], XtNborderWidth, 0);
1502 w = XtCreateManagedWidget ("clear-box", boxWidgetClass, render_area, arg, 6);
1503 clear = XtCreateManagedWidget ("clear", commandWidgetClass, w, arg, 0);
1504 XtAddCallback (clear, XtNcallback, RenderProc, (XtPointer) -1);
1505 del = XtCreateManagedWidget ("delete", commandWidgetClass, w, arg, 0);
1506 XtAddCallback (del, XtNcallback, RenderProc, (XtPointer) -2);
1507 bidi = XtCreateManagedWidget ("L->R", toggleWidgetClass, w, arg, 0);
1508 XtAddCallback (bidi, XtNcallback, BidiProc, NULL);
1509 alt_subst = XtCreateManagedWidget ("AltSubst", toggleWidgetClass, w, arg, 0);
1510 XtAddCallback (alt_subst, XtNcallback, AltSubstProc, NULL);
1512 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1513 XtSetArg (arg[5], XtNborderWidth, 0);
1514 XtSetArg (arg[6], XtNfromVert, w);
1515 raw = XtCreateManagedWidget ("raw", boxWidgetClass, render_area, arg, 7);
1517 XtSetArg (arg[0], XtNborderWidth, 0);
1518 XtSetArg (arg[1], XtNlabel, "raw: ");
1519 raw_label = XtCreateManagedWidget ("raw-label", labelWidgetClass,
1521 XtSetArg (arg[1], XtNbitmap, raw_pixmap);
1522 raw_image = XtCreateManagedWidget ("raw-image", labelWidgetClass,
1527 OTF_get_table (otf, "GSUB");
1528 OTF_get_table (otf, "GPOS");
1529 w = create_otf_script_widgets (w);
1532 gsub.label = "GSUB";
1533 gsub.gsub_gpos = otf->gsub;
1534 w = create_otf_widgets (w, &gsub);
1538 gpos.label = "GPOS";
1539 gpos.gsub_gpos = otf->gpos;
1540 w = create_otf_widgets (w, &gpos);
1544 XtSetArg (arg[6], XtNfromVert, w);
1545 seq = XtCreateManagedWidget ("seq", boxWidgetClass, render_area, arg, 7);
1546 XtSetArg (arg[0], XtNborderWidth, 0);
1547 XtSetArg (arg[1], XtNlabel, "seq: ");
1548 seq_label = XtCreateManagedWidget ("seq-label", labelWidgetClass,
1550 XtSetArg (arg[1], XtNbitmap, seq_pixmap);
1551 seq_image = XtCreateManagedWidget ("seq-image", labelWidgetClass,
1553 XtSetArg (arg[6], XtNfromVert, seq);
1554 code = XtCreateManagedWidget ("code", boxWidgetClass, render_area, arg, 7);
1555 XtSetArg (arg[0], XtNborderWidth, 0);
1556 XtSetArg (arg[1], XtNlabel, "code:");
1557 code_label = XtCreateManagedWidget ("code-label", labelWidgetClass,
1559 XtSetArg (arg[1], XtNlabel, "");
1560 XtSetArg (arg[2], XtNwidth, render_width);
1561 code_list = XtCreateManagedWidget ("code-list", labelWidgetClass,
1563 XtInstallAllAccelerators (shell, shell);
1567 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1569 XTextProperty text_prop;
1570 char *pname = "otfview";
1571 char *fname = basename (filename);
1572 char *name = alloca (strlen (fname) + 3 + strlen (pname) + 1);
1574 sprintf (name, "%s - %s", pname, fname);
1575 text_prop.value = (unsigned char *) name;
1576 text_prop.encoding = XA_STRING;
1577 text_prop.format = 8;
1578 text_prop.nitems = strlen (name);
1579 XSetWMName (display, XtWindow (shell), &text_prop);
1582 /* Format MSG by FMT and print the result to the stderr, and exit. */
1584 #define FATAL_ERROR(fmt, arg) \
1586 fprintf (stderr, fmt, arg); \
1591 x_error_handler (Display *display, XErrorEvent *error)
1597 help (char **argv, int err)
1599 FILE *fp = err ? stderr : stdout;
1601 fprintf (fp, "Usage: %s [ X-OPTION ... ] OTF-FILE [INDEX]\n",
1602 basename (argv[0]));
1603 fprintf (fp, " Environment variable PIXEL_SIZE specifies the pixel size.\n");
1604 fprintf (fp, " The default pixel size is %d, but is reduced\n",
1605 DEFAULT_PIXEL_SIZE);
1606 fprintf (fp, " if your screen is not that wide.\n");
1611 main (int argc, char **argv)
1613 XtActionsRec actions[] = { {"Expose", ExposeProc} };
1617 OTF_GlyphString gstring;
1622 int fixed_pixel_size = 0;
1625 pixel_size = DEFAULT_PIXEL_SIZE;
1627 char *str = getenv ("PIXEL_SIZE");
1629 if (str && (i = atoi (str)) > 0)
1632 fixed_pixel_size = 1;
1636 gstring.size = gstring.used = 256;
1637 g = calloc (256, sizeof (OTF_Glyph));
1640 shell = XtOpenApplication (&context, "OTFView", NULL, 0, &argc, argv, NULL,
1641 shellWidgetClass, arg, 0);
1642 display = XtDisplay (shell);
1643 /*XSynchronize (display, True);*/
1644 XSetErrorHandler (x_error_handler);
1645 display_width = DisplayWidth (display,
1646 XScreenNumberOfScreen (XtScreen (shell)));
1647 font = XLoadQueryFont (display, DEFAULT_FONT_NAME);
1649 font = XLoadQueryFont (display, "fixed");
1653 if (!strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
1658 fontindex = atoi (argv[2]);
1660 FATAL_ERROR ("Invalid font index: %d\n", fontindex);
1663 if ((err = FT_Init_FreeType (&library)))
1664 FATAL_ERROR ("%s\n", "FT_Init_FreeType: error");
1665 err = FT_New_Face (library, filename, fontindex, &face);
1666 if (err == FT_Err_Unknown_File_Format)
1667 FATAL_ERROR ("%s\n", "FT_New_Face: unknown file format");
1669 FATAL_ERROR ("%s\n", "FT_New_Face: unknown error (invalid face index?)");
1670 if ((err = FT_Set_Pixel_Sizes (face, 0, pixel_size)))
1671 FATAL_ERROR ("%s\n", "FT_Set_Pixel_Sizes: error");
1673 if (strstr (filename, ".ttf")
1674 || strstr (filename, ".TTF")
1675 || strstr (filename, ".otf")
1676 || strstr (filename, ".OTF"))
1678 otf = OTF_open_ft_face (face);
1681 if (OTF_get_table (otf, "head") < 0
1682 || OTF_get_table (otf, "cmap") < 0
1683 || (OTF_check_table (otf, "GSUB") < 0
1684 && OTF_check_table (otf, "GPOS") < 0))
1691 for (i = 0; i < otf->cmap->numTables; i++)
1692 if (otf->cmap->EncodingRecord[i].subtable.format == 14)
1694 sub14 = otf->cmap->EncodingRecord[i].subtable.f.f14;
1703 filename = basename (filename);
1704 sprintf (title, "%s family:%s style:%s",
1705 filename, face->family_name, face->style_name);
1706 XtSetArg (arg[0], XtNtitle, title);
1707 XtSetValues (shell, arg, 1);
1710 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1711 * pixel_size / face->units_per_EM);
1712 if (! fixed_pixel_size && glyph_width * 16 > display_width * 0.8)
1714 pixel_size = (pixel_size * display_width * 0.8 / 16 / glyph_width);
1715 FT_Set_Pixel_Sizes (face, 0, pixel_size);
1716 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1717 * pixel_size / face->units_per_EM);
1719 if (glyph_width < FONT_WIDTH * 4)
1720 glyph_width = FONT_WIDTH * 4;
1722 glyph_height = ((face->bbox.yMax - face->bbox.yMin)
1723 * pixel_size / face->units_per_EM);
1725 glyph_x = - (face->bbox.xMin * pixel_size / face->units_per_EM);
1726 glyph_y = face->bbox.yMax * pixel_size / face->units_per_EM;
1727 none_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1728 glyph_width, glyph_height, 1);
1731 unsigned long valuemask = GCFunction | GCLineWidth;
1734 gc = XCreateGC (display, none_pixmap, (unsigned long) 0, NULL);
1735 XSetFont (display, gc, font->fid);
1736 values.function = GXset;
1737 values.line_width = 1;
1738 gc_set = XCreateGC (display, none_pixmap, valuemask, &values);
1739 XSetFont (display, gc_set, font->fid);
1740 values.function = GXor;
1741 gc_or = XCreateGC (display, none_pixmap, valuemask, &values);
1742 values.function = GXcopyInverted;
1743 gc_inv = XCreateGC (display, none_pixmap, valuemask, &values);
1746 XFillRectangle (display, none_pixmap, gc, 0, 0,
1747 glyph_width, glyph_height);
1748 XDrawString (display, none_pixmap, gc_inv,
1749 (glyph_width - XTextWidth (font, "none", 4)) / 2,
1750 glyph_height / 2, "none", 4);
1752 render_width = (glyph_width + 4) * 15 + 1;
1753 render_height = glyph_height + 2;
1755 charmap_rec[0].platform_id = -1;
1756 charmap_rec[0].encoding_id = -1;
1757 strcpy (charmap_rec[0].name, "no charmap");
1759 for (i = 0; i < face->num_charmaps; i++)
1761 charmap_rec[i + 1].platform_id = face->charmaps[i]->platform_id;
1762 charmap_rec[i + 1].encoding_id = face->charmaps[i]->encoding_id;
1763 sprintf (charmap_rec[i + 1].name, "%d-%d",
1764 charmap_rec[i + 1].platform_id, charmap_rec[i + 1].encoding_id);
1765 if (face->charmaps[i]->platform_id == 0
1766 || (face->charmaps[i]->platform_id == 3
1767 && face->charmaps[i]->encoding_id == 1))
1768 strcat (charmap_rec[i + 1].name, " (unicode)");
1769 else if (face->charmaps[i]->platform_id == 1
1770 && face->charmaps[i]->encoding_id == 0)
1771 strcat (charmap_rec[i + 1].name, " (apple-roman)");
1774 raw_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1775 render_width, render_height, 1);
1776 seq_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1777 render_width, render_height, 1);
1779 memset (bitmap, 0, sizeof (bitmap));
1783 update_glyph_area ();
1784 update_render_area ();
1786 XtAppAddActions (context, actions, XtNumber (actions));
1787 XtRealizeWidget (shell);
1788 XtAppMainLoop (context);
1793 #else /* not HAVE_X11_XAW_COMMAND_H */
1796 main (int argc, char **argv)
1799 "Building of this program failed (lack of some header files)\n");