1 /* otfview.c -- View glyphs of OpenType fonts.
3 Copyright (C) 2003, 2004, 2005
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H15PRO167
7 This file is part of libotf.
9 Libotf is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 Libotf is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library, in a file named COPYING; if not,
21 write to the Free Software Foundation, Inc., 59 Temple Place, Suite
22 330, Boston, MA 02111-1307, USA. */
33 #ifdef HAVE_X11_XAW_COMMAND_H
35 #include <X11/Xatom.h>
36 #include <X11/Intrinsic.h>
37 #include <X11/StringDefs.h>
38 #include <X11/Shell.h>
39 #include <X11/Xaw/Command.h>
40 #include <X11/Xaw/Toggle.h>
41 #include <X11/Xaw/Box.h>
42 #include <X11/Xaw/Form.h>
43 #include <X11/Xaw/Viewport.h>
46 #include FT_FREETYPE_H
50 #define DEFAULT_PIXEL_SIZE 30
53 #define DEFAULT_FONT_NAME "6x13"
55 #define FONT_HEIGHT (font->ascent + font->descent)
56 #define FONT_ASCENT (font->ascent)
57 #define FONT_DESCENT (font->descent)
58 #define FONT_WIDTH (font->max_bounds.width)
62 +--- frame (form) -------------------------+
63 | +--- command_area (box) ---------------+ |
64 | | quit dump charmap ... | |
65 | +--------------------------------------+ |
66 | +---- navi_area (box) -----------------+ |
67 | | FIRST PREV prev range next NEXT LAST | |
68 | +--------------------------------------+ |
69 | +--- glyph_area (form) ----------------+ |
70 | | idxh[0] glyph[0] ... glyph[15] | |
72 | | idxh[7] glyph[112] ... glyph[127]| |
73 | | idxl[0] ... idxl[15] | |
74 | +--------------------------------------+ |
75 | +--- render_area (form) ---------------+ |
76 | | clear del bidi alt_subst | |
77 | | +--- raw (box) --------------------+ | |
78 | | | raw_label raw_image | | |
79 | | +----------------------------------+ | |
80 | | GSUB all none features... | |
81 | | GPOS all none features... | |
82 | | +--- seq (box) --------------------+ | |
83 | | | seq_label seq_image | | |
84 | | +----------------------------------+ | |
85 | +--------------------------------------+ |
86 +------------------------------------------+ */
88 Widget command_area, quit, dump, *charmap;
89 Widget navi_area, FIRST, PREV, prev, range, next, NEXT, LAST;
90 Widget glyph_area, glyph[128], index_label[8];
91 Widget render_area, clear, del, bidi, alt_subst, raw, seq;
92 Widget raw_label, raw_image, seq_label, seq_image;
93 unsigned long foreground, background;
105 OTF_GSUB_GPOS *gsub_gpos;
106 OTF_LangSys *langsys;
108 FeatureElement *features;
112 FeatureRec gsub, gpos;
114 /* Currently selected script and langsys. */
115 OTF_Tag script_tag, langsys_tag;
120 GC gc, gc_set, gc_or, gc_inv;
124 unsigned width, height;
129 BitmapRec bitmap[0x110000];
131 int render_width, render_height;
132 Pixmap raw_pixmap, seq_pixmap, gsub_pixmap, gpos_pixmap;
146 int do_alternate_subst;
147 unsigned glyph_width, glyph_height;
148 int glyph_x, glyph_y;
162 create_pixmap (int index)
164 int err = FT_Load_Glyph (face, index, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
170 bitmap[index].pixmap = none_pixmap;
173 ximage.height = face->glyph->bitmap.rows;
174 ximage.width = face->glyph->bitmap.width;
176 ximage.bits_per_pixel = 1;
178 ximage.format = XYPixmap;
179 ximage.data = (char *) face->glyph->bitmap.buffer;
180 ximage.byte_order = MSBFirst;
181 ximage.bitmap_unit = 8;
182 ximage.bitmap_bit_order = MSBFirst;
183 ximage.bitmap_pad = 8;
184 ximage.bytes_per_line = face->glyph->bitmap.pitch;
185 XInitImage (&ximage);
186 pixmap = XCreatePixmap (display, DefaultRootWindow (display),
187 glyph_width, glyph_height, 1);
188 XFillRectangle (display, pixmap, gc, 0, 0, glyph_width, glyph_height);
189 XPutImage (display, pixmap, gc, &ximage, 0, 0,
190 glyph_x + face->glyph->bitmap_left,
191 glyph_y - face->glyph->bitmap_top,
192 ximage.width, ximage.height);
193 bitmap[index].pixmap = pixmap;
194 bitmap[index].width = ximage.width;
195 bitmap[index].height = ximage.height;
196 bitmap[index].x = face->glyph->bitmap_left;
197 bitmap[index].y = - face->glyph->bitmap_top;
198 bitmap[index].advance = face->glyph->metrics.horiAdvance >> 6;
209 for (i = 0; i < 128; i++)
211 int index = glyph_index + i;
213 if (charmap_index >= 0)
214 index = FT_Get_Char_Index (face, (FT_ULong) index);
215 if (charmap_index >= 0 && ! index)
216 XtSetArg (arg[0], XtNbitmap, none_pixmap);
219 if (! bitmap[index].pixmap)
220 create_pixmap (index);
221 XtSetArg (arg[0], XtNbitmap, bitmap[index].pixmap);
223 XtSetValues (glyph[i], arg, 1);
226 msb = (glyph_index >> 7) % 2 ? 8 : 0;
227 for (i = 0; i < 8; i++)
231 sprintf (str, "%XX", i | msb );
232 XtSetArg (arg[0], XtNheight, glyph_height + 5);
233 XtSetArg (arg[1], XtNlabel, str);
234 XtSetValues (index_label[i], arg, 2);
237 if (glyph_index < 0x10000)
238 sprintf (buf, " %04X-%04X ", glyph_index, glyph_index + 0x7F);
240 sprintf (buf, "%06X-%06X", glyph_index, glyph_index + 0x7F);
241 XtSetArg (arg[0], XtNlabel, buf);
242 XtSetValues (range, arg, 1);
246 get_features (OTF_FeatureList *list, FeatureRec *rec)
251 if (! rec->langsys || ! rec->features || ! rec->features[0].on)
253 for (i = n = 0; i < rec->langsys->FeatureCount; i++)
255 if (rec->features[i].on)
260 str = malloc (n * 5);
261 for (i = 0, p = str; i < n; i++, p += 5)
263 OTF_tag_name (rec->features[i].tag, p);
271 #define DEVICE_DELTA(table, size) \
272 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
273 ? (table).DeltaValue[(size) >= (table).StartSize] \
277 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
278 OTF_Glyph *g, int *x, int *y)
280 if (anchor->AnchorFormat == 2)
283 int ap = anchor->f.f1.AnchorPoint;
285 FT_Load_Glyph (ft_face, (FT_UInt) g->glyph_id, FT_LOAD_MONOCHROME);
286 outline = &ft_face->glyph->outline;
287 if (ap < outline->n_points)
289 *x = outline->points[ap].x;
290 *y = outline->points[ap].y;
293 else if (anchor->AnchorFormat == 3)
295 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, pixel_size);
296 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, pixel_size);
304 OTF_GlyphString gstring;
305 OTF_Glyph *g, *prev, *base, *mark;
307 int len = glyph_rec.n_glyphs;
309 int unitsPerEm = face->units_per_EM;
311 gstring.size = gstring.used = len;
312 gstring.glyphs = malloc (sizeof (OTF_Glyph) * len);
313 memset (gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
314 for (i = 0; i < len; i++)
315 gstring.glyphs[i].c = gstring.glyphs[i].glyph_id = glyph_rec.glyphs[i];
317 XFillRectangle (display, seq_pixmap, gc, 0, 0, render_width, render_height);
318 XDrawLine (display, seq_pixmap, gc_set, 0, glyph_y, render_width, glyph_y);
323 OTF_drive_gdef (otf, &gstring);
326 str = get_features (&otf->gsub->FeatureList, &gsub);
329 if (do_alternate_subst)
330 OTF_drive_gsub_alternate (otf, &gstring, NULL, NULL, str);
332 OTF_drive_gsub (otf, &gstring, NULL, NULL, str);
338 str = get_features (&otf->gpos->FeatureList, &gpos);
341 OTF_drive_gpos (otf, &gstring, NULL, NULL, str);
352 for (prev = gstring.glyphs, g = gstring.glyphs + gstring.used - 1;
353 prev < g; prev++, g--)
354 temp = *prev, *prev = *g, *g = temp;
355 for (g = gstring.glyphs; g < gstring.glyphs + gstring.used; g++)
356 if (g->GlyphClass == 3)
360 while (g < gstring.glyphs + gstring.used && g->GlyphClass == 3)
362 for (g0 = g; prev < g0; prev++, g0--)
363 temp = *prev, *prev = *g, *g = temp;
369 for (i = 0, x = glyph_x, prev = NULL, g = gstring.glyphs;
370 i < gstring.used; i++, prev = g++)
372 BitmapRec *bmp = bitmap + gstring.glyphs[i].glyph_id;
373 int xoff = 0, yoff = 0;
375 int advance = bmp->advance;
379 create_pixmap (gstring.glyphs[i].glyph_id);
382 advance = bmp->advance;
384 switch (g->positioning_type)
391 int format = g->f.f1.format;
393 if (format & OTF_XPlacement)
394 xoff = g->f.f1.value->XPlacement * pixel_size / unitsPerEm;
395 if (format & OTF_XPlaDevice)
396 xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, pixel_size);
397 if (format & OTF_YPlacement)
398 yoff = g->f.f1.value->YPlacement * pixel_size / unitsPerEm;
399 if (format & OTF_YPlaDevice)
400 yoff += DEVICE_DELTA (g->f.f1.value->YPlaDevice, pixel_size);
401 if (format & OTF_XAdvance)
402 advance += g->f.f1.value->XAdvance * pixel_size / unitsPerEm;
403 if (format & OTF_XAdvDevice)
404 advance += DEVICE_DELTA (g->f.f1.value->XAdvDevice, pixel_size);
409 /* Not yet supported. */
415 prev_width = base_width;
416 goto label_adjust_anchor;
417 default: /* i.e. case 6 */
424 int base_x, base_y, mark_x, mark_y;
426 base_x = g->f.f4.base_anchor->XCoordinate * pixel_size / unitsPerEm;
427 base_y = g->f.f4.base_anchor->YCoordinate * pixel_size / unitsPerEm;
428 mark_x = g->f.f4.mark_anchor->XCoordinate * pixel_size / unitsPerEm;
429 mark_y = g->f.f4.mark_anchor->YCoordinate * pixel_size / unitsPerEm;
431 if (g->f.f4.base_anchor->AnchorFormat != 1)
432 adjust_anchor (g->f.f4.base_anchor, face, prev, &base_x, &base_y);
433 if (g->f.f4.mark_anchor->AnchorFormat != 1)
434 adjust_anchor (g->f.f4.mark_anchor, face, g, &mark_x, &mark_y);
435 xoff = (base_x - prev_width) - mark_x;
436 yoff = base_y - mark_y;
440 XCopyArea (display, bmp->pixmap, seq_pixmap, gc_or,
441 glyph_x + bmp->x, glyph_y + bmp->y, bmp->width, bmp->height,
442 x + bmp->x + xoff, glyph_y + bmp->y - yoff);
445 if (g->GlyphClass == OTF_GlyphClass0)
446 base = mark = g, base_width = advance;
447 else if (g->GlyphClass == OTF_GlyphClassMark)
450 base = g, base_width = advance;
452 free (gstring.glyphs);
454 XtSetArg (arg[0], XtNbitmap, seq_pixmap);
455 XtSetValues (seq_image, arg, 1);
460 update_render_area ()
466 XFillRectangle (display, raw_pixmap, gc, 0, 0, render_width, render_height);
467 for (i = 0, x = glyph_x; i < glyph_rec.n_glyphs; i++)
469 BitmapRec *bmp = bitmap + glyph_rec.glyphs[i];
472 XCopyArea (display, bmp->pixmap, raw_pixmap, gc,
473 0, 0, glyph_width, glyph_height,
474 (glyph_width + 4) * i + 1, 1);
475 XDrawRectangle (display, raw_pixmap, gc_set,
476 (glyph_width + 4) * i, 0,
477 glyph_width + 1, glyph_height + 1);
478 XDrawLine (display, raw_pixmap, gc_set,
479 (glyph_width + 4) * i + 1 + glyph_x, 1,
480 (glyph_width + 4) * i + 1 + glyph_x, glyph_height + 1);
481 XDrawLine (display, raw_pixmap, gc_set,
482 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance, 1,
483 (glyph_width + 4) * i + 1 + glyph_x + bmp->advance,
486 sprintf (buf, "%04X", glyph_rec.codes[i]);
487 XDrawString (display, raw_pixmap, gc_inv,
488 (glyph_width + 1) * i + 1
489 + (glyph_width - XTextWidth (font, buf, 4)) / 2,
490 glyph_height + 2 + FONT_HEIGHT, buf, 4);
492 XtSetArg (arg[0], XtNbitmap, raw_pixmap);
493 XtSetValues (raw_image, arg, 1);
498 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
500 XtAppSetExitFlag (XtWidgetToApplicationContext (w));
504 DumpProc (Widget w, XtPointer client_data, XtPointer call_data)
506 int g_width, g_height;
508 /* unit in points (1/72 inch); to fit in both US-letter and A4 */
509 static int xoff = 30, yoff = 30;
510 static int unit = 30;
511 static int margin = 2;
512 static int title_height = 20, label_height = 10;
513 int total_width = (unit + margin * 2) * 16;
514 int total_height = (unit + margin * 2 + label_height) * 16 + title_height;
515 /* pixel size (dots) */
518 char *name = alloca (strlen (filename) + 10);
520 int index = (glyph_index / 0x100) * 0x100;
523 g_width = face->bbox.xMax - face->bbox.xMin;
524 g_height = face->bbox.yMax - face->bbox.yMin;
525 if (g_width > g_height)
527 scale = g_width * size;
528 g_x = face->bbox.xMin * unit / g_width;
529 g_y = face->bbox.yMin * unit / g_width;
533 scale = g_height * size;
534 g_x = face->bbox.xMin * unit / g_height;
535 g_y = face->bbox.yMin * unit / g_height;
537 scale /= face->units_per_EM;
539 FT_Set_Pixel_Sizes (face, 0, size);
541 sprintf (name, "%s-%04X.ps", face->family_name, index);
542 printf ("Writing %s ... ", name);
544 fp = fopen (name, "w");
546 fprintf (fp, "%s\n", "%!PS-Adobe-2.0 EPSF-2.0");
547 fprintf (fp, "%s\n", "%%Creater: otfview");
548 fprintf (fp, "%s %s(%s)-%04X\n", "%%Title:",
549 face->family_name, face->style_name, index);
550 fprintf (fp, "%s\n", "%%Pages: 1");
551 fprintf (fp, "%s %d %d %d %d\n", "%%BoundingBox:",
552 xoff, yoff, xoff + total_width, yoff + total_height);
553 fprintf (fp, "%s\n", "%%EndComments");
554 fprintf (fp, "%s\n", "%%BeginProlog");
555 fprintf (fp, "/W %d def\n", unit + margin * 2);
556 fprintf (fp, "/H %d def\n", unit + margin * 2 + label_height);
557 fprintf (fp, "/STR 10 string def\n");
558 fprintf (fp, "/DrawIndex {\n");
559 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");
560 fprintf (fp, "} def\n");
561 fprintf (fp, "/DrawTitle {\n");
562 fprintf (fp, " /Courier findfont 20 scalefont setfont\n");
563 fprintf (fp, " %d %d 4 add moveto\n", xoff + total_width / 2,
564 yoff + total_height - title_height + 2);
565 fprintf (fp, " (%s(%s)-%04X) dup stringwidth pop 2 div neg 0 rmoveto show\n",
566 face->family_name, face->style_name, index);
567 fprintf (fp, "} def\n");
568 fprintf (fp, "/DrawFrame { gsave %d %d translate 0 setlinewidth\n",
570 fprintf (fp, " /Courier findfont 10 scalefont setfont\n");
571 fprintf (fp, " /I %d def\n", index);
572 fprintf (fp, " 0 1 16 { W mul 0 moveto 0 H 16 mul rlineto stroke } for\n");
573 fprintf (fp, " 0 1 16 { H mul 0 exch moveto W 16 mul 0 rlineto stroke } for\n");
574 fprintf (fp, " 0 1 15 { H mul %d add 0 exch moveto W 16 mul 0 rlineto stroke } for\n", label_height);
575 fprintf (fp, " 15 -1 0 { gsave H mul 0 exch translate 0 0 moveto\n");
576 fprintf (fp, " 0 1 15 { gsave W mul 0 moveto\n");
577 fprintf (fp, " 4 2 rmoveto DrawIndex /I I 1 add def grestore} for\n");
578 fprintf (fp, " grestore } for grestore } def\n");
579 fprintf (fp, "%s\n", "%%EndProlog");
580 fprintf (fp, "DrawTitle DrawFrame\n");
582 for (i = 0; i < 16; i++)
583 for (j = 0; j < 16; j++, index++)
587 if (charmap_index >= 0)
588 idx = FT_Get_Char_Index (face, (FT_ULong) index);
592 && FT_Load_Glyph (face, idx, FT_LOAD_RENDER | FT_LOAD_MONOCHROME) == 0
593 && face->glyph->bitmap.rows > 0
594 && face->glyph->bitmap.width > 0)
596 unsigned char *p = face->glyph->bitmap.buffer;
597 int width = (face->glyph->bitmap.width - 1) / 8 + 1;
599 fprintf (fp, "gsave %f %f translate %d %d scale 0 0 moveto\n",
600 xoff + (unit + margin * 2) * j + margin - g_x,
601 yoff + (unit + label_height + margin * 2) * (15 - i) + label_height + margin - g_y,
603 fprintf (fp, "%d %d true [%f 0 0 %f %d %d]\n",
604 width * 8, face->glyph->bitmap.rows,
605 scale, -scale, -face->glyph->bitmap_left,
606 face->glyph->bitmap_top);
608 for (k = 0; k < face->glyph->bitmap.rows;
609 k++, p += face->glyph->bitmap.pitch)
611 for (l = 0; l < width; l++)
612 fprintf (fp, "%02X", p[l]);
615 fprintf (fp, ">} imagemask grestore\n");
619 int boxsize = unit + margin * 2;
621 fprintf (fp, "gsave 0 setlinewidth %d %d translate\n",
623 yoff + (boxsize + label_height) * (15 - i) + label_height);
624 fprintf (fp, "0 0 moveto %d %d lineto stroke\n",
626 fprintf (fp, "0 %d moveto %d 0 lineto stroke grestore\n",
630 fprintf (fp, "showpage\n");
634 FT_Set_Pixel_Sizes (face, 0, (int) pixel_size);
639 GlyphProc (Widget w, XtPointer client_data, XtPointer call_data)
641 int old_glyph_index = glyph_index;
643 if ((int) client_data == -3 && glyph_index > 0)
645 else if ((int) client_data == -2 && glyph_index > 0)
646 glyph_index = (glyph_index - 1) & 0x1FF000;
647 else if ((int) client_data == -1 && glyph_index > 0)
649 else if ((int) client_data == 1 && glyph_index < 0x10FF80)
651 else if ((int) client_data == 2 && glyph_index < 0x10F000)
652 glyph_index = (glyph_index + 0x1000) & 0x1FF000;
653 else if ((int) client_data == 3 && glyph_index < 0x10F000)
654 glyph_index = 0x10FF80;
655 if (glyph_index != old_glyph_index)
656 update_glyph_area ();
660 CharmapProc (Widget w, XtPointer client_data, XtPointer call_data)
662 if (charmap_index == (int) client_data)
664 charmap_index = (int) client_data;
665 if (charmap_index >= 0)
666 FT_Set_Charmap (face, face->charmaps[charmap_index]);
667 update_glyph_area ();
671 RenderProc (Widget w, XtPointer client_data, XtPointer call_data)
673 if ((int) client_data < 0)
675 if (glyph_rec.n_glyphs > 0)
677 if ((int) client_data == -2)
678 glyph_rec.n_glyphs--;
680 glyph_rec.n_glyphs = 0;
681 update_render_area ();
684 else if (glyph_rec.n_glyphs < 64)
686 int index = glyph_index + (int) client_data;
688 if (charmap_index >= 0)
689 index = FT_Get_Char_Index (face, (FT_ULong) index);
690 if (bitmap[index].pixmap)
692 glyph_rec.codes[glyph_rec.n_glyphs] = glyph_index + (int) client_data;
693 glyph_rec.glyphs[glyph_rec.n_glyphs++] = index;
694 update_render_area ();
700 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
704 reversed = ! reversed;
706 XtSetArg (arg[0], XtNlabel, "L<-R");
708 XtSetArg (arg[0], XtNlabel, "L->R");
709 XtSetValues (w, arg, 1);
714 AltSubstProc (Widget w, XtPointer client_data, XtPointer call_data)
716 do_alternate_subst = ! do_alternate_subst;
721 FeatureProc (Widget w, XtPointer client_data, XtPointer call_data)
723 FeatureRec *rec = (FeatureRec *) client_data;
730 XtSetArg (arg[0], XtNlabel, &label);
731 XtGetValues (w, arg, 1);
732 if (! strcmp (label, "all"))
734 else if (! strcmp (label, "none"))
738 for (idx = 0; idx < rec->langsys->FeatureCount; idx++)
739 if (rec->features[idx].w == w)
741 if (idx == rec->langsys->FeatureCount)
748 for (i = j = 0; j < rec->langsys->FeatureCount; j++)
750 int index = rec->langsys->FeatureIndex[j];
753 = rec->gsub_gpos->FeatureList.Feature[index].FeatureTag;
754 rec->features[j].on = on;
759 OTF_Tag tag = rec->features[idx].tag;
762 if (rec->features[i].on)
765 j < rec->langsys->FeatureCount && rec->features[j].on; j++)
766 rec->features[j - 1].tag = rec->features[j].tag;
767 rec->features[j - 1].tag = tag;
768 rec->features[j - 1].on = 0;
772 for (j = i + 1; i > 0 && ! rec->features[i - 1].on; i--)
773 rec->features[i].tag = rec->features[i - 1].tag;
774 rec->features[i].tag = tag;
775 rec->features[i].on = 1;
783 if (rec->features[i].on)
785 XtSetArg (arg[0], XtNborderWidth, 3);
786 XtSetArg (arg[1], XtNinternalHeight, 2);
787 XtSetArg (arg[2], XtNinternalWidth, 2);
791 XtSetArg (arg[0], XtNborderWidth, 1);
792 XtSetArg (arg[1], XtNinternalHeight, 4);
793 XtSetArg (arg[2], XtNinternalWidth, 4);
795 OTF_tag_name (rec->features[i].tag, str);
796 XtSetArg (arg[3], XtNlabel, str);
797 XtSetValues (rec->features[i].w, arg, 4);
803 setup_feature_rec (FeatureRec *rec)
809 if (! rec->gsub_gpos)
811 for (i = 0; i < rec->gsub_gpos->ScriptList.ScriptCount; i++)
812 if (rec->gsub_gpos->ScriptList.Script[i].ScriptTag == script_tag)
814 OTF_Script *script = rec->gsub_gpos->ScriptList.Script + i;
818 for (j = 0; j < script->LangSysCount; j++)
819 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
821 rec->langsys = script->LangSys + j;
826 rec->langsys = &rec->gsub_gpos->ScriptList.Script[i].DefaultLangSys;
834 XtSetArg (arg[0], XtNborderWidth, 1);
835 XtSetArg (arg[1], XtNinternalHeight, 4);
836 XtSetArg (arg[2], XtNinternalWidth, 4);
837 XtSetArg (arg[3], XtNborderColor, foreground);
838 XtSetArg (arg[4], XtNsensitive, True);
839 for (i = 0; i < rec->langsys->FeatureCount; i++)
841 OTF_Feature *feature = rec->gsub_gpos->FeatureList.Feature;
842 int index = rec->langsys->FeatureIndex[i];
845 if (! rec->features[i].w)
847 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
848 rec->parent, arg, 0);
849 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
850 rec->features[i].w = w;
853 rec->features[i].tag = feature[index].FeatureTag;
854 rec->features[i].on = 0;
855 OTF_tag_name (rec->features[i].tag, label);
856 XtSetArg (arg[5], XtNlabel, label);
857 XtSetValues (rec->features[i].w, arg, 6);
860 XtSetArg (arg[0], XtNborderColor, background);
861 XtSetArg (arg[1], XtNsensitive, False);
862 XtSetArg (arg[2], XtNlabel, " ");
863 for (; i < rec->num_features; i++)
865 if (! rec->features[i].w)
867 Widget w = XtCreateManagedWidget ("", commandWidgetClass,
868 rec->parent, arg, 0);
869 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
870 rec->features[i].w = w;
872 XtSetValues (rec->features[i].w, arg, 3);
877 compose_script_langsys (OTF_Tag script, OTF_Tag langsys, char *name)
879 OTF_tag_name (script, name);
883 OTF_tag_name (langsys, name + 5);
890 decompose_script_langsys (OTF_Tag *script, OTF_Tag *langsys, char *name)
892 *script = OTF_tag (name);
894 *langsys = OTF_tag (name + 5);
900 ScriptProc (Widget w, XtPointer client_data, XtPointer call_data)
903 OTF_Tag script, langsys;
906 XtSetArg (arg[0], XtNlabel, &name);
907 XtGetValues (w, arg, 1);
908 decompose_script_langsys (&script, &langsys, name);
909 if (script_tag == script && langsys_tag == langsys)
912 langsys_tag = langsys;
913 setup_feature_rec (&gsub);
914 setup_feature_rec (&gpos);
919 create_otf_script_widgets (Widget prev)
931 XtSetArg (arg[0], XtNborderWidth, 0);
932 XtSetArg (arg[1], XtNleft, XawChainLeft);
933 XtSetArg (arg[2], XtNright, XawChainLeft);
934 XtSetArg (arg[3], XtNtop, XawChainTop);
935 XtSetArg (arg[4], XtNbottom, XawChainTop);
936 XtSetArg (arg[5], XtNfromVert, prev);
937 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
938 prev = XtCreateManagedWidget ("Script", boxWidgetClass, render_area, arg, 7);
939 XtCreateManagedWidget ("script(langsys)", labelWidgetClass, prev, arg, 1);
943 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
944 n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
946 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
947 n += otf->gpos->ScriptList.Script[i].LangSysCount + 1;
948 script_langsys = alloca ((sizeof script_langsys[0]) * n);
952 for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
954 OTF_Tag tag = otf->gsub->ScriptList.Script[i].ScriptTag;
956 script_langsys[n].script = tag;
957 script_langsys[n++].langsys = 0;
959 < otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount)
961 = otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount;
962 for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
964 script_langsys[n].script = tag;
965 script_langsys[n++].langsys
966 = otf->gsub->ScriptList.Script[i].LangSysRecord[j].LangSysTag;
968 < otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount)
970 = otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount;
973 gsub.num_features = nfeatures;
976 gsub.num_features = nfeatures;
977 gsub.features = malloc ((sizeof (FeatureElement)) * nfeatures);
978 memset (gsub.features, 0, (sizeof (FeatureElement)) * nfeatures);
983 for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
985 OTF_Tag tag = otf->gpos->ScriptList.Script[i].ScriptTag;
989 < otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount)
991 = otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount;
992 for (k = 0; k < prev_n; k++)
993 if (tag == script_langsys[k].script)
997 script_langsys[n].script = tag;
998 script_langsys[n++].langsys = 0;
1000 for (j = 0; j < otf->gpos->ScriptList.Script[i].LangSysCount; j++)
1006 OTF_Script *script = otf->gpos->ScriptList.Script + i;
1008 for (l = k; l < prev_n && tag == script_langsys[l].script; l++)
1009 if (script->LangSysRecord[j].LangSysTag
1010 == script_langsys[l].langsys)
1017 script_langsys[n].script = tag;
1018 script_langsys[n++].langsys = 0;
1021 < otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount)
1023 = otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount;
1029 gpos.num_features = nfeatures;
1030 gpos.features = malloc ((sizeof (FeatureElement)) * nfeatures);
1031 memset (gpos.features, 0, (sizeof (FeatureElement)) * nfeatures);
1037 script_tag = script_langsys[0].script;
1038 langsys_tag = script_langsys[0].langsys;
1039 compose_script_langsys (script_tag, langsys_tag, name);
1043 XtSetArg (arg[0], XtNforeground, background);
1044 XtSetArg (arg[1], XtNbackground, foreground);
1045 XtCreateManagedWidget (name, labelWidgetClass, prev, arg, 2);
1049 XtSetArg (arg[0], XtNstate, True);
1050 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1051 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1052 XtSetArg (arg[0], XtNradioGroup, w);
1053 for (i = 1; i < n; i++)
1055 compose_script_langsys (script_langsys[i].script,
1056 script_langsys[i].langsys, name);
1057 w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
1058 XtAddCallback (w, XtNcallback, ScriptProc, NULL);
1066 create_otf_widgets (Widget prev, FeatureRec *rec)
1071 XtSetArg (arg[0], XtNborderWidth, 0);
1072 XtSetArg (arg[1], XtNleft, XawChainLeft);
1073 XtSetArg (arg[2], XtNright, XawChainLeft);
1074 XtSetArg (arg[3], XtNtop, XawChainTop);
1075 XtSetArg (arg[4], XtNbottom, XawChainTop);
1076 XtSetArg (arg[5], XtNfromVert, prev);
1077 XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
1078 prev = XtCreateManagedWidget (rec->label, boxWidgetClass, render_area,
1080 XtCreateManagedWidget (rec->label, labelWidgetClass, prev, arg, 1);
1081 XtSetArg (arg[0], XtNborderWidth, 1);
1082 XtSetArg (arg[1], XtNinternalHeight, 4);
1083 XtSetArg (arg[2], XtNinternalWidth, 4);
1084 w = XtCreateManagedWidget ("all", commandWidgetClass, prev, arg, 3);
1085 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1086 w = XtCreateManagedWidget ("none", commandWidgetClass, prev, arg, 3);
1087 XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
1090 setup_feature_rec (rec);
1097 String quit_action = "<KeyPress>q: set() notify() unset()";
1098 String FIRST_action = "<KeyPress>f: set() notify() unset()\n\
1099 <KeyPress>Home: set() notify() unset()";
1100 String PREV_action = "Shift<KeyPress>p: set() notify() unset()\n\
1101 <KeyPress>Up: set() notify() unset()";
1102 String prev_action = "~Shift<KeyPress>p: set() notify() unset()\n\
1103 <KeyPress>Left: set() notify() unset()";
1104 String next_action = "~Shift<KeyPress>n: set() notify() unset()\n\
1105 <KeyPress>Right: set() notify() unset()";
1106 String NEXT_action = "Shift<KeyPress>n: set() notify() unset()\n\
1107 <KeyPress>Down: set() notify() unset()";
1108 String LAST_action = "<KeyPress>l: set() notify() unset()\n\
1109 <KeyPress>End: set() notify() unset()";
1113 String trans = "<Expose>: Expose()";
1115 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans));
1116 frame = XtCreateManagedWidget ("frame", formWidgetClass, shell, arg, 1);
1118 XtSetArg (arg[0], XtNleft, XawChainLeft);
1119 XtSetArg (arg[1], XtNright, XawChainLeft);
1120 XtSetArg (arg[2], XtNtop, XawChainTop);
1121 XtSetArg (arg[3], XtNbottom, XawChainTop);
1122 XtSetArg (arg[4], XtNborderWidth, 0);
1123 XtSetArg (arg[5], XtNorientation, XtorientHorizontal);
1124 command_area = XtCreateManagedWidget ("command-area", boxWidgetClass,
1126 XtSetArg (arg[6], XtNfromVert, command_area);
1127 navi_area = XtCreateManagedWidget ("navi-area", boxWidgetClass,
1129 XtSetArg (arg[4], XtNborderWidth, 0);
1130 XtSetArg (arg[5], XtNfromVert, navi_area);
1131 XtSetArg (arg[6], XtNdefaultDistance, 0);
1132 glyph_area = XtCreateManagedWidget ("glyph-area", formWidgetClass,
1134 XtSetArg (arg[5], XtNfromVert, glyph_area);
1135 render_area = XtCreateManagedWidget ("render-area", formWidgetClass,
1138 XtSetArg (arg[0], XtNaccelerators, XtParseAcceleratorTable (quit_action));
1139 quit = XtCreateManagedWidget ("Quit", commandWidgetClass,
1140 command_area, arg, 1);
1141 XtAddCallback (quit, XtNcallback, QuitProc, NULL);
1143 dump = XtCreateManagedWidget ("DumpImage", commandWidgetClass,
1144 command_area, arg, 1);
1145 XtAddCallback (dump, XtNcallback, DumpProc, NULL);
1147 XtSetArg (arg[0], XtNborderWidth, 0);
1148 XtSetArg (arg[1], XtNwidth, 10);
1149 XtCreateManagedWidget ("spacer", boxWidgetClass, command_area, arg, 2);
1151 charmap = alloca (sizeof (Widget) * (face->num_charmaps + 1));
1152 XtSetArg (arg[0], XtNstate, True);
1153 charmap[0] = XtCreateManagedWidget (charmap_rec[0].name, toggleWidgetClass,
1154 command_area, arg, 1);
1155 XtAddCallback (charmap[0], XtNcallback, CharmapProc, (XtPointer) -1);
1156 XtSetArg (arg[0], XtNradioGroup, charmap[0]);
1157 for (i = 0; i < face->num_charmaps; i++)
1159 charmap[i + 1] = XtCreateManagedWidget (charmap_rec[i + 1].name,
1161 command_area, arg, 1);
1162 XtAddCallback (charmap[i + 1], XtNcallback, CharmapProc, (XtPointer) i);
1165 XtSetArg (arg[0], XtNlabel, " |< (f)");
1166 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (FIRST_action));
1167 FIRST = XtCreateManagedWidget ("FIRST", commandWidgetClass,
1169 XtAddCallback (FIRST, XtNcallback, GlyphProc, (XtPointer) -3);
1170 XtSetArg (arg[0], XtNlabel, "<< (P)");
1171 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (PREV_action));
1172 PREV = XtCreateManagedWidget ("PREV", commandWidgetClass,
1174 XtAddCallback (PREV, XtNcallback, GlyphProc, (XtPointer) -2);
1175 XtSetArg (arg[0], XtNlabel, "< (p)");
1176 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (prev_action));
1177 prev = XtCreateManagedWidget ("prev", commandWidgetClass,
1179 XtAddCallback (prev, XtNcallback, GlyphProc, (XtPointer) -1);
1180 XtSetArg (arg[0], XtNlabel, " 0000 ");
1181 range = XtCreateManagedWidget ("range", labelWidgetClass,
1183 XtSetArg (arg[0], XtNforeground, &foreground);
1184 XtSetArg (arg[1], XtNbackground, &background);
1185 XtGetValues (range, arg, 2);
1187 XtSetArg (arg[0], XtNlabel, "> (n)");
1188 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (next_action));
1189 next = XtCreateManagedWidget ("next", commandWidgetClass,
1191 XtAddCallback (next, XtNcallback, GlyphProc, (XtPointer) 1);
1192 XtSetArg (arg[0], XtNlabel, ">> (N)");
1193 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (NEXT_action));
1194 NEXT = XtCreateManagedWidget ("NEXT", commandWidgetClass,
1196 XtAddCallback (NEXT, XtNcallback, GlyphProc, (XtPointer) 2);
1197 XtSetArg (arg[0], XtNlabel, ">| (l)");
1198 XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (LAST_action));
1199 LAST = XtCreateManagedWidget ("LAST", commandWidgetClass,
1201 XtAddCallback (LAST, XtNcallback, GlyphProc, (XtPointer) 3);
1203 XtSetArg (arg[0], XtNleft, XawChainLeft);
1204 XtSetArg (arg[1], XtNright, XawChainLeft);
1205 XtSetArg (arg[2], XtNtop, XawChainTop);
1206 XtSetArg (arg[3], XtNbottom, XawChainTop);
1208 for (i = 0; i < 8; i++)
1214 sprintf (str, "%XX", i);
1215 XtSetArg (arg[n], XtNheight, glyph_height + 5), n++;
1216 XtSetArg (arg[n], XtNlabel, str), n++;
1217 XtSetArg (arg[n], XtNborderWidth, 0), n++;
1219 XtSetArg (arg[n], XtNfromVert, w), n++;
1220 head = XtCreateManagedWidget (str, labelWidgetClass, glyph_area, arg, n);
1221 index_label[i] = head;
1222 for (j = 0; j < 16; j++)
1228 XtSetArg (arg[n], XtNfromVert, w), n++;
1230 XtSetArg (arg[n], XtNfromHoriz, head), n++;
1232 XtSetArg (arg[n], XtNfromHoriz, glyph[k - 1]), n++;
1233 XtSetArg (arg[n], XtNbitmap, none_pixmap), n++;
1234 glyph[k] = XtCreateManagedWidget ("glyph", commandWidgetClass,
1235 glyph_area, arg, n);
1236 XtAddCallback (glyph[k], XtNcallback, RenderProc, (XtPointer) k);
1240 /* 10 = (1 (border_width) + 4 (inner_width)) * 2 */
1241 XtSetArg(arg[4], XtNwidth, glyph_width + 10);
1242 XtSetArg (arg[5], XtNfromVert, glyph[112]);
1243 XtSetArg (arg[6], XtNfromHoriz, w);
1244 XtSetArg (arg[7], XtNborderWidth, 0);
1246 for (j = 0; j < 16; j++)
1250 sprintf (str, "X%X", j);
1251 XtSetArg (arg[8], XtNlabel, str);
1252 w = XtCreateManagedWidget ("idx", labelWidgetClass, glyph_area, arg, 9);
1253 XtSetArg (arg[6], XtNfromHoriz, w);
1256 XtSetArg (arg[0], XtNleft, XawChainLeft);
1257 XtSetArg (arg[1], XtNright, XawChainLeft);
1258 XtSetArg (arg[2], XtNtop, XawChainTop);
1259 XtSetArg (arg[3], XtNbottom, XawChainTop);
1260 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1261 XtSetArg (arg[5], XtNborderWidth, 0);
1262 w = XtCreateManagedWidget ("clear-box", boxWidgetClass, render_area, arg, 6);
1263 clear = XtCreateManagedWidget ("clear", commandWidgetClass, w, arg, 0);
1264 XtAddCallback (clear, XtNcallback, RenderProc, (XtPointer) -1);
1265 del = XtCreateManagedWidget ("delete", commandWidgetClass, w, arg, 0);
1266 XtAddCallback (del, XtNcallback, RenderProc, (XtPointer) -2);
1267 bidi = XtCreateManagedWidget ("L->R", toggleWidgetClass, w, arg, 0);
1268 XtAddCallback (bidi, XtNcallback, BidiProc, NULL);
1269 alt_subst = XtCreateManagedWidget ("AltSubst", toggleWidgetClass, w, arg, 0);
1270 XtAddCallback (alt_subst, XtNcallback, AltSubstProc, NULL);
1272 XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
1273 XtSetArg (arg[5], XtNborderWidth, 0);
1274 XtSetArg (arg[6], XtNfromVert, w);
1275 raw = XtCreateManagedWidget ("raw", boxWidgetClass, render_area, arg, 7);
1277 XtSetArg (arg[0], XtNborderWidth, 0);
1278 XtSetArg (arg[1], XtNlabel, "raw: ");
1279 raw_label = XtCreateManagedWidget ("raw-label", labelWidgetClass,
1281 XtSetArg (arg[1], XtNbitmap, raw_pixmap);
1282 raw_image = XtCreateManagedWidget ("raw-image", labelWidgetClass,
1287 OTF_get_table (otf, "GSUB");
1288 OTF_get_table (otf, "GPOS");
1289 w = create_otf_script_widgets (w);
1292 gsub.label = "GSUB";
1293 gsub.gsub_gpos = otf->gsub;
1294 w = create_otf_widgets (w, &gsub);
1298 gpos.label = "GPOS";
1299 gpos.gsub_gpos = otf->gpos;
1300 w = create_otf_widgets (w, &gpos);
1304 XtSetArg (arg[6], XtNfromVert, w);
1305 seq = XtCreateManagedWidget ("seq", boxWidgetClass, render_area, arg, 7);
1306 XtSetArg (arg[0], XtNborderWidth, 0);
1307 XtSetArg (arg[1], XtNlabel, "seq: ");
1308 seq_label = XtCreateManagedWidget ("seq-label", labelWidgetClass,
1310 XtSetArg (arg[1], XtNbitmap, seq_pixmap);
1311 seq_image = XtCreateManagedWidget ("seq-image", labelWidgetClass,
1313 XtInstallAllAccelerators (shell, shell);
1317 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1319 XTextProperty text_prop;
1320 char *pname = "otfview";
1321 char *fname = basename (filename);
1322 char *name = alloca (strlen (fname) + 3 + strlen (pname) + 1);
1324 sprintf (name, "%s - %s", pname, fname);
1325 text_prop.value = (unsigned char *) name;
1326 text_prop.encoding = XA_STRING;
1327 text_prop.format = 8;
1328 text_prop.nitems = strlen (name);
1329 XSetWMName (display, XtWindow (shell), &text_prop);
1332 /* Format MSG by FMT and print the result to the stderr, and exit. */
1334 #define FATAL_ERROR(fmt, arg) \
1336 fprintf (stderr, fmt, arg); \
1341 x_error_handler (Display *display, XErrorEvent *error)
1347 help (char **argv, int err)
1349 FILE *fp = err ? stderr : stdout;
1351 fprintf (fp, "Usage: %s [ X-OPTION ... ] OTF-FILE [INDEX]\n",
1352 basename (argv[0]));
1353 fprintf (fp, " Environment variable PIXEL_SIZE specifies the pixel size.\n");
1354 fprintf (fp, " The default pixel size is %d, but is reduced\n",
1355 DEFAULT_PIXEL_SIZE);
1356 fprintf (fp, " if your screen is not that wide.\n");
1361 main (int argc, char **argv)
1363 XtActionsRec actions[] = { {"Expose", ExposeProc} };
1367 OTF_GlyphString gstring;
1372 int fixed_pixel_size = 0;
1375 pixel_size = DEFAULT_PIXEL_SIZE;
1377 char *str = getenv ("PIXEL_SIZE");
1379 if (str && (i = atoi (str)) > 0)
1382 fixed_pixel_size = 1;
1386 gstring.size = gstring.used = 256;
1387 g = calloc (256, sizeof (OTF_Glyph));
1390 shell = XtOpenApplication (&context, "OTFView", NULL, 0, &argc, argv, NULL,
1391 shellWidgetClass, arg, 0);
1392 display = XtDisplay (shell);
1393 /*XSynchronize (display, True);*/
1394 XSetErrorHandler (x_error_handler);
1395 display_width = DisplayWidth (display,
1396 XScreenNumberOfScreen (XtScreen (shell)));
1397 font = XLoadQueryFont (display, DEFAULT_FONT_NAME);
1399 font = XLoadQueryFont (display, "fixed");
1403 if (!strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
1408 fontindex = atoi (argv[2]);
1410 FATAL_ERROR ("Invalid font index: %d\n", fontindex);
1413 if ((err = FT_Init_FreeType (&library)))
1414 FATAL_ERROR ("%s\n", "FT_Init_FreeType: error");
1415 err = FT_New_Face (library, filename, fontindex, &face);
1416 if (err == FT_Err_Unknown_File_Format)
1417 FATAL_ERROR ("%s\n", "FT_New_Face: unknown file format");
1419 FATAL_ERROR ("%s\n", "FT_New_Face: unknown error (invalid face index?)");
1420 if ((err = FT_Set_Pixel_Sizes (face, 0, pixel_size)))
1421 FATAL_ERROR ("%s\n", "FT_Set_Pixel_Sizes: error");
1423 if (strstr (filename, ".ttf")
1424 || strstr (filename, ".TTF")
1425 || strstr (filename, ".otf")
1426 || strstr (filename, ".OTF"))
1428 otf = OTF_open_ft_face (face);
1430 || OTF_get_table (otf, "head") < 0
1431 || OTF_get_table (otf, "cmap") < 0
1432 || (OTF_check_table (otf, "GSUB") < 0
1433 && OTF_check_table (otf, "GPOS") < 0))
1441 filename = basename (filename);
1442 sprintf (title, "%s family:%s style:%s",
1443 filename, face->family_name, face->style_name);
1444 XtSetArg (arg[0], XtNtitle, title);
1445 XtSetValues (shell, arg, 1);
1448 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1449 * pixel_size / face->units_per_EM);
1450 if (! fixed_pixel_size && glyph_width * 16 > display_width * 0.8)
1452 pixel_size = (pixel_size * display_width * 0.8 / 16 / glyph_width);
1453 FT_Set_Pixel_Sizes (face, 0, pixel_size);
1454 glyph_width = ((face->bbox.xMax - face->bbox.xMin)
1455 * pixel_size / face->units_per_EM);
1457 if (glyph_width < FONT_WIDTH * 4)
1458 glyph_width = FONT_WIDTH * 4;
1460 glyph_height = ((face->bbox.yMax - face->bbox.yMin)
1461 * pixel_size / face->units_per_EM);
1463 glyph_x = - (face->bbox.xMin * pixel_size / face->units_per_EM);
1464 glyph_y = face->bbox.yMax * pixel_size / face->units_per_EM;
1465 none_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1466 glyph_width, glyph_height, 1);
1469 unsigned long valuemask = GCFunction | GCLineWidth;
1472 gc = XCreateGC (display, none_pixmap, (unsigned long) 0, NULL);
1473 values.function = GXset;
1474 values.line_width = 1;
1475 gc_set = XCreateGC (display, none_pixmap, valuemask, &values);
1476 values.function = GXor;
1477 gc_or = XCreateGC (display, none_pixmap, valuemask, &values);
1478 values.function = GXcopyInverted;
1479 gc_inv = XCreateGC (display, none_pixmap, valuemask, &values);
1482 XFillRectangle (display, none_pixmap, gc, 0, 0,
1483 glyph_width, glyph_height);
1484 XDrawString (display, none_pixmap, gc_inv,
1485 (glyph_width - XTextWidth (font, "none", 4)) / 2,
1486 glyph_height / 2, "none", 4);
1488 render_width = (glyph_width + 4) * 15 + 1;
1489 render_height = glyph_height + 2;
1491 charmap_rec[0].platform_id = -1;
1492 charmap_rec[0].encoding_id = -1;
1493 strcpy (charmap_rec[0].name, "no charmap");
1495 for (i = 0; i < face->num_charmaps; i++)
1497 charmap_rec[i + 1].platform_id = face->charmaps[i]->platform_id;
1498 charmap_rec[i + 1].encoding_id = face->charmaps[i]->encoding_id;
1499 sprintf (charmap_rec[i + 1].name, "%d-%d",
1500 charmap_rec[i + 1].platform_id, charmap_rec[i + 1].encoding_id);
1501 if (face->charmaps[i]->platform_id == 0
1502 || (face->charmaps[i]->platform_id == 3
1503 && face->charmaps[i]->encoding_id == 1))
1504 strcat (charmap_rec[i + 1].name, " (unicode)");
1505 else if (face->charmaps[i]->platform_id == 1
1506 && face->charmaps[i]->encoding_id == 0)
1507 strcat (charmap_rec[i + 1].name, " (apple-roman)");
1510 raw_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1511 render_width, render_height, 1);
1512 seq_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
1513 render_width, render_height, 1);
1515 memset (bitmap, 0, sizeof (bitmap));
1519 update_glyph_area ();
1520 update_render_area ();
1522 XtAppAddActions (context, actions, XtNumber (actions));
1523 XtRealizeWidget (shell);
1524 XtAppMainLoop (context);
1529 #else /* not HAVE_X11_XAW_COMMAND_H */
1532 main (int argc, char **argv)
1535 "Building of this program failed (lack of some header files)\n");