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 int size = render_width / FONT_WIDTH;
535 char *buf = alloca (size + 1);
537 sprintf (buf, "%04X", gstring.glyphs[0].glyph_id);
538 for (i = 1, x = 4; i < gstring.used; i++, x += 5)
539 sprintf (buf + x, " %04X", gstring.glyphs[i].glyph_id);
543 XtSetArg (arg[0], XtNlabel, buf);
544 XtSetValues (code_list, arg, 1);
547 free (gstring.glyphs);
552 update_render_area ()
558 XFillRectangle (display, raw_pixmap, gc, 0, 0, render_width, render_height);
559 for (i = 0, x = glyph_x; i < glyph_rec.n_glyphs; i++)
561 if (glyph_rec.glyphs[i] >= 0)
563 BitmapRec *bmp = bitmap + glyph_rec.glyphs[i];
566 XCopyArea (display, bmp->pixmap, raw_pixmap, gc,
567 0, 0, glyph_width, glyph_height,
568 (glyph_width + 4) * i + 1, 1);
569 XDrawRectangle (display, raw_pixmap, gc_set,
570 (glyph_width + 4) * i, 0,
571 glyph_width + 1, glyph_height + 1);
572 XDrawLine (display, raw_pixmap, gc_set,
573 (glyph_width + 4) * i + 1 + glyph_x, 1,
574 (glyph_width + 4) * i + 1 + glyph_x, glyph_height + 1);
575 XDrawLine (display, raw_pixmap, gc_set,
576 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance, 1,
577 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance,
580 sprintf (buf, "%04X", glyph_rec.codes[i]);
581 XDrawString (display, raw_pixmap, gc_inv,
582 (glyph_width + 4) * i + 1
583 + (glyph_width - XTextWidth (font, buf, 4)) / 2,
584 glyph_height + 2 + FONT_HEIGHT, buf, 4);
588 /* Variation Selector */
589 int idx = - glyph_rec.glyphs[i];
592 sprintf (buf, "%03d", idx);
593 XDrawRectangle (display, raw_pixmap, gc_set,
594 (glyph_width + 4) * i, 0,
595 glyph_width + 1, glyph_height + 1);
596 XDrawString (display, raw_pixmap, gc_set,
597 (glyph_width + 4) * i + 1
598 + (glyph_width - XTextWidth (font, "VS", 2)) / 2,
599 1 + glyph_height / 2, "VS", 2);
600 XDrawString (display, raw_pixmap, gc_set,
601 (glyph_width + 4) * i + 1
602 + (glyph_width - XTextWidth (font, buf, 3)) / 2,
603 1 + glyph_height / 2 + FONT_ASCENT, buf, 3);
606 XtSetArg (arg[0], XtNbitmap, raw_pixmap);
607 XtSetValues (raw_image, arg, 1);
612 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
614 XtAppSetExitFlag (XtWidgetToApplicationContext (w));
618 DumpProc (Widget w, XtPointer client_data, XtPointer call_data)
620 int g_width, g_height;
622 /* unit in points (1/72 inch); to fit in both US-letter and A4 */
623 static int xoff = 30, yoff = 30;
624 static int unit = 30;
625 static int margin = 2;
626 static int title_height = 20, label_height = 10;
627 int total_width = (unit + margin * 2) * 16;
628 int total_height = (unit + margin * 2 + label_height) * 16 + title_height;
629 /* pixel size (dots) */
632 char *name = alloca (strlen (filename) + 10);
634 int index = (glyph_index / 0x100) * 0x100;
637 g_width = face->bbox.xMax - face->bbox.xMin;
638 g_height = face->bbox.yMax - face->bbox.yMin;
639 if (g_width > g_height)
641 scale = g_width * size;
642 g_x = face->bbox.xMin * unit / g_width;
643 g_y = face->bbox.yMin * unit / g_width;
647 scale = g_height * size;
648 g_x = face->bbox.xMin * unit / g_height;
649 g_y = face->bbox.yMin * unit / g_height;
651 scale /= face->units_per_EM;
653 FT_Set_Pixel_Sizes (face, 0, size);
655 sprintf (name, "%s-%04X.ps", face->family_name, index);
656 printf ("Writing %s ... ", name);
658 fp = fopen (name, "w");
660 fprintf (fp, "%s\n", "%!PS-Adobe-2.0 EPSF-2.0");
661 fprintf (fp, "%s\n", "%%Creater: otfview");
662 fprintf (fp, "%s %s(%s)-%04X\n", "%%Title:",
663 face->family_name, face->style_name, index);
664 fprintf (fp, "%s\n", "%%Pages: 1");
665 fprintf (fp, "%s %d %d %d %d\n", "%%BoundingBox:",
666 xoff, yoff, xoff + total_width, yoff + total_height);
667 fprintf (fp, "%s\n", "%%EndComments");
668 fprintf (fp, "%s\n", "%%BeginProlog");
669 fprintf (fp, "/W %d def\n", unit + margin * 2);
670 fprintf (fp, "/H %d def\n", unit + margin * 2 + label_height);
671 fprintf (fp, "/STR 10 string def\n");
672 fprintf (fp, "/DrawIndex {\n");
673 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");
674 fprintf (fp, "} def\n");
675 fprintf (fp, "/DrawTitle {\n");
676 fprintf (fp, " /Courier findfont 20 scalefont setfont\n");
677 fprintf (fp, " %d %d 4 add moveto\n", xoff + total_width / 2,
678 yoff + total_height - title_height + 2);
679 fprintf (fp, " (%s(%s)-%04X) dup stringwidth pop 2 div neg 0 rmoveto show\n",
680 face->family_name, face->style_name, index);
681 fprintf (fp, "} def\n");
682 fprintf (fp, "/DrawFrame { gsave %d %d translate 0 setlinewidth\n",
684 fprintf (fp, " /Courier findfont 10 scalefont setfont\n");
685 fprintf (fp, " /I %d def\n", index);
686 fprintf (fp, " 0 1 16 { W mul 0 moveto 0 H 16 mul rlineto stroke } for\n");
687 fprintf (fp, " 0 1 16 { H mul 0 exch moveto W 16 mul 0 rlineto stroke } for\n");
688 fprintf (fp, " 0 1 15 { H mul %d add 0 exch moveto W 16 mul 0 rlineto stroke } for\n", label_height);
689 fprintf (fp, " 15 -1 0 { gsave H mul 0 exch translate 0 0 moveto\n");
690 fprintf (fp, " 0 1 15 { gsave W mul 0 moveto\n");
691 fprintf (fp, " 4 2 rmoveto DrawIndex /I I 1 add def grestore} for\n");
692 fprintf (fp, " grestore } for grestore } def\n");
693 fprintf (fp, "%s\n", "%%EndProlog");
694 fprintf (fp, "DrawTitle DrawFrame\n");
696 for (i = 0; i < 16; i++)
697 for (j = 0; j < 16; j++, index++)
701 if (charmap_index >= 0)
702 idx = FT_Get_Char_Index (face, (FT_ULong) index);
706 && FT_Load_Glyph (face, idx, FT_LOAD_RENDER | FT_LOAD_MONOCHROME) == 0
707 && face->glyph->bitmap.rows > 0
708 && face->glyph->bitmap.width > 0)
710 unsigned char *p = face->glyph->bitmap.buffer;
711 int width = (face->glyph->bitmap.width - 1) / 8 + 1;
713 fprintf (fp, "gsave %f %f translate %d %d scale 0 0 moveto\n",
714 xoff + (unit + margin * 2) * j + margin - g_x,
715 yoff + (unit + label_height + margin * 2) * (15 - i) + label_height + margin - g_y,
717 fprintf (fp, "%d %d true [%f 0 0 %f %d %d]\n",
718 width * 8, face->glyph->bitmap.rows,
719 scale, -scale, -face->glyph->bitmap_left,
720 face->glyph->bitmap_top);
722 for (k = 0; k < face->glyph->bitmap.rows;
723 k++, p += face->glyph->bitmap.pitch)
725 for (l = 0; l < width; l++)
726 fprintf (fp, "%02X", p[l]);
729 fprintf (fp, ">} imagemask grestore\n");
733 int boxsize = unit + margin * 2;
735 fprintf (fp, "gsave 0 setlinewidth %d %d translate\n",
737 yoff + (boxsize + label_height) * (15 - i) + label_height);
738 fprintf (fp, "0 0 moveto %d %d lineto stroke\n",
740 fprintf (fp, "0 %d moveto %d 0 lineto stroke grestore\n",
744 fprintf (fp, "showpage\n");
748 FT_Set_Pixel_Sizes (face, 0, (int) pixel_size);
753 GlyphProc (Widget w, XtPointer client_data, XtPointer call_data)
755 int old_glyph_index = glyph_index;
758 CAST_FROM_XTPOINTER (int, client_data, data);
760 if (data == -3 && glyph_index > 0)
762 else if (data == -2 && glyph_index > 0)
763 glyph_index = (glyph_index - 1) & 0x1FF000;
764 else if (data == -1 && glyph_index > 0)
766 else if (data == 1 && glyph_index < 0x10FF80)
768 else if (data == 2 && glyph_index < 0x10F000)
769 glyph_index = (glyph_index + 0x1000) & 0x1FF000;
770 else if (data == 3 && glyph_index < 0x10F000)
771 glyph_index = 0x10FF80;
772 if (glyph_index != old_glyph_index)
773 update_glyph_area ();
777 CharmapProc (Widget w, XtPointer client_data, XtPointer call_data)
781 CAST_FROM_XTPOINTER (int, client_data, data);
783 if (charmap_index == data)
785 charmap_index = data;
786 if (charmap_index >= 0)
787 FT_Set_Charmap (face, face->charmaps[charmap_index]);
788 update_glyph_area ();
792 UVSProc (Widget w, XtPointer client_data, XtPointer call_data)
796 OTF_VariationSelectorRecord *record;
799 CAST_FROM_XTPOINTER (unsigned, client_data, idx);
800 selector = uvs[idx].c;
802 if (glyph_rec.n_glyphs >= 64)
804 for (i = 0; i < sub14->nRecords; i++)
806 record = sub14->Records + i;
807 if (record->varSelector == selector)
810 if (i < sub14->nRecords)
812 if (glyph_rec.n_glyphs > 0
813 && glyph_rec.glyphs[glyph_rec.n_glyphs - 1] < 0)
814 glyph_rec.n_glyphs--;
815 glyph_rec.codes[glyph_rec.n_glyphs] = selector;
816 glyph_rec.glyphs[glyph_rec.n_glyphs++] = - idx - 1;
817 update_render_area ();
822 RenderProc (Widget w, XtPointer client_data, XtPointer call_data)
826 CAST_FROM_XTPOINTER (int, client_data, data);
830 if (glyph_rec.n_glyphs > 0)
833 glyph_rec.n_glyphs--;
835 glyph_rec.n_glyphs = 0;
836 update_render_area ();
839 else if (glyph_rec.n_glyphs < 64)
841 int index = glyph_index + data;
843 if (charmap_index >= 0)
844 index = FT_Get_Char_Index (face, (FT_ULong) index);
845 if (bitmap[index].pixmap)
847 glyph_rec.codes[glyph_rec.n_glyphs] = glyph_index + data;
848 glyph_rec.glyphs[glyph_rec.n_glyphs++] = index;
850 update_uvs_area (glyph_index + data);
851 update_render_area ();
857 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
861 reversed = ! reversed;
863 XtSetArg (arg[0], XtNlabel, "L<-R");
865 XtSetArg (arg[0], XtNlabel, "L->R");
866 XtSetValues (w, arg, 1);
871 AltSubstProc (Widget w, XtPointer client_data, XtPointer call_data)
873 do_alternate_subst = ! do_alternate_subst;
878 FeatureProc (Widget w, XtPointer client_data, XtPointer call_data)
880 FeatureRec *rec = (FeatureRec *) client_data;
887 XtSetArg (arg[0], XtNlabel, &label);
888 XtGetValues (w, arg, 1);
889 if (! strcmp (label, "all"))
891 else if (! strcmp (label, "none"))
895 for (idx = 0; idx < rec->langsys->FeatureCount; idx++)
896 if (rec->features[idx].w == w)
898 if (idx == rec->langsys->FeatureCount)
905 for (i = j = 0; j < rec->langsys->FeatureCount; j++)
907 int index = rec->langsys->FeatureIndex[j];
910 = rec->gsub_gpos->FeatureList.Feature[index].FeatureTag;
911 rec->features[j].on = on;
916 OTF_Tag tag = rec->features[idx].tag;
919 if (rec->features[i].on)
922 j < rec->langsys->FeatureCount && rec->features[j].on; j++)
923 rec->features[j - 1].tag = rec->features[j].tag;
924 rec->features[j - 1].tag = tag;
925 rec->features[j - 1].on = 0;
929 for (j = i + 1; i > 0 && ! rec->features[i - 1].on; i--)
930 rec->features[i].tag = rec->features[i - 1].tag;
931 rec->features[i].tag = tag;
932 rec->features[i].on = 1;
940 if (rec->features[i].on)
942 XtSetArg (arg[0], XtNborderWidth, 3);
943 XtSetArg (arg[1], XtNinternalHeight, 2);
944 XtSetArg (arg[2], XtNinternalWidth, 2);
948 XtSetArg (arg[0], XtNborderWidth, 1);
949 XtSetArg (arg[1], XtNinternalHeight, 4);
950 XtSetArg (arg[2], XtNinternalWidth, 4);
952 OTF_tag_name (rec->features[i].tag, str);
953 XtSetArg (arg[3], XtNlabel, str);
954 XtSetValues (rec->features[i].w, arg, 4);
960 setup_feature_rec (FeatureRec *rec)
966 if (! rec->gsub_gpos)
968 for (i = 0; i < rec->gsub_gpos->ScriptList.ScriptCount; i++)
969 if (rec->gsub_gpos->ScriptList.Script[i].ScriptTag == script_tag)
971 OTF_Script *script = rec->gsub_gpos->ScriptList.Script + i;
975 for (j = 0; j < script->LangSysCount; j++)
976 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
978 rec->langsys = script->LangSys + j;
983 rec->langsys = &rec->gsub_gpos->ScriptList.Script[i].DefaultLangSys;
991 XtSetArg (arg[0], XtNborderWidth, 1);
992 XtSetArg (arg[1], XtNinternalHeight, 4);
993 XtSetArg (arg[2], XtNinternalWidth, 4);
994 XtSetArg (arg[3], XtNborderColor, foreground);
995 XtSetArg (arg[4], XtNsensitive, True);
996 for (i = 0; i < rec->langsys->FeatureCount; i++)
998 OTF_Feature *feature = rec->gsub_gpos->FeatureList.Feature;
999 int index = rec->langsys->FeatureIndex[i];
1002 if (! rec->features[i].w)
1004 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
1005 rec->parent, arg, 0);
1006 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1007 rec->features[i].w = w;
1010 rec->features[i].tag = feature[index].FeatureTag;
1011 rec->features[i].on = 0;
1012 OTF_tag_name (rec->features[i].tag, label);
1013 XtSetArg (arg[5], XtNlabel, label);
1014 XtSetValues (rec->features[i].w, arg, 6);
1017 XtSetArg (arg[0], XtNborderColor, background);
1018 XtSetArg (arg[1], XtNsensitive, False);
1019 XtSetArg (arg[2], XtNlabel, " ");
1020 for (; i < rec->num_features; i++)
1022 if (! rec->features[i].w)
1024 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
1025 rec->parent, arg, 0);
1026 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1027 rec->features[i].w = w;
1029 XtSetValues (rec->features[i].w, arg, 3);
1034 compose_script_langsys (OTF_Tag script, OTF_Tag langsys, char *name)
1036 OTF_tag_name (script, name);
1040 OTF_tag_name (langsys, name + 5);
1047 decompose_script_langsys (OTF_Tag *script, OTF_Tag *langsys, char *name)
1049 *script = OTF_tag (name);
1051 *langsys = OTF_tag (name + 5);
1057 ScriptProc (Widget w, XtPointer client_data, XtPointer call_data)
1060 OTF_Tag script, langsys;
1063 XtSetArg (arg[0], XtNlabel, &name);
1064 XtGetValues (w, arg, 1);
1065 decompose_script_langsys (&script, &langsys, name);
1066 if (script_tag == script && langsys_tag == langsys)
1068 script_tag = script;
1069 langsys_tag = langsys;
1070 setup_feature_rec (&gsub);
1071 setup_feature_rec (&gpos);
1076 create_otf_script_widgets (Widget prev)
1080 int n, prev_n, i, j;
1088 XtSetArg (arg[0], XtNborderWidth, 0);
1089 XtSetArg (arg[1], XtNleft, XawChainLeft);
1090 XtSetArg (arg[2], XtNright, XawChainLeft);
1091 XtSetArg (arg[3], XtNtop, XawChainTop);
1092 XtSetArg (arg[4], XtNbottom, XawChainTop);
1093 XtSetArg (arg[5], XtNfromVert, prev);
1094 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1095 prev = XtCreateManagedWidget ("Script", boxWidgetClass, render_area, arg, 7);
1096 XtCreateManagedWidget ("script(langsys)", labelWidgetClass, prev, arg, 1);
1100 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
1101 n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
1103 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
1104 n += otf->gpos->ScriptList.Script[i].LangSysCount + 1;
1105 script_langsys = alloca ((sizeof script_langsys[0]) * n);
1109 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
1111 OTF_Tag tag = otf->gsub->ScriptList.Script[i].ScriptTag;
1113 script_langsys[n].script = tag;
1114 script_langsys[n++].langsys = 0;
1116 < otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount)
1118 = otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount;
1119 for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
1121 script_langsys[n].script = tag;
1122 script_langsys[n++].langsys
1123 = otf->gsub->ScriptList.Script[i].LangSysRecord[j].LangSysTag;
1125 < otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount)
1127 = otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount;
1130 gsub.num_features = nfeatures;
1133 gsub.num_features = nfeatures;
1134 gsub.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1135 memset (gsub.features, 0, (sizeof (FeatureElement)) * nfeatures);
1140 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
1142 OTF_Tag tag = otf->gpos->ScriptList.Script[i].ScriptTag;
1146 < otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount)
1148 = otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount;
1149 for (k = 0; k < prev_n; k++)
1150 if (tag == script_langsys[k].script)
1154 script_langsys[n].script = tag;
1155 script_langsys[n++].langsys = 0;
1157 for (j = 0; j < otf->gpos->ScriptList.Script[i].LangSysCount; j++)
1163 OTF_Script *script = otf->gpos->ScriptList.Script + i;
1165 for (l = k; l < prev_n && tag == script_langsys[l].script; l++)
1166 if (script->LangSysRecord[j].LangSysTag
1167 == script_langsys[l].langsys)
1174 script_langsys[n].script = tag;
1175 script_langsys[n++].langsys = 0;
1178 < otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount)
1180 = otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount;
1186 gpos.num_features = nfeatures;
1187 gpos.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1188 memset (gpos.features, 0, (sizeof (FeatureElement)) * nfeatures);
1194 script_tag = script_langsys[0].script;
1195 langsys_tag = script_langsys[0].langsys;
1196 compose_script_langsys (script_tag, langsys_tag, name);
1200 XtSetArg (arg[0], XtNforeground, background);
1201 XtSetArg (arg[1], XtNbackground, foreground);
1202 XtCreateManagedWidget (name, labelWidgetClass, prev, arg, 2);
1206 XtSetArg (arg[0], XtNstate, True);
1207 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1208 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1209 XtSetArg (arg[0], XtNradioGroup, w);
1210 for (i = 1; i < n; i++)
1212 compose_script_langsys (script_langsys[i].script,
1213 script_langsys[i].langsys, name);
1214 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1215 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1223 create_otf_widgets (Widget prev, FeatureRec *rec)
1228 XtSetArg (arg[0], XtNborderWidth, 0);
1229 XtSetArg (arg[1], XtNleft, XawChainLeft);
1230 XtSetArg (arg[2], XtNright, XawChainLeft);
1231 XtSetArg (arg[3], XtNtop, XawChainTop);
1232 XtSetArg (arg[4], XtNbottom, XawChainTop);
1233 XtSetArg (arg[5], XtNfromVert, prev);
1234 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1235 prev = XtCreateManagedWidget (rec->label, boxWidgetClass, render_area,
1237 XtCreateManagedWidget (rec->label, labelWidgetClass, prev, arg, 1);
1238 XtSetArg (arg[0], XtNborderWidth, 1);
1239 XtSetArg (arg[1], XtNinternalHeight, 4);
1240 XtSetArg (arg[2], XtNinternalWidth, 4);
1241 w = XtCreateManagedWidget ("all", commandWidgetClass, prev, arg, 3);
1242 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1243 w = XtCreateManagedWidget ("none", commandWidgetClass, prev, arg, 3);
1244 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1247 setup_feature_rec (rec);
1254 String quit_action = "<KeyPress>q: set() notify() unset()";
1255 String FIRST_action = "<KeyPress>f: set() notify() unset()\n\
1256 <KeyPress>Home: set() notify() unset()";
1257 String PREV_action = "Shift<KeyPress>p: set() notify() unset()\n\
1258 <KeyPress>Up: set() notify() unset()";
1259 String prev_action = "~Shift<KeyPress>p: set() notify() unset()\n\
1260 <KeyPress>Left: set() notify() unset()";
1261 String next_action = "~Shift<KeyPress>n: set() notify() unset()\n\
1262 <KeyPress>Right: set() notify() unset()";
1263 String NEXT_action = "Shift<KeyPress>n: set() notify() unset()\n\
1264 <KeyPress>Down: set() notify() unset()";
1265 String LAST_action = "<KeyPress>l: set() notify() unset()\n\
1266 <KeyPress>End: set() notify() unset()";
1270 String trans = "<Expose>: Expose()";
1272 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans));
1273 frame = XtCreateManagedWidget ("frame", formWidgetClass, shell, arg, 1);
1275 XtSetArg (arg[0], XtNleft, XawChainLeft);
1276 XtSetArg (arg[1], XtNright, XawChainLeft);
1277 XtSetArg (arg[2], XtNtop, XawChainTop);
1278 XtSetArg (arg[3], XtNbottom, XawChainTop);
1279 XtSetArg (arg[4], XtNborderWidth, 0);
1280 XtSetArg (arg[5], XtNorientation, XtorientHorizontal);
1281 command_area = XtCreateManagedWidget ("command-area", boxWidgetClass,
1283 XtSetArg (arg[6], XtNfromVert, command_area);
1284 navi_area = XtCreateManagedWidget ("navi-area", boxWidgetClass,
1286 XtSetArg (arg[4], XtNborderWidth, 0);
1287 XtSetArg (arg[5], XtNfromVert, navi_area);
1288 XtSetArg (arg[6], XtNdefaultDistance, 0);
1289 glyph_area = XtCreateManagedWidget ("glyph-area", formWidgetClass,
1292 XtSetArg (arg[5], XtNfromVert, glyph_area);
1297 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1298 uvs_area = XtCreateManagedWidget ("uvs-area", boxWidgetClass,
1300 XtSetArg (arg2[0], XtNborderWidth, 0);
1301 XtSetArg (arg2[1], XtNlabel, "Variation Selector: ");
1302 uvs_label = XtCreateManagedWidget ("uvs-label", labelWidgetClass,
1304 XtSetArg (arg2[0], XtNborderWidth, 1);
1305 for (i = 0; i < sub14->nRecords; i++)
1307 OTF_VariationSelectorRecord *record = sub14->Records + i;
1308 unsigned selector = record->varSelector;
1312 idx = (selector <= 0xFE0F ? selector - 0xFE00
1313 : selector - 0xE0100 + 16);
1316 uvs[idx].c = selector;
1317 sprintf (lbl, "%03d", idx + 1);
1318 XtSetArg (arg2[1], XtNlabel, lbl);
1319 XtSetArg (arg2[2], XtNsensitive, False);
1320 uvs[idx].w = XtCreateManagedWidget ("lbl", commandWidgetClass,
1322 XtAddCallbackWithCast (unsigned, uvs[idx].w, UVSProc, idx);
1324 XtSetArg (arg[5], XtNfromVert, uvs_area);
1326 render_area = XtCreateManagedWidget ("render-area", formWidgetClass,
1329 XtSetArg (arg[0], XtNaccelerators, XtParseAcceleratorTable (quit_action));
1330 quit = XtCreateManagedWidget ("Quit", commandWidgetClass,
1331 command_area, arg, 1);
1332 XtAddCallback (quit, XtNcallback, QuitProc, NULL);
1334 dump = XtCreateManagedWidget ("DumpImage", commandWidgetClass,
1335 command_area, arg, 1);
1336 XtAddCallback (dump, XtNcallback, DumpProc, NULL);
1338 XtSetArg (arg[0], XtNborderWidth, 0);
1339 XtSetArg (arg[1], XtNwidth, 10);
1340 XtCreateManagedWidget ("spacer", boxWidgetClass, command_area, arg, 2);
1342 charmap = alloca (sizeof (Widget) * (face->num_charmaps + 1));
1343 XtSetArg (arg[0], XtNstate, True);
1344 charmap[0] = XtCreateManagedWidget (charmap_rec[0].name, toggleWidgetClass,
1345 command_area, arg, 1);
1346 XtAddCallback (charmap[0], XtNcallback, CharmapProc, (XtPointer) -1);
1347 XtSetArg (arg[0], XtNradioGroup, charmap[0]);
1348 for (i = 0; i < face->num_charmaps; i++)
1350 charmap[i + 1] = XtCreateManagedWidget (charmap_rec[i + 1].name,
1352 command_area, arg, 1);
1353 XtAddCallbackWithCast (int, charmap[i + 1], CharmapProc, i);
1356 XtSetArg (arg[0], XtNlabel, " |< (f)");
1357 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (FIRST_action));
1358 FIRST = XtCreateManagedWidget ("FIRST", commandWidgetClass,
1360 XtAddCallback (FIRST, XtNcallback, GlyphProc, (XtPointer) -3);
1361 XtSetArg (arg[0], XtNlabel, "<< (P)");
1362 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (PREV_action));
1363 PREV = XtCreateManagedWidget ("PREV", commandWidgetClass,
1365 XtAddCallback (PREV, XtNcallback, GlyphProc, (XtPointer) -2);
1366 XtSetArg (arg[0], XtNlabel, "< (p)");
1367 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (prev_action));
1368 prev = XtCreateManagedWidget ("prev", commandWidgetClass,
1370 XtAddCallback (prev, XtNcallback, GlyphProc, (XtPointer) -1);
1371 XtSetArg (arg[0], XtNlabel, " 0000 ");
1372 range = XtCreateManagedWidget ("range", labelWidgetClass,
1374 XtSetArg (arg[0], XtNforeground, &foreground);
1375 XtSetArg (arg[1], XtNbackground, &background);
1376 XtGetValues (range, arg, 2);
1378 XtSetArg (arg[0], XtNlabel, "> (n)");
1379 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (next_action));
1380 next = XtCreateManagedWidget ("next", commandWidgetClass,
1382 XtAddCallback (next, XtNcallback, GlyphProc, (XtPointer) 1);
1383 XtSetArg (arg[0], XtNlabel, ">> (N)");
1384 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (NEXT_action));
1385 NEXT = XtCreateManagedWidget ("NEXT", commandWidgetClass,
1387 XtAddCallback (NEXT, XtNcallback, GlyphProc, (XtPointer) 2);
1388 XtSetArg (arg[0], XtNlabel, ">| (l)");
1389 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (LAST_action));
1390 LAST = XtCreateManagedWidget ("LAST", commandWidgetClass,
1392 XtAddCallback (LAST, XtNcallback, GlyphProc, (XtPointer) 3);
1394 XtSetArg (arg[0], XtNleft, XawChainLeft);
1395 XtSetArg (arg[1], XtNright, XawChainLeft);
1396 XtSetArg (arg[2], XtNtop, XawChainTop);
1397 XtSetArg (arg[3], XtNbottom, XawChainTop);
1399 for (i = 0; i < 8; i++)
1405 sprintf (str, "%XX", i);
1406 XtSetArg (arg[n], XtNheight, glyph_height + 5), n++;
1407 XtSetArg (arg[n], XtNlabel, str), n++;
1408 XtSetArg (arg[n], XtNborderWidth, 0), n++;
1410 XtSetArg (arg[n], XtNfromVert, w), n++;
1411 head = XtCreateManagedWidget (str, labelWidgetClass, glyph_area, arg, n);
1412 index_label[i] = head;
1413 for (j = 0; j < 16; j++)
1419 XtSetArg (arg[n], XtNfromVert, w), n++;
1421 XtSetArg (arg[n], XtNfromHoriz, head), n++;
1423 XtSetArg (arg[n], XtNfromHoriz, glyph[k - 1]), n++;
1424 XtSetArg (arg[n], XtNbitmap, none_pixmap), n++;
1425 glyph[k] = XtCreateManagedWidget ("glyph", commandWidgetClass,
1426 glyph_area, arg, n);
1427 XtAddCallbackWithCast (int, glyph[k], RenderProc, k);
1431 /* 10 = (1 (border_width) + 4 (inner_width)) * 2 */
1432 XtSetArg(arg[4], XtNwidth, glyph_width + 10);
1433 XtSetArg (arg[5], XtNfromVert, glyph[112]);
1434 XtSetArg (arg[6], XtNfromHoriz, w);
1435 XtSetArg (arg[7], XtNborderWidth, 0);
1437 for (j = 0; j < 16; j++)
1441 sprintf (str, "X%X", j);
1442 XtSetArg (arg[8], XtNlabel, str);
1443 w = XtCreateManagedWidget ("idx", labelWidgetClass, glyph_area, arg, 9);
1444 XtSetArg (arg[6], XtNfromHoriz, w);
1447 XtSetArg (arg[0], XtNleft, XawChainLeft);
1448 XtSetArg (arg[1], XtNright, XawChainLeft);
1449 XtSetArg (arg[2], XtNtop, XawChainTop);
1450 XtSetArg (arg[3], XtNbottom, XawChainTop);
1451 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1452 XtSetArg (arg[5], XtNborderWidth, 0);
1453 w = XtCreateManagedWidget ("clear-box", boxWidgetClass, render_area, arg, 6);
1454 clear = XtCreateManagedWidget ("clear", commandWidgetClass, w, arg, 0);
1455 XtAddCallback (clear, XtNcallback, RenderProc, (XtPointer) -1);
1456 del = XtCreateManagedWidget ("delete", commandWidgetClass, w, arg, 0);
1457 XtAddCallback (del, XtNcallback, RenderProc, (XtPointer) -2);
1458 bidi = XtCreateManagedWidget ("L->R", toggleWidgetClass, w, arg, 0);
1459 XtAddCallback (bidi, XtNcallback, BidiProc, NULL);
1460 alt_subst = XtCreateManagedWidget ("AltSubst", toggleWidgetClass, w, arg, 0);
1461 XtAddCallback (alt_subst, XtNcallback, AltSubstProc, NULL);
1463 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1464 XtSetArg (arg[5], XtNborderWidth, 0);
1465 XtSetArg (arg[6], XtNfromVert, w);
1466 raw = XtCreateManagedWidget ("raw", boxWidgetClass, render_area, arg, 7);
1468 XtSetArg (arg[0], XtNborderWidth, 0);
1469 XtSetArg (arg[1], XtNlabel, "raw: ");
1470 raw_label = XtCreateManagedWidget ("raw-label", labelWidgetClass,
1472 XtSetArg (arg[1], XtNbitmap, raw_pixmap);
1473 raw_image = XtCreateManagedWidget ("raw-image", labelWidgetClass,
1478 OTF_get_table (otf, "GSUB");
1479 OTF_get_table (otf, "GPOS");
1480 w = create_otf_script_widgets (w);
1483 gsub.label = "GSUB";
1484 gsub.gsub_gpos = otf->gsub;
1485 w = create_otf_widgets (w, &gsub);
1489 gpos.label = "GPOS";
1490 gpos.gsub_gpos = otf->gpos;
1491 w = create_otf_widgets (w, &gpos);
1495 XtSetArg (arg[6], XtNfromVert, w);
1496 seq = XtCreateManagedWidget ("seq", boxWidgetClass, render_area, arg, 7);
1497 XtSetArg (arg[0], XtNborderWidth, 0);
1498 XtSetArg (arg[1], XtNlabel, "seq: ");
1499 seq_label = XtCreateManagedWidget ("seq-label", labelWidgetClass,
1501 XtSetArg (arg[1], XtNbitmap, seq_pixmap);
1502 seq_image = XtCreateManagedWidget ("seq-image", labelWidgetClass,
1504 XtSetArg (arg[6], XtNfromVert, seq);
1505 code = XtCreateManagedWidget ("code", boxWidgetClass, render_area, arg, 7);
1506 XtSetArg (arg[0], XtNborderWidth, 0);
1507 XtSetArg (arg[1], XtNlabel, "code:");
1508 code_label = XtCreateManagedWidget ("code-label", labelWidgetClass,
1510 XtSetArg (arg[1], XtNlabel, "");
1511 XtSetArg (arg[2], XtNwidth, render_width);
1512 code_list = XtCreateManagedWidget ("code-list", labelWidgetClass,
1514 XtInstallAllAccelerators (shell, shell);
1518 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1520 XTextProperty text_prop;
1521 char *pname = "otfview";
1522 char *fname = basename (filename);
1523 char *name = alloca (strlen (fname) + 3 + strlen (pname) + 1);
1525 sprintf (name, "%s - %s", pname, fname);
1526 text_prop.value = (unsigned char *) name;
1527 text_prop.encoding = XA_STRING;
1528 text_prop.format = 8;
1529 text_prop.nitems = strlen (name);
1530 XSetWMName (display, XtWindow (shell), &text_prop);
1533 /* Format MSG by FMT and print the result to the stderr, and exit. */
1535 #define FATAL_ERROR(fmt, arg) \
1537 fprintf (stderr, fmt, arg); \
1542 x_error_handler (Display *display, XErrorEvent *error)
1548 help (char **argv, int err)
1550 FILE *fp = err ? stderr : stdout;
1552 fprintf (fp, "Usage: %s [ X-OPTION ... ] OTF-FILE [INDEX]\n",
1553 basename (argv[0]));
1554 fprintf (fp, " Environment variable PIXEL_SIZE specifies the pixel size.\n");
1555 fprintf (fp, " The default pixel size is %d, but is reduced\n",
1556 DEFAULT_PIXEL_SIZE);
1557 fprintf (fp, " if your screen is not that wide.\n");
1562 main (int argc, char **argv)
1564 XtActionsRec actions[] = { {"Expose", ExposeProc} };
1568 OTF_GlyphString gstring;
1573 int fixed_pixel_size = 0;
1576 pixel_size = DEFAULT_PIXEL_SIZE;
1578 char *str = getenv ("PIXEL_SIZE");
1580 if (str && (i = atoi (str)) > 0)
1583 fixed_pixel_size = 1;
1587 gstring.size = gstring.used = 256;
1588 g = calloc (256, sizeof (OTF_Glyph));
1591 shell = XtOpenApplication (&context, "OTFView", NULL, 0, &argc, argv, NULL,
1592 shellWidgetClass, arg, 0);
1593 display = XtDisplay (shell);
1594 /*XSynchronize (display, True);*/
1595 XSetErrorHandler (x_error_handler);
1596 display_width = DisplayWidth (display,
1597 XScreenNumberOfScreen (XtScreen (shell)));
1598 font = XLoadQueryFont (display, DEFAULT_FONT_NAME);
1600 font = XLoadQueryFont (display, "fixed");
1604 if (!strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
1609 fontindex = atoi (argv[2]);
1611 FATAL_ERROR ("Invalid font index: %d\n", fontindex);
1614 if ((err = FT_Init_FreeType (&library)))
1615 FATAL_ERROR ("%s\n", "FT_Init_FreeType: error");
1616 err = FT_New_Face (library, filename, fontindex, &face);
1617 if (err == FT_Err_Unknown_File_Format)
1618 FATAL_ERROR ("%s\n", "FT_New_Face: unknown file format");
1620 FATAL_ERROR ("%s\n", "FT_New_Face: unknown error (invalid face index?)");
1621 if ((err = FT_Set_Pixel_Sizes (face, 0, pixel_size)))
1622 FATAL_ERROR ("%s\n", "FT_Set_Pixel_Sizes: error");
1624 if (strstr (filename, ".ttf")
1625 || strstr (filename, ".TTF")
1626 || strstr (filename, ".otf")
1627 || strstr (filename, ".OTF"))
1629 otf = OTF_open_ft_face (face);
1632 if (OTF_get_table (otf, "head") < 0
1633 || OTF_get_table (otf, "cmap") < 0
1634 || (OTF_check_table (otf, "GSUB") < 0
1635 && OTF_check_table (otf, "GPOS") < 0))
1642 for (i = 0; i < otf->cmap->numTables; i++)
1643 if (otf->cmap->EncodingRecord[i].subtable.format == 14)
1645 sub14 = otf->cmap->EncodingRecord[i].subtable.f.f14;
1654 filename = basename (filename);
1655 sprintf (title, "%s family:%s style:%s",
1656 filename, face->family_name, face->style_name);
1657 XtSetArg (arg[0], XtNtitle, title);
1658 XtSetValues (shell, arg, 1);
1661 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1662 * pixel_size / face->units_per_EM);
1663 if (! fixed_pixel_size && glyph_width * 16 > display_width * 0.8)
1665 pixel_size = (pixel_size * display_width * 0.8 / 16 / glyph_width);
1666 FT_Set_Pixel_Sizes (face, 0, pixel_size);
1667 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1668 * pixel_size / face->units_per_EM);
1670 if (glyph_width < FONT_WIDTH * 4)
1671 glyph_width = FONT_WIDTH * 4;
1673 glyph_height = ((face->bbox.yMax - face->bbox.yMin)
1674 * pixel_size / face->units_per_EM);
1676 glyph_x = - (face->bbox.xMin * pixel_size / face->units_per_EM);
1677 glyph_y = face->bbox.yMax * pixel_size / face->units_per_EM;
1678 none_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1679 glyph_width, glyph_height, 1);
1682 unsigned long valuemask = GCFunction | GCLineWidth;
1685 gc = XCreateGC (display, none_pixmap, (unsigned long) 0, NULL);
1686 XSetFont (display, gc, font->fid);
1687 values.function = GXset;
1688 values.line_width = 1;
1689 gc_set = XCreateGC (display, none_pixmap, valuemask, &values);
1690 XSetFont (display, gc_set, font->fid);
1691 values.function = GXor;
1692 gc_or = XCreateGC (display, none_pixmap, valuemask, &values);
1693 values.function = GXcopyInverted;
1694 gc_inv = XCreateGC (display, none_pixmap, valuemask, &values);
1697 XFillRectangle (display, none_pixmap, gc, 0, 0,
1698 glyph_width, glyph_height);
1699 XDrawString (display, none_pixmap, gc_inv,
1700 (glyph_width - XTextWidth (font, "none", 4)) / 2,
1701 glyph_height / 2, "none", 4);
1703 render_width = (glyph_width + 4) * 15 + 1;
1704 render_height = glyph_height + 2;
1706 charmap_rec[0].platform_id = -1;
1707 charmap_rec[0].encoding_id = -1;
1708 strcpy (charmap_rec[0].name, "no charmap");
1710 for (i = 0; i < face->num_charmaps; i++)
1712 charmap_rec[i + 1].platform_id = face->charmaps[i]->platform_id;
1713 charmap_rec[i + 1].encoding_id = face->charmaps[i]->encoding_id;
1714 sprintf (charmap_rec[i + 1].name, "%d-%d",
1715 charmap_rec[i + 1].platform_id, charmap_rec[i + 1].encoding_id);
1716 if (face->charmaps[i]->platform_id == 0
1717 || (face->charmaps[i]->platform_id == 3
1718 && face->charmaps[i]->encoding_id == 1))
1719 strcat (charmap_rec[i + 1].name, " (unicode)");
1720 else if (face->charmaps[i]->platform_id == 1
1721 && face->charmaps[i]->encoding_id == 0)
1722 strcat (charmap_rec[i + 1].name, " (apple-roman)");
1725 raw_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1726 render_width, render_height, 1);
1727 seq_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1728 render_width, render_height, 1);
1730 memset (bitmap, 0, sizeof (bitmap));
1734 update_glyph_area ();
1735 update_render_area ();
1737 XtAppAddActions (context, actions, XtNumber (actions));
1738 XtRealizeWidget (shell);
1739 XtAppMainLoop (context);
1744 #else /* not HAVE_X11_XAW_COMMAND_H */
1747 main (int argc, char **argv)
1750 "Building of this program failed (lack of some header files)\n");