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++)
303 if (rec->features[i].on)
308 str = malloc (n * 5);
309 for (i = 0, p = str; i < n; i++, p += 5)
311 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;
360 gstring.size = gstring.used = len;
361 gstring.glyphs = malloc (sizeof (OTF_Glyph) * len);
362 memset (gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
363 for (i = 0; i < len; i++)
365 gstring.glyphs[i].c = glyph_rec.codes[i];
366 if (charmap_index < 0)
367 gstring.glyphs[i].glyph_id = glyph_rec.glyphs[i];
370 XFillRectangle (display, seq_pixmap, gc, 0, 0, render_width, render_height);
371 XDrawLine (display, seq_pixmap, gc_set, 0, glyph_y, render_width, glyph_y);
374 char *script_name = NULL, *langsys_name = NULL, buf[10];
380 OTF_tag_name (script_tag, script_name);
384 langsys_name = buf + 5;
385 OTF_tag_name (langsys_tag, langsys_name);
388 OTF_drive_cmap (otf, &gstring);
389 OTF_drive_gdef (otf, &gstring);
392 str = get_features (&otf->gsub->FeatureList, &gsub);
395 if (do_alternate_subst)
396 OTF_drive_gsub_alternate (otf, &gstring,
397 script_name, langsys_name, str);
399 OTF_drive_gsub (otf, &gstring, script_name, langsys_name, str);
405 str = get_features (&otf->gpos->FeatureList, &gpos);
408 OTF_drive_gpos2 (otf, &gstring, script_name, langsys_name, str);
419 for (prev = gstring.glyphs, g = gstring.glyphs + gstring.used - 1;
420 prev < g; prev++, g--)
421 temp = *prev, *prev = *g, *g = temp;
422 for (g = gstring.glyphs; g < gstring.glyphs + gstring.used; g++)
423 if (g->GlyphClass == 3)
427 while (g < gstring.glyphs + gstring.used && g->GlyphClass == 3)
429 for (g0 = g; prev < g0; prev++, g0--)
430 temp = *prev, *prev = *g, *g = temp;
436 for (i = 0, x = glyph_x, prev = NULL, g = gstring.glyphs;
437 i < gstring.used; i++, prev = g++)
439 BitmapRec *bmp = bitmap + gstring.glyphs[i].glyph_id;
440 int xoff = 0, yoff = 0;
442 int advance = bmp->advance;
444 if (gstring.glyphs[i].glyph_id && ! bmp->pixmap)
446 create_pixmap (gstring.glyphs[i].glyph_id);
449 advance = bmp->advance;
451 if (g->positioning_type)
455 switch (g->positioning_type)
459 int format = g->f.f1.format;
461 if (format & OTF_XPlacement)
462 xoff += g->f.f1.value->XPlacement * pixel_size / unitsPerEm;
463 if (format & OTF_XPlaDevice)
464 xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, pixel_size);
465 if (format & OTF_YPlacement)
466 yoff += g->f.f1.value->YPlacement * pixel_size / unitsPerEm;
467 if (format & OTF_YPlaDevice)
468 yoff += DEVICE_DELTA (g->f.f1.value->YPlaDevice, pixel_size);
469 if (format & OTF_XAdvance)
470 advance += g->f.f1.value->XAdvance * pixel_size / unitsPerEm;
471 if (format & OTF_XAdvDevice)
472 advance += DEVICE_DELTA (g->f.f1.value->XAdvDevice,
478 /* Not yet supported. */
484 prev_width = base_width;
485 goto label_adjust_anchor;
486 default: /* i.e. case 6 */
493 int base_x, base_y, mark_x, mark_y;
495 base_x = g->f.f4.base_anchor->XCoordinate * pixel_size / unitsPerEm;
496 base_y = g->f.f4.base_anchor->YCoordinate * pixel_size / unitsPerEm;
497 mark_x = g->f.f4.mark_anchor->XCoordinate * pixel_size / unitsPerEm;
498 mark_y = g->f.f4.mark_anchor->YCoordinate * pixel_size / unitsPerEm;
500 if (g->f.f4.base_anchor->AnchorFormat != 1)
501 adjust_anchor (g->f.f4.base_anchor, face, prev, &base_x, &base_y);
502 if (g->f.f4.mark_anchor->AnchorFormat != 1)
503 adjust_anchor (g->f.f4.mark_anchor, face, g, &mark_x, &mark_y);
504 xoff = (base_x - prev_width) - mark_x;
505 yoff = base_y - mark_y;
508 if (i + 1 == gstring.used
509 || gstring.glyphs[i + 1].glyph_id
510 || ! gstring.glyphs[i + 1].positioning_type)
516 XCopyArea (display, bmp->pixmap, seq_pixmap, gc_or,
517 glyph_x + bmp->x, glyph_y + bmp->y, bmp->width, bmp->height,
518 x + bmp->x + xoff, glyph_y + bmp->y - yoff);
521 if (g->GlyphClass == OTF_GlyphClass0)
522 base = mark = g, base_width = advance;
523 else if (g->GlyphClass == OTF_GlyphClassMark)
526 base = g, base_width = advance;
529 XtSetArg (arg[0], XtNbitmap, seq_pixmap);
530 XtSetValues (seq_image, arg, 1);
532 if (gstring.used > 0)
534 char *buf = alloca (gstring.used * 5);
536 sprintf (buf, "%04X", gstring.glyphs[0].glyph_id);
537 for (i = 1; i < gstring.used; i++)
538 sprintf (buf + 4 + (i - 1) * 5, " %04X", gstring.glyphs[i].glyph_id);
539 XtSetArg (arg[0], XtNlabel, buf);
540 XtSetValues (code_list, arg, 1);
543 free (gstring.glyphs);
548 update_render_area ()
554 XFillRectangle (display, raw_pixmap, gc, 0, 0, render_width, render_height);
555 for (i = 0, x = glyph_x; i < glyph_rec.n_glyphs; i++)
557 if (glyph_rec.glyphs[i] >= 0)
559 BitmapRec *bmp = bitmap + glyph_rec.glyphs[i];
562 XCopyArea (display, bmp->pixmap, raw_pixmap, gc,
563 0, 0, glyph_width, glyph_height,
564 (glyph_width + 4) * i + 1, 1);
565 XDrawRectangle (display, raw_pixmap, gc_set,
566 (glyph_width + 4) * i, 0,
567 glyph_width + 1, glyph_height + 1);
568 XDrawLine (display, raw_pixmap, gc_set,
569 (glyph_width + 4) * i + 1 + glyph_x, 1,
570 (glyph_width + 4) * i + 1 + glyph_x, glyph_height + 1);
571 XDrawLine (display, raw_pixmap, gc_set,
572 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance, 1,
573 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance,
576 sprintf (buf, "%04X", glyph_rec.codes[i]);
577 XDrawString (display, raw_pixmap, gc_inv,
578 (glyph_width + 4) * i + 1
579 + (glyph_width - XTextWidth (font, buf, 4)) / 2,
580 glyph_height + 2 + FONT_HEIGHT, buf, 4);
584 /* Variation Selector */
585 int idx = - glyph_rec.glyphs[i];
588 sprintf (buf, "%03d", idx);
589 XDrawRectangle (display, raw_pixmap, gc_set,
590 (glyph_width + 4) * i, 0,
591 glyph_width + 1, glyph_height + 1);
592 XDrawString (display, raw_pixmap, gc_set,
593 (glyph_width + 4) * i + 1
594 + (glyph_width - XTextWidth (font, "VS", 2)) / 2,
595 1 + glyph_height / 2, "VS", 2);
596 XDrawString (display, raw_pixmap, gc_set,
597 (glyph_width + 4) * i + 1
598 + (glyph_width - XTextWidth (font, buf, 3)) / 2,
599 1 + glyph_height / 2 + FONT_ASCENT, buf, 3);
602 XtSetArg (arg[0], XtNbitmap, raw_pixmap);
603 XtSetValues (raw_image, arg, 1);
608 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
610 XtAppSetExitFlag (XtWidgetToApplicationContext (w));
614 DumpProc (Widget w, XtPointer client_data, XtPointer call_data)
616 int g_width, g_height;
618 /* unit in points (1/72 inch); to fit in both US-letter and A4 */
619 static int xoff = 30, yoff = 30;
620 static int unit = 30;
621 static int margin = 2;
622 static int title_height = 20, label_height = 10;
623 int total_width = (unit + margin * 2) * 16;
624 int total_height = (unit + margin * 2 + label_height) * 16 + title_height;
625 /* pixel size (dots) */
628 char *name = alloca (strlen (filename) + 10);
630 int index = (glyph_index / 0x100) * 0x100;
633 g_width = face->bbox.xMax - face->bbox.xMin;
634 g_height = face->bbox.yMax - face->bbox.yMin;
635 if (g_width > g_height)
637 scale = g_width * size;
638 g_x = face->bbox.xMin * unit / g_width;
639 g_y = face->bbox.yMin * unit / g_width;
643 scale = g_height * size;
644 g_x = face->bbox.xMin * unit / g_height;
645 g_y = face->bbox.yMin * unit / g_height;
647 scale /= face->units_per_EM;
649 FT_Set_Pixel_Sizes (face, 0, size);
651 sprintf (name, "%s-%04X.ps", face->family_name, index);
652 printf ("Writing %s ... ", name);
654 fp = fopen (name, "w");
656 fprintf (fp, "%s\n", "%!PS-Adobe-2.0 EPSF-2.0");
657 fprintf (fp, "%s\n", "%%Creater: otfview");
658 fprintf (fp, "%s %s(%s)-%04X\n", "%%Title:",
659 face->family_name, face->style_name, index);
660 fprintf (fp, "%s\n", "%%Pages: 1");
661 fprintf (fp, "%s %d %d %d %d\n", "%%BoundingBox:",
662 xoff, yoff, xoff + total_width, yoff + total_height);
663 fprintf (fp, "%s\n", "%%EndComments");
664 fprintf (fp, "%s\n", "%%BeginProlog");
665 fprintf (fp, "/W %d def\n", unit + margin * 2);
666 fprintf (fp, "/H %d def\n", unit + margin * 2 + label_height);
667 fprintf (fp, "/STR 10 string def\n");
668 fprintf (fp, "/DrawIndex {\n");
669 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");
670 fprintf (fp, "} def\n");
671 fprintf (fp, "/DrawTitle {\n");
672 fprintf (fp, " /Courier findfont 20 scalefont setfont\n");
673 fprintf (fp, " %d %d 4 add moveto\n", xoff + total_width / 2,
674 yoff + total_height - title_height + 2);
675 fprintf (fp, " (%s(%s)-%04X) dup stringwidth pop 2 div neg 0 rmoveto show\n",
676 face->family_name, face->style_name, index);
677 fprintf (fp, "} def\n");
678 fprintf (fp, "/DrawFrame { gsave %d %d translate 0 setlinewidth\n",
680 fprintf (fp, " /Courier findfont 10 scalefont setfont\n");
681 fprintf (fp, " /I %d def\n", index);
682 fprintf (fp, " 0 1 16 { W mul 0 moveto 0 H 16 mul rlineto stroke } for\n");
683 fprintf (fp, " 0 1 16 { H mul 0 exch moveto W 16 mul 0 rlineto stroke } for\n");
684 fprintf (fp, " 0 1 15 { H mul %d add 0 exch moveto W 16 mul 0 rlineto stroke } for\n", label_height);
685 fprintf (fp, " 15 -1 0 { gsave H mul 0 exch translate 0 0 moveto\n");
686 fprintf (fp, " 0 1 15 { gsave W mul 0 moveto\n");
687 fprintf (fp, " 4 2 rmoveto DrawIndex /I I 1 add def grestore} for\n");
688 fprintf (fp, " grestore } for grestore } def\n");
689 fprintf (fp, "%s\n", "%%EndProlog");
690 fprintf (fp, "DrawTitle DrawFrame\n");
692 for (i = 0; i < 16; i++)
693 for (j = 0; j < 16; j++, index++)
697 if (charmap_index >= 0)
698 idx = FT_Get_Char_Index (face, (FT_ULong) index);
702 && FT_Load_Glyph (face, idx, FT_LOAD_RENDER | FT_LOAD_MONOCHROME) == 0
703 && face->glyph->bitmap.rows > 0
704 && face->glyph->bitmap.width > 0)
706 unsigned char *p = face->glyph->bitmap.buffer;
707 int width = (face->glyph->bitmap.width - 1) / 8 + 1;
709 fprintf (fp, "gsave %f %f translate %d %d scale 0 0 moveto\n",
710 xoff + (unit + margin * 2) * j + margin - g_x,
711 yoff + (unit + label_height + margin * 2) * (15 - i) + label_height + margin - g_y,
713 fprintf (fp, "%d %d true [%f 0 0 %f %d %d]\n",
714 width * 8, face->glyph->bitmap.rows,
715 scale, -scale, -face->glyph->bitmap_left,
716 face->glyph->bitmap_top);
718 for (k = 0; k < face->glyph->bitmap.rows;
719 k++, p += face->glyph->bitmap.pitch)
721 for (l = 0; l < width; l++)
722 fprintf (fp, "%02X", p[l]);
725 fprintf (fp, ">} imagemask grestore\n");
729 int boxsize = unit + margin * 2;
731 fprintf (fp, "gsave 0 setlinewidth %d %d translate\n",
733 yoff + (boxsize + label_height) * (15 - i) + label_height);
734 fprintf (fp, "0 0 moveto %d %d lineto stroke\n",
736 fprintf (fp, "0 %d moveto %d 0 lineto stroke grestore\n",
740 fprintf (fp, "showpage\n");
744 FT_Set_Pixel_Sizes (face, 0, (int) pixel_size);
749 GlyphProc (Widget w, XtPointer client_data, XtPointer call_data)
751 int old_glyph_index = glyph_index;
754 CAST_FROM_XTPOINTER (int, client_data, data);
756 if (data == -3 && glyph_index > 0)
758 else if (data == -2 && glyph_index > 0)
759 glyph_index = (glyph_index - 1) & 0x1FF000;
760 else if (data == -1 && glyph_index > 0)
762 else if (data == 1 && glyph_index < 0x10FF80)
764 else if (data == 2 && glyph_index < 0x10F000)
765 glyph_index = (glyph_index + 0x1000) & 0x1FF000;
766 else if (data == 3 && glyph_index < 0x10F000)
767 glyph_index = 0x10FF80;
768 if (glyph_index != old_glyph_index)
769 update_glyph_area ();
773 CharmapProc (Widget w, XtPointer client_data, XtPointer call_data)
777 CAST_FROM_XTPOINTER (int, client_data, data);
779 if (charmap_index == data)
781 charmap_index = data;
782 if (charmap_index >= 0)
783 FT_Set_Charmap (face, face->charmaps[charmap_index]);
784 update_glyph_area ();
788 UVSProc (Widget w, XtPointer client_data, XtPointer call_data)
792 OTF_VariationSelectorRecord *record;
795 CAST_FROM_XTPOINTER (unsigned, client_data, idx);
796 selector = uvs[idx].c;
798 if (glyph_rec.n_glyphs >= 64)
800 for (i = 0; i < sub14->nRecords; i++)
802 record = sub14->Records + i;
803 if (record->varSelector == selector)
806 if (i < sub14->nRecords)
808 if (glyph_rec.n_glyphs > 0
809 && glyph_rec.glyphs[glyph_rec.n_glyphs - 1] < 0)
810 glyph_rec.n_glyphs--;
811 glyph_rec.codes[glyph_rec.n_glyphs] = selector;
812 glyph_rec.glyphs[glyph_rec.n_glyphs++] = - idx - 1;
813 update_render_area ();
818 RenderProc (Widget w, XtPointer client_data, XtPointer call_data)
822 CAST_FROM_XTPOINTER (int, client_data, data);
826 if (glyph_rec.n_glyphs > 0)
829 glyph_rec.n_glyphs--;
831 glyph_rec.n_glyphs = 0;
832 update_render_area ();
835 else if (glyph_rec.n_glyphs < 64)
837 int index = glyph_index + data;
839 if (charmap_index >= 0)
840 index = FT_Get_Char_Index (face, (FT_ULong) index);
841 if (bitmap[index].pixmap)
843 glyph_rec.codes[glyph_rec.n_glyphs] = glyph_index + data;
844 glyph_rec.glyphs[glyph_rec.n_glyphs++] = index;
846 update_uvs_area (glyph_index + data);
847 update_render_area ();
853 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
857 reversed = ! reversed;
859 XtSetArg (arg[0], XtNlabel, "L<-R");
861 XtSetArg (arg[0], XtNlabel, "L->R");
862 XtSetValues (w, arg, 1);
867 AltSubstProc (Widget w, XtPointer client_data, XtPointer call_data)
869 do_alternate_subst = ! do_alternate_subst;
874 FeatureProc (Widget w, XtPointer client_data, XtPointer call_data)
876 FeatureRec *rec = (FeatureRec *) client_data;
883 XtSetArg (arg[0], XtNlabel, &label);
884 XtGetValues (w, arg, 1);
885 if (! strcmp (label, "all"))
887 else if (! strcmp (label, "none"))
891 for (idx = 0; idx < rec->langsys->FeatureCount; idx++)
892 if (rec->features[idx].w == w)
894 if (idx == rec->langsys->FeatureCount)
901 for (i = j = 0; j < rec->langsys->FeatureCount; j++)
903 int index = rec->langsys->FeatureIndex[j];
906 = rec->gsub_gpos->FeatureList.Feature[index].FeatureTag;
907 rec->features[j].on = on;
912 OTF_Tag tag = rec->features[idx].tag;
915 if (rec->features[i].on)
918 j < rec->langsys->FeatureCount && rec->features[j].on; j++)
919 rec->features[j - 1].tag = rec->features[j].tag;
920 rec->features[j - 1].tag = tag;
921 rec->features[j - 1].on = 0;
925 for (j = i + 1; i > 0 && ! rec->features[i - 1].on; i--)
926 rec->features[i].tag = rec->features[i - 1].tag;
927 rec->features[i].tag = tag;
928 rec->features[i].on = 1;
936 if (rec->features[i].on)
938 XtSetArg (arg[0], XtNborderWidth, 3);
939 XtSetArg (arg[1], XtNinternalHeight, 2);
940 XtSetArg (arg[2], XtNinternalWidth, 2);
944 XtSetArg (arg[0], XtNborderWidth, 1);
945 XtSetArg (arg[1], XtNinternalHeight, 4);
946 XtSetArg (arg[2], XtNinternalWidth, 4);
948 OTF_tag_name (rec->features[i].tag, str);
949 XtSetArg (arg[3], XtNlabel, str);
950 XtSetValues (rec->features[i].w, arg, 4);
956 setup_feature_rec (FeatureRec *rec)
962 if (! rec->gsub_gpos)
964 for (i = 0; i < rec->gsub_gpos->ScriptList.ScriptCount; i++)
965 if (rec->gsub_gpos->ScriptList.Script[i].ScriptTag == script_tag)
967 OTF_Script *script = rec->gsub_gpos->ScriptList.Script + i;
971 for (j = 0; j < script->LangSysCount; j++)
972 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
974 rec->langsys = script->LangSys + j;
979 rec->langsys = &rec->gsub_gpos->ScriptList.Script[i].DefaultLangSys;
987 XtSetArg (arg[0], XtNborderWidth, 1);
988 XtSetArg (arg[1], XtNinternalHeight, 4);
989 XtSetArg (arg[2], XtNinternalWidth, 4);
990 XtSetArg (arg[3], XtNborderColor, foreground);
991 XtSetArg (arg[4], XtNsensitive, True);
992 for (i = 0; i < rec->langsys->FeatureCount; i++)
994 OTF_Feature *feature = rec->gsub_gpos->FeatureList.Feature;
995 int index = rec->langsys->FeatureIndex[i];
998 if (! rec->features[i].w)
1000 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
1001 rec->parent, arg, 0);
1002 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1003 rec->features[i].w = w;
1006 rec->features[i].tag = feature[index].FeatureTag;
1007 rec->features[i].on = 0;
1008 OTF_tag_name (rec->features[i].tag, label);
1009 XtSetArg (arg[5], XtNlabel, label);
1010 XtSetValues (rec->features[i].w, arg, 6);
1013 XtSetArg (arg[0], XtNborderColor, background);
1014 XtSetArg (arg[1], XtNsensitive, False);
1015 XtSetArg (arg[2], XtNlabel, " ");
1016 for (; i < rec->num_features; i++)
1018 if (! rec->features[i].w)
1020 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
1021 rec->parent, arg, 0);
1022 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1023 rec->features[i].w = w;
1025 XtSetValues (rec->features[i].w, arg, 3);
1030 compose_script_langsys (OTF_Tag script, OTF_Tag langsys, char *name)
1032 OTF_tag_name (script, name);
1036 OTF_tag_name (langsys, name + 5);
1043 decompose_script_langsys (OTF_Tag *script, OTF_Tag *langsys, char *name)
1045 *script = OTF_tag (name);
1047 *langsys = OTF_tag (name + 5);
1053 ScriptProc (Widget w, XtPointer client_data, XtPointer call_data)
1056 OTF_Tag script, langsys;
1059 XtSetArg (arg[0], XtNlabel, &name);
1060 XtGetValues (w, arg, 1);
1061 decompose_script_langsys (&script, &langsys, name);
1062 if (script_tag == script && langsys_tag == langsys)
1064 script_tag = script;
1065 langsys_tag = langsys;
1066 setup_feature_rec (&gsub);
1067 setup_feature_rec (&gpos);
1072 create_otf_script_widgets (Widget prev)
1076 int n, prev_n, i, j;
1084 XtSetArg (arg[0], XtNborderWidth, 0);
1085 XtSetArg (arg[1], XtNleft, XawChainLeft);
1086 XtSetArg (arg[2], XtNright, XawChainLeft);
1087 XtSetArg (arg[3], XtNtop, XawChainTop);
1088 XtSetArg (arg[4], XtNbottom, XawChainTop);
1089 XtSetArg (arg[5], XtNfromVert, prev);
1090 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1091 prev = XtCreateManagedWidget ("Script", boxWidgetClass, render_area, arg, 7);
1092 XtCreateManagedWidget ("script(langsys)", labelWidgetClass, prev, arg, 1);
1096 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
1097 n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
1099 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
1100 n += otf->gpos->ScriptList.Script[i].LangSysCount + 1;
1101 script_langsys = alloca ((sizeof script_langsys[0]) * n);
1105 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
1107 OTF_Tag tag = otf->gsub->ScriptList.Script[i].ScriptTag;
1109 script_langsys[n].script = tag;
1110 script_langsys[n++].langsys = 0;
1112 < otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount)
1114 = otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount;
1115 for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
1117 script_langsys[n].script = tag;
1118 script_langsys[n++].langsys
1119 = otf->gsub->ScriptList.Script[i].LangSysRecord[j].LangSysTag;
1121 < otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount)
1123 = otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount;
1126 gsub.num_features = nfeatures;
1129 gsub.num_features = nfeatures;
1130 gsub.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1131 memset (gsub.features, 0, (sizeof (FeatureElement)) * nfeatures);
1136 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
1138 OTF_Tag tag = otf->gpos->ScriptList.Script[i].ScriptTag;
1142 < otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount)
1144 = otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount;
1145 for (k = 0; k < prev_n; k++)
1146 if (tag == script_langsys[k].script)
1150 script_langsys[n].script = tag;
1151 script_langsys[n++].langsys = 0;
1153 for (j = 0; j < otf->gpos->ScriptList.Script[i].LangSysCount; j++)
1159 OTF_Script *script = otf->gpos->ScriptList.Script + i;
1161 for (l = k; l < prev_n && tag == script_langsys[l].script; l++)
1162 if (script->LangSysRecord[j].LangSysTag
1163 == script_langsys[l].langsys)
1170 script_langsys[n].script = tag;
1171 script_langsys[n++].langsys = 0;
1174 < otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount)
1176 = otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount;
1182 gpos.num_features = nfeatures;
1183 gpos.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1184 memset (gpos.features, 0, (sizeof (FeatureElement)) * nfeatures);
1190 script_tag = script_langsys[0].script;
1191 langsys_tag = script_langsys[0].langsys;
1192 compose_script_langsys (script_tag, langsys_tag, name);
1196 XtSetArg (arg[0], XtNforeground, background);
1197 XtSetArg (arg[1], XtNbackground, foreground);
1198 XtCreateManagedWidget (name, labelWidgetClass, prev, arg, 2);
1202 XtSetArg (arg[0], XtNstate, True);
1203 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1204 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1205 XtSetArg (arg[0], XtNradioGroup, w);
1206 for (i = 1; i < n; i++)
1208 compose_script_langsys (script_langsys[i].script,
1209 script_langsys[i].langsys, name);
1210 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1211 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1219 create_otf_widgets (Widget prev, FeatureRec *rec)
1224 XtSetArg (arg[0], XtNborderWidth, 0);
1225 XtSetArg (arg[1], XtNleft, XawChainLeft);
1226 XtSetArg (arg[2], XtNright, XawChainLeft);
1227 XtSetArg (arg[3], XtNtop, XawChainTop);
1228 XtSetArg (arg[4], XtNbottom, XawChainTop);
1229 XtSetArg (arg[5], XtNfromVert, prev);
1230 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1231 prev = XtCreateManagedWidget (rec->label, boxWidgetClass, render_area,
1233 XtCreateManagedWidget (rec->label, labelWidgetClass, prev, arg, 1);
1234 XtSetArg (arg[0], XtNborderWidth, 1);
1235 XtSetArg (arg[1], XtNinternalHeight, 4);
1236 XtSetArg (arg[2], XtNinternalWidth, 4);
1237 w = XtCreateManagedWidget ("all", commandWidgetClass, prev, arg, 3);
1238 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1239 w = XtCreateManagedWidget ("none", commandWidgetClass, prev, arg, 3);
1240 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1243 setup_feature_rec (rec);
1250 String quit_action = "<KeyPress>q: set() notify() unset()";
1251 String FIRST_action = "<KeyPress>f: set() notify() unset()\n\
1252 <KeyPress>Home: set() notify() unset()";
1253 String PREV_action = "Shift<KeyPress>p: set() notify() unset()\n\
1254 <KeyPress>Up: set() notify() unset()";
1255 String prev_action = "~Shift<KeyPress>p: set() notify() unset()\n\
1256 <KeyPress>Left: set() notify() unset()";
1257 String next_action = "~Shift<KeyPress>n: set() notify() unset()\n\
1258 <KeyPress>Right: set() notify() unset()";
1259 String NEXT_action = "Shift<KeyPress>n: set() notify() unset()\n\
1260 <KeyPress>Down: set() notify() unset()";
1261 String LAST_action = "<KeyPress>l: set() notify() unset()\n\
1262 <KeyPress>End: set() notify() unset()";
1266 String trans = "<Expose>: Expose()";
1268 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans));
1269 frame = XtCreateManagedWidget ("frame", formWidgetClass, shell, arg, 1);
1271 XtSetArg (arg[0], XtNleft, XawChainLeft);
1272 XtSetArg (arg[1], XtNright, XawChainLeft);
1273 XtSetArg (arg[2], XtNtop, XawChainTop);
1274 XtSetArg (arg[3], XtNbottom, XawChainTop);
1275 XtSetArg (arg[4], XtNborderWidth, 0);
1276 XtSetArg (arg[5], XtNorientation, XtorientHorizontal);
1277 command_area = XtCreateManagedWidget ("command-area", boxWidgetClass,
1279 XtSetArg (arg[6], XtNfromVert, command_area);
1280 navi_area = XtCreateManagedWidget ("navi-area", boxWidgetClass,
1282 XtSetArg (arg[4], XtNborderWidth, 0);
1283 XtSetArg (arg[5], XtNfromVert, navi_area);
1284 XtSetArg (arg[6], XtNdefaultDistance, 0);
1285 glyph_area = XtCreateManagedWidget ("glyph-area", formWidgetClass,
1288 XtSetArg (arg[5], XtNfromVert, glyph_area);
1293 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1294 uvs_area = XtCreateManagedWidget ("uvs-area", boxWidgetClass,
1296 XtSetArg (arg2[0], XtNborderWidth, 0);
1297 XtSetArg (arg2[1], XtNlabel, "Variation Selector: ");
1298 uvs_label = XtCreateManagedWidget ("uvs-label", labelWidgetClass,
1300 XtSetArg (arg2[0], XtNborderWidth, 1);
1301 for (i = 0; i < sub14->nRecords; i++)
1303 OTF_VariationSelectorRecord *record = sub14->Records + i;
1304 unsigned selector = record->varSelector;
1308 idx = (selector <= 0xFE0F ? selector - 0xFE00
1309 : selector - 0xE0100 + 16);
1312 uvs[idx].c = selector;
1313 sprintf (lbl, "%03d", idx + 1);
1314 XtSetArg (arg2[1], XtNlabel, lbl);
1315 XtSetArg (arg2[2], XtNsensitive, False);
1316 uvs[idx].w = XtCreateManagedWidget ("lbl", commandWidgetClass,
1318 XtAddCallbackWithCast (unsigned, uvs[idx].w, UVSProc, idx);
1320 XtSetArg (arg[5], XtNfromVert, uvs_area);
1322 render_area = XtCreateManagedWidget ("render-area", formWidgetClass,
1325 XtSetArg (arg[0], XtNaccelerators, XtParseAcceleratorTable (quit_action));
1326 quit = XtCreateManagedWidget ("Quit", commandWidgetClass,
1327 command_area, arg, 1);
1328 XtAddCallback (quit, XtNcallback, QuitProc, NULL);
1330 dump = XtCreateManagedWidget ("DumpImage", commandWidgetClass,
1331 command_area, arg, 1);
1332 XtAddCallback (dump, XtNcallback, DumpProc, NULL);
1334 XtSetArg (arg[0], XtNborderWidth, 0);
1335 XtSetArg (arg[1], XtNwidth, 10);
1336 XtCreateManagedWidget ("spacer", boxWidgetClass, command_area, arg, 2);
1338 charmap = alloca (sizeof (Widget) * (face->num_charmaps + 1));
1339 XtSetArg (arg[0], XtNstate, True);
1340 charmap[0] = XtCreateManagedWidget (charmap_rec[0].name, toggleWidgetClass,
1341 command_area, arg, 1);
1342 XtAddCallback (charmap[0], XtNcallback, CharmapProc, (XtPointer) -1);
1343 XtSetArg (arg[0], XtNradioGroup, charmap[0]);
1344 for (i = 0; i < face->num_charmaps; i++)
1346 charmap[i + 1] = XtCreateManagedWidget (charmap_rec[i + 1].name,
1348 command_area, arg, 1);
1349 XtAddCallbackWithCast (int, charmap[i + 1], CharmapProc, i);
1352 XtSetArg (arg[0], XtNlabel, " |< (f)");
1353 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (FIRST_action));
1354 FIRST = XtCreateManagedWidget ("FIRST", commandWidgetClass,
1356 XtAddCallback (FIRST, XtNcallback, GlyphProc, (XtPointer) -3);
1357 XtSetArg (arg[0], XtNlabel, "<< (P)");
1358 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (PREV_action));
1359 PREV = XtCreateManagedWidget ("PREV", commandWidgetClass,
1361 XtAddCallback (PREV, XtNcallback, GlyphProc, (XtPointer) -2);
1362 XtSetArg (arg[0], XtNlabel, "< (p)");
1363 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (prev_action));
1364 prev = XtCreateManagedWidget ("prev", commandWidgetClass,
1366 XtAddCallback (prev, XtNcallback, GlyphProc, (XtPointer) -1);
1367 XtSetArg (arg[0], XtNlabel, " 0000 ");
1368 range = XtCreateManagedWidget ("range", labelWidgetClass,
1370 XtSetArg (arg[0], XtNforeground, &foreground);
1371 XtSetArg (arg[1], XtNbackground, &background);
1372 XtGetValues (range, arg, 2);
1374 XtSetArg (arg[0], XtNlabel, "> (n)");
1375 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (next_action));
1376 next = XtCreateManagedWidget ("next", commandWidgetClass,
1378 XtAddCallback (next, XtNcallback, GlyphProc, (XtPointer) 1);
1379 XtSetArg (arg[0], XtNlabel, ">> (N)");
1380 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (NEXT_action));
1381 NEXT = XtCreateManagedWidget ("NEXT", commandWidgetClass,
1383 XtAddCallback (NEXT, XtNcallback, GlyphProc, (XtPointer) 2);
1384 XtSetArg (arg[0], XtNlabel, ">| (l)");
1385 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (LAST_action));
1386 LAST = XtCreateManagedWidget ("LAST", commandWidgetClass,
1388 XtAddCallback (LAST, XtNcallback, GlyphProc, (XtPointer) 3);
1390 XtSetArg (arg[0], XtNleft, XawChainLeft);
1391 XtSetArg (arg[1], XtNright, XawChainLeft);
1392 XtSetArg (arg[2], XtNtop, XawChainTop);
1393 XtSetArg (arg[3], XtNbottom, XawChainTop);
1395 for (i = 0; i < 8; i++)
1401 sprintf (str, "%XX", i);
1402 XtSetArg (arg[n], XtNheight, glyph_height + 5), n++;
1403 XtSetArg (arg[n], XtNlabel, str), n++;
1404 XtSetArg (arg[n], XtNborderWidth, 0), n++;
1406 XtSetArg (arg[n], XtNfromVert, w), n++;
1407 head = XtCreateManagedWidget (str, labelWidgetClass, glyph_area, arg, n);
1408 index_label[i] = head;
1409 for (j = 0; j < 16; j++)
1415 XtSetArg (arg[n], XtNfromVert, w), n++;
1417 XtSetArg (arg[n], XtNfromHoriz, head), n++;
1419 XtSetArg (arg[n], XtNfromHoriz, glyph[k - 1]), n++;
1420 XtSetArg (arg[n], XtNbitmap, none_pixmap), n++;
1421 glyph[k] = XtCreateManagedWidget ("glyph", commandWidgetClass,
1422 glyph_area, arg, n);
1423 XtAddCallbackWithCast (int, glyph[k], RenderProc, k);
1427 /* 10 = (1 (border_width) + 4 (inner_width)) * 2 */
1428 XtSetArg(arg[4], XtNwidth, glyph_width + 10);
1429 XtSetArg (arg[5], XtNfromVert, glyph[112]);
1430 XtSetArg (arg[6], XtNfromHoriz, w);
1431 XtSetArg (arg[7], XtNborderWidth, 0);
1433 for (j = 0; j < 16; j++)
1437 sprintf (str, "X%X", j);
1438 XtSetArg (arg[8], XtNlabel, str);
1439 w = XtCreateManagedWidget ("idx", labelWidgetClass, glyph_area, arg, 9);
1440 XtSetArg (arg[6], XtNfromHoriz, w);
1443 XtSetArg (arg[0], XtNleft, XawChainLeft);
1444 XtSetArg (arg[1], XtNright, XawChainLeft);
1445 XtSetArg (arg[2], XtNtop, XawChainTop);
1446 XtSetArg (arg[3], XtNbottom, XawChainTop);
1447 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1448 XtSetArg (arg[5], XtNborderWidth, 0);
1449 w = XtCreateManagedWidget ("clear-box", boxWidgetClass, render_area, arg, 6);
1450 clear = XtCreateManagedWidget ("clear", commandWidgetClass, w, arg, 0);
1451 XtAddCallback (clear, XtNcallback, RenderProc, (XtPointer) -1);
1452 del = XtCreateManagedWidget ("delete", commandWidgetClass, w, arg, 0);
1453 XtAddCallback (del, XtNcallback, RenderProc, (XtPointer) -2);
1454 bidi = XtCreateManagedWidget ("L->R", toggleWidgetClass, w, arg, 0);
1455 XtAddCallback (bidi, XtNcallback, BidiProc, NULL);
1456 alt_subst = XtCreateManagedWidget ("AltSubst", toggleWidgetClass, w, arg, 0);
1457 XtAddCallback (alt_subst, XtNcallback, AltSubstProc, NULL);
1459 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1460 XtSetArg (arg[5], XtNborderWidth, 0);
1461 XtSetArg (arg[6], XtNfromVert, w);
1462 raw = XtCreateManagedWidget ("raw", boxWidgetClass, render_area, arg, 7);
1464 XtSetArg (arg[0], XtNborderWidth, 0);
1465 XtSetArg (arg[1], XtNlabel, "raw: ");
1466 raw_label = XtCreateManagedWidget ("raw-label", labelWidgetClass,
1468 XtSetArg (arg[1], XtNbitmap, raw_pixmap);
1469 raw_image = XtCreateManagedWidget ("raw-image", labelWidgetClass,
1474 OTF_get_table (otf, "GSUB");
1475 OTF_get_table (otf, "GPOS");
1476 w = create_otf_script_widgets (w);
1479 gsub.label = "GSUB";
1480 gsub.gsub_gpos = otf->gsub;
1481 w = create_otf_widgets (w, &gsub);
1485 gpos.label = "GPOS";
1486 gpos.gsub_gpos = otf->gpos;
1487 w = create_otf_widgets (w, &gpos);
1491 XtSetArg (arg[6], XtNfromVert, w);
1492 seq = XtCreateManagedWidget ("seq", boxWidgetClass, render_area, arg, 7);
1493 XtSetArg (arg[0], XtNborderWidth, 0);
1494 XtSetArg (arg[1], XtNlabel, "seq: ");
1495 seq_label = XtCreateManagedWidget ("seq-label", labelWidgetClass,
1497 XtSetArg (arg[1], XtNbitmap, seq_pixmap);
1498 seq_image = XtCreateManagedWidget ("seq-image", labelWidgetClass,
1500 XtSetArg (arg[6], XtNfromVert, seq);
1501 code = XtCreateManagedWidget ("code", boxWidgetClass, render_area, arg, 7);
1502 XtSetArg (arg[0], XtNborderWidth, 0);
1503 XtSetArg (arg[1], XtNlabel, "code:");
1504 code_label = XtCreateManagedWidget ("code-label", labelWidgetClass,
1506 XtSetArg (arg[1], XtNlabel, "");
1507 XtSetArg (arg[2], XtNwidth, render_width);
1508 code_list = XtCreateManagedWidget ("code-list", labelWidgetClass,
1510 XtInstallAllAccelerators (shell, shell);
1514 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1516 XTextProperty text_prop;
1517 char *pname = "otfview";
1518 char *fname = basename (filename);
1519 char *name = alloca (strlen (fname) + 3 + strlen (pname) + 1);
1521 sprintf (name, "%s - %s", pname, fname);
1522 text_prop.value = (unsigned char *) name;
1523 text_prop.encoding = XA_STRING;
1524 text_prop.format = 8;
1525 text_prop.nitems = strlen (name);
1526 XSetWMName (display, XtWindow (shell), &text_prop);
1529 /* Format MSG by FMT and print the result to the stderr, and exit. */
1531 #define FATAL_ERROR(fmt, arg) \
1533 fprintf (stderr, fmt, arg); \
1538 x_error_handler (Display *display, XErrorEvent *error)
1544 help (char **argv, int err)
1546 FILE *fp = err ? stderr : stdout;
1548 fprintf (fp, "Usage: %s [ X-OPTION ... ] OTF-FILE [INDEX]\n",
1549 basename (argv[0]));
1550 fprintf (fp, " Environment variable PIXEL_SIZE specifies the pixel size.\n");
1551 fprintf (fp, " The default pixel size is %d, but is reduced\n",
1552 DEFAULT_PIXEL_SIZE);
1553 fprintf (fp, " if your screen is not that wide.\n");
1558 main (int argc, char **argv)
1560 XtActionsRec actions[] = { {"Expose", ExposeProc} };
1564 OTF_GlyphString gstring;
1569 int fixed_pixel_size = 0;
1572 pixel_size = DEFAULT_PIXEL_SIZE;
1574 char *str = getenv ("PIXEL_SIZE");
1576 if (str && (i = atoi (str)) > 0)
1579 fixed_pixel_size = 1;
1583 gstring.size = gstring.used = 256;
1584 g = calloc (256, sizeof (OTF_Glyph));
1587 shell = XtOpenApplication (&context, "OTFView", NULL, 0, &argc, argv, NULL,
1588 shellWidgetClass, arg, 0);
1589 display = XtDisplay (shell);
1590 /*XSynchronize (display, True);*/
1591 XSetErrorHandler (x_error_handler);
1592 display_width = DisplayWidth (display,
1593 XScreenNumberOfScreen (XtScreen (shell)));
1594 font = XLoadQueryFont (display, DEFAULT_FONT_NAME);
1596 font = XLoadQueryFont (display, "fixed");
1600 if (!strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
1605 fontindex = atoi (argv[2]);
1607 FATAL_ERROR ("Invalid font index: %d\n", fontindex);
1610 if ((err = FT_Init_FreeType (&library)))
1611 FATAL_ERROR ("%s\n", "FT_Init_FreeType: error");
1612 err = FT_New_Face (library, filename, fontindex, &face);
1613 if (err == FT_Err_Unknown_File_Format)
1614 FATAL_ERROR ("%s\n", "FT_New_Face: unknown file format");
1616 FATAL_ERROR ("%s\n", "FT_New_Face: unknown error (invalid face index?)");
1617 if ((err = FT_Set_Pixel_Sizes (face, 0, pixel_size)))
1618 FATAL_ERROR ("%s\n", "FT_Set_Pixel_Sizes: error");
1620 if (strstr (filename, ".ttf")
1621 || strstr (filename, ".TTF")
1622 || strstr (filename, ".otf")
1623 || strstr (filename, ".OTF"))
1625 otf = OTF_open_ft_face (face);
1628 if (OTF_get_table (otf, "head") < 0
1629 || OTF_get_table (otf, "cmap") < 0
1630 || (OTF_check_table (otf, "GSUB") < 0
1631 && OTF_check_table (otf, "GPOS") < 0))
1638 for (i = 0; i < otf->cmap->numTables; i++)
1639 if (otf->cmap->EncodingRecord[i].subtable.format == 14)
1641 sub14 = otf->cmap->EncodingRecord[i].subtable.f.f14;
1650 filename = basename (filename);
1651 sprintf (title, "%s family:%s style:%s",
1652 filename, face->family_name, face->style_name);
1653 XtSetArg (arg[0], XtNtitle, title);
1654 XtSetValues (shell, arg, 1);
1657 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1658 * pixel_size / face->units_per_EM);
1659 if (! fixed_pixel_size && glyph_width * 16 > display_width * 0.8)
1661 pixel_size = (pixel_size * display_width * 0.8 / 16 / glyph_width);
1662 FT_Set_Pixel_Sizes (face, 0, pixel_size);
1663 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1664 * pixel_size / face->units_per_EM);
1666 if (glyph_width < FONT_WIDTH * 4)
1667 glyph_width = FONT_WIDTH * 4;
1669 glyph_height = ((face->bbox.yMax - face->bbox.yMin)
1670 * pixel_size / face->units_per_EM);
1672 glyph_x = - (face->bbox.xMin * pixel_size / face->units_per_EM);
1673 glyph_y = face->bbox.yMax * pixel_size / face->units_per_EM;
1674 none_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1675 glyph_width, glyph_height, 1);
1678 unsigned long valuemask = GCFunction | GCLineWidth;
1681 gc = XCreateGC (display, none_pixmap, (unsigned long) 0, NULL);
1682 XSetFont (display, gc, font->fid);
1683 values.function = GXset;
1684 values.line_width = 1;
1685 gc_set = XCreateGC (display, none_pixmap, valuemask, &values);
1686 XSetFont (display, gc_set, font->fid);
1687 values.function = GXor;
1688 gc_or = XCreateGC (display, none_pixmap, valuemask, &values);
1689 values.function = GXcopyInverted;
1690 gc_inv = XCreateGC (display, none_pixmap, valuemask, &values);
1693 XFillRectangle (display, none_pixmap, gc, 0, 0,
1694 glyph_width, glyph_height);
1695 XDrawString (display, none_pixmap, gc_inv,
1696 (glyph_width - XTextWidth (font, "none", 4)) / 2,
1697 glyph_height / 2, "none", 4);
1699 render_width = (glyph_width + 4) * 15 + 1;
1700 render_height = glyph_height + 2;
1702 charmap_rec[0].platform_id = -1;
1703 charmap_rec[0].encoding_id = -1;
1704 strcpy (charmap_rec[0].name, "no charmap");
1706 for (i = 0; i < face->num_charmaps; i++)
1708 charmap_rec[i + 1].platform_id = face->charmaps[i]->platform_id;
1709 charmap_rec[i + 1].encoding_id = face->charmaps[i]->encoding_id;
1710 sprintf (charmap_rec[i + 1].name, "%d-%d",
1711 charmap_rec[i + 1].platform_id, charmap_rec[i + 1].encoding_id);
1712 if (face->charmaps[i]->platform_id == 0
1713 || (face->charmaps[i]->platform_id == 3
1714 && face->charmaps[i]->encoding_id == 1))
1715 strcat (charmap_rec[i + 1].name, " (unicode)");
1716 else if (face->charmaps[i]->platform_id == 1
1717 && face->charmaps[i]->encoding_id == 0)
1718 strcat (charmap_rec[i + 1].name, " (apple-roman)");
1721 raw_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1722 render_width, render_height, 1);
1723 seq_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1724 render_width, render_height, 1);
1726 memset (bitmap, 0, sizeof (bitmap));
1730 update_glyph_area ();
1731 update_render_area ();
1733 XtAppAddActions (context, actions, XtNumber (actions));
1734 XtRealizeWidget (shell);
1735 XtAppMainLoop (context);
1740 #else /* not HAVE_X11_XAW_COMMAND_H */
1743 main (int argc, char **argv)
1746 "Building of this program failed (lack of some header files)\n");