+/* otfview.c -- View glyphs of OpenType fonts.
+
+Copyright (C) 2003, 2004, 2005
+ National Institute of Advanced Industrial Science and Technology (AIST)
+ Registration Number H15PRO167
+
+This file is part of libotf.
+
+Libotf is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as published
+by the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+Libotf is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library, in a file named COPYING; if not,
+write to the Free Software Foundation, Inc., 59 Temple Place, Suite
+330, Boston, MA 02111-1307, USA. */
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
+#include "config.h"
+
+#ifdef HAVE_X11_XAW_COMMAND_H
+
+#include <X11/Xatom.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <otf.h>
#define DEFAULT_PIXEL_SIZE 30
+int pixel_size;
+
#define DEFAULT_FONT_NAME "6x13"
XFontStruct *font;
#define FONT_HEIGHT (font->ascent + font->descent)
+#define FONT_ASCENT (font->ascent)
#define FONT_DESCENT (font->descent)
#define FONT_WIDTH (font->max_bounds.width)
/* Widget structure.
+--- frame (form) -------------------------+
| +--- command_area (box) ---------------+ |
- | | quit charmap ... | |
+ | | quit dump charmap ... | |
| +--------------------------------------+ |
| +---- navi_area (box) -----------------+ |
- | | FIRST PREV prev label next NEXT LAST | |
+ | | FIRST PREV prev range next NEXT LAST | |
| +--------------------------------------+ |
| +--- glyph_area (form) ----------------+ |
- | | glyph[0] ... glyph[15] | |
+ | | idxh[0] glyph[0] ... glyph[15] | |
| | ... ... | |
- | | glyph[112] ... glyph[127]| |
+ | | idxh[7] glyph[112] ... glyph[127]| |
+ | | idxl[0] ... idxl[15] | |
| +--------------------------------------+ |
| +--- render_area (form) ---------------+ |
- | | clear | |
+ | | clear del bidi alt_subst | |
| | +--- raw (box) --------------------+ | |
| | | raw_label raw_image | | |
+ | | +----------------------------------+ | |
+ | | GSUB all none features... | |
+ | | GPOS all none features... | |
| | +--- seq (box) --------------------+ | |
| | | seq_label seq_image | | |
- | | +--- gsub (box) -------------------+ | |
- | | | gsub_label gsub_image | | |
- | | +--- gpos (box) -------------------+ | |
- | | | gpos_label gpos_image | | |
| | +----------------------------------+ | |
| +--------------------------------------+ |
+------------------------------------------+ */
Widget shell, frame;
-Widget command_area, quit, *charmap;
-Widget navi_area, FIRST, PREV, prev, label, next, NEXT, LAST;
-Widget glyph_area, glyph[128];
-Widget render_area, clear, raw, seq, gsub, gpos;
+Widget command_area, quit, dump, *charmap;
+Widget navi_area, FIRST, PREV, prev, range, next, NEXT, LAST;
+Widget glyph_area, glyph[128], index_label[8];
+Widget render_area, clear, del, bidi, alt_subst, raw, seq;
Widget raw_label, raw_image, seq_label, seq_image;
-Widget gsub_label, gsub_image, gpos_label, gpos_image;
+unsigned long foreground, background;
+
+typedef struct
+{
+ OTF_Tag tag;
+ int on;
+ Widget w;
+} FeatureElement;
+
+typedef struct
+{
+ char *label;
+ OTF_GSUB_GPOS *gsub_gpos;
+ OTF_LangSys *langsys;
+ int num_features;
+ FeatureElement *features;
+ Widget parent;
+} FeatureRec;
+
+FeatureRec gsub, gpos;
+
+/* Currently selected script and langsys. */
+OTF_Tag script_tag, langsys_tag;
int glyph_char[128];
int advance;
} BitmapRec;
-BitmapRec bitmap[0x10000];
+BitmapRec bitmap[0x110000];
int render_width, render_height;
Pixmap raw_pixmap, seq_pixmap, gsub_pixmap, gpos_pixmap;
int charmap_index;
+int reversed;
+int do_alternate_subst;
unsigned glyph_width, glyph_height;
int glyph_x, glyph_y;
int glyph_index;
} glyph_rec;
OTF *otf;
+char *filename;
+int fontindex;
void
-create_pixmap (int pixel_size, int index)
+create_pixmap (int index)
{
int err = FT_Load_Glyph (face, index, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
XImage ximage;
Pixmap pixmap;
- int height = glyph_height + 1 + FONT_HEIGHT;
- char index_buf[5];
if (err)
{
- bitmap[index].pixmap = (Pixmap) 0;
+ bitmap[index].pixmap = none_pixmap;
return;
}
ximage.height = face->glyph->bitmap.rows;
ximage.bytes_per_line = face->glyph->bitmap.pitch;
XInitImage (&ximage);
pixmap = XCreatePixmap (display, DefaultRootWindow (display),
- glyph_width, height, 1);
- XFillRectangle (display, pixmap, gc, 0, 0, glyph_width, height);
+ glyph_width, glyph_height, 1);
+ XFillRectangle (display, pixmap, gc, 0, 0, glyph_width, glyph_height);
XPutImage (display, pixmap, gc, &ximage, 0, 0,
glyph_x + face->glyph->bitmap_left,
glyph_y - face->glyph->bitmap_top,
ximage.width, ximage.height);
- sprintf (index_buf, "%04X", index);
- XDrawLine (display, pixmap, gc_inv,
- 0, glyph_height + 1, glyph_width, glyph_height + 1);
- XDrawString (display, pixmap, gc_inv,
- (glyph_width - XTextWidth (font, index_buf, 4)) / 2,
- height - FONT_DESCENT, index_buf, 4);
bitmap[index].pixmap = pixmap;
bitmap[index].width = ximage.width;
bitmap[index].height = ximage.height;
int i;
Arg arg[2];
char buf[16];
+ int msb;
for (i = 0; i < 128; i++)
{
if (charmap_index >= 0)
index = FT_Get_Char_Index (face, (FT_ULong) index);
- if (bitmap[index].pixmap)
- XtSetArg (arg[0], XtNbitmap, bitmap[index].pixmap);
- else
+ if (charmap_index >= 0 && ! index)
XtSetArg (arg[0], XtNbitmap, none_pixmap);
+ else
+ {
+ if (! bitmap[index].pixmap)
+ create_pixmap (index);
+ XtSetArg (arg[0], XtNbitmap, bitmap[index].pixmap);
+ }
XtSetValues (glyph[i], arg, 1);
}
- sprintf (buf, " %04X-%04X ", glyph_index, glyph_index + 0x7F);
+ msb = (glyph_index >> 7) % 2 ? 8 : 0;
+ for (i = 0; i < 8; i++)
+ {
+ char str[3];
+
+ sprintf (str, "%XX", i | msb );
+ XtSetArg (arg[0], XtNheight, glyph_height + 5);
+ XtSetArg (arg[1], XtNlabel, str);
+ XtSetValues (index_label[i], arg, 2);
+ }
+
+ if (glyph_index < 0x10000)
+ sprintf (buf, " %04X-%04X ", glyph_index, glyph_index + 0x7F);
+ else
+ sprintf (buf, "%06X-%06X", glyph_index, glyph_index + 0x7F);
XtSetArg (arg[0], XtNlabel, buf);
- XtSetValues (label, arg, 1);
+ XtSetValues (range, arg, 1);
+}
+
+char *
+get_features (OTF_FeatureList *list, FeatureRec *rec)
+{
+ int i, n;
+ char *str, *p;
+
+ if (! rec->langsys || ! rec->features || ! rec->features[0].on)
+ return NULL;
+ for (i = n = 0; i < rec->langsys->FeatureCount; i++)
+ {
+ if (rec->features[i].on)
+ n++;
+ else
+ break;
+ }
+ str = malloc (n * 5);
+ for (i = 0, p = str; i < n; i++, p += 5)
+ {
+ OTF_tag_name (rec->features[i].tag, p);
+ p[4] = ',';
+ }
+ p[-1] = '\0';
+ return str;
+}
+
+
+#define DEVICE_DELTA(table, size) \
+ (((size) >= (table).StartSize && (size) <= (table).EndSize) \
+ ? (table).DeltaValue[(size) >= (table).StartSize] \
+ : 0)
+
+void
+adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
+ OTF_Glyph *g, int *x, int *y)
+{
+ if (anchor->AnchorFormat == 2)
+ {
+ FT_Outline *outline;
+ int ap = anchor->f.f1.AnchorPoint;
+
+ FT_Load_Glyph (ft_face, (FT_UInt) g->glyph_id, FT_LOAD_MONOCHROME);
+ outline = &ft_face->glyph->outline;
+ if (ap < outline->n_points)
+ {
+ *x = outline->points[ap].x;
+ *y = outline->points[ap].y;
+ }
+ }
+ else if (anchor->AnchorFormat == 3)
+ {
+ *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, pixel_size);
+ *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, pixel_size);
+ }
}
void
+update_seq_area ()
+{
+ int i, x;
+ OTF_GlyphString gstring;
+ OTF_Glyph *g, *prev, *base, *mark;
+ int base_width;
+ int len = glyph_rec.n_glyphs;
+ Arg arg[1];
+ int unitsPerEm = face->units_per_EM;
+
+ gstring.size = gstring.used = len;
+ gstring.glyphs = malloc (sizeof (OTF_Glyph) * len);
+ memset (gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
+ for (i = 0; i < len; i++)
+ gstring.glyphs[i].c = gstring.glyphs[i].glyph_id = glyph_rec.glyphs[i];
+
+ XFillRectangle (display, seq_pixmap, gc, 0, 0, render_width, render_height);
+ XDrawLine (display, seq_pixmap, gc_set, 0, glyph_y, render_width, glyph_y);
+ if (otf)
+ {
+ char *str;
+
+ OTF_drive_gdef (otf, &gstring);
+ if (otf->gsub)
+ {
+ str = get_features (&otf->gsub->FeatureList, &gsub);
+ if (str)
+ {
+ if (do_alternate_subst)
+ OTF_drive_gsub_alternate (otf, &gstring, NULL, NULL, str);
+ else
+ OTF_drive_gsub (otf, &gstring, NULL, NULL, str);
+ free (str);
+ }
+ }
+ if (otf->gpos)
+ {
+ str = get_features (&otf->gpos->FeatureList, &gpos);
+ if (str)
+ {
+ OTF_drive_gpos (otf, &gstring, NULL, NULL, str);
+ free (str);
+ }
+ }
+ }
+
+ prev = NULL;
+ if (reversed)
+ {
+ OTF_Glyph temp;
+
+ for (prev = gstring.glyphs, g = gstring.glyphs + gstring.used - 1;
+ prev < g; prev++, g--)
+ temp = *prev, *prev = *g, *g = temp;
+ for (g = gstring.glyphs; g < gstring.glyphs + gstring.used; g++)
+ if (g->GlyphClass == 3)
+ {
+ OTF_Glyph *g0;
+ prev = g++;
+ while (g < gstring.glyphs + gstring.used && g->GlyphClass == 3)
+ g++;
+ for (g0 = g; prev < g0; prev++, g0--)
+ temp = *prev, *prev = *g, *g = temp;
+ }
+ }
+
+
+ mark = base = NULL;
+ for (i = 0, x = glyph_x, prev = NULL, g = gstring.glyphs;
+ i < gstring.used; i++, prev = g++)
+ {
+ BitmapRec *bmp = bitmap + gstring.glyphs[i].glyph_id;
+ int xoff = 0, yoff = 0;
+ int prev_width;
+ int advance = bmp->advance;
+
+ if (! bmp->pixmap)
+ {
+ create_pixmap (gstring.glyphs[i].glyph_id);
+ if (! bmp->pixmap)
+ continue;
+ advance = bmp->advance;
+ }
+ switch (g->positioning_type)
+ {
+ case 0:
+ break;
+
+ case 1: case 2:
+ {
+ int format = g->f.f1.format;
+
+ if (format & OTF_XPlacement)
+ xoff = g->f.f1.value->XPlacement * pixel_size / unitsPerEm;
+ if (format & OTF_XPlaDevice)
+ xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, pixel_size);
+ if (format & OTF_YPlacement)
+ yoff = g->f.f1.value->YPlacement * pixel_size / unitsPerEm;
+ if (format & OTF_YPlaDevice)
+ yoff += DEVICE_DELTA (g->f.f1.value->YPlaDevice, pixel_size);
+ if (format & OTF_XAdvance)
+ advance += g->f.f1.value->XAdvance * pixel_size / unitsPerEm;
+ if (format & OTF_XAdvDevice)
+ advance += DEVICE_DELTA (g->f.f1.value->XAdvDevice, pixel_size);
+ }
+ break;
+
+ case 3:
+ /* Not yet supported. */
+ break;
+ case 4: case 5:
+ if (! base)
+ break;
+ prev = base;
+ prev_width = base_width;
+ goto label_adjust_anchor;
+ default: /* i.e. case 6 */
+ if (! mark)
+ break;
+ prev = mark;
+ prev_width = 0;
+ label_adjust_anchor:
+ {
+ int base_x, base_y, mark_x, mark_y;
+
+ base_x = g->f.f4.base_anchor->XCoordinate * pixel_size / unitsPerEm;
+ base_y = g->f.f4.base_anchor->YCoordinate * pixel_size / unitsPerEm;
+ mark_x = g->f.f4.mark_anchor->XCoordinate * pixel_size / unitsPerEm;
+ mark_y = g->f.f4.mark_anchor->YCoordinate * pixel_size / unitsPerEm;
+
+ if (g->f.f4.base_anchor->AnchorFormat != 1)
+ adjust_anchor (g->f.f4.base_anchor, face, prev, &base_x, &base_y);
+ if (g->f.f4.mark_anchor->AnchorFormat != 1)
+ adjust_anchor (g->f.f4.mark_anchor, face, g, &mark_x, &mark_y);
+ xoff = (base_x - prev_width) - mark_x;
+ yoff = base_y - mark_y;
+ }
+ }
+
+ XCopyArea (display, bmp->pixmap, seq_pixmap, gc_or,
+ glyph_x + bmp->x, glyph_y + bmp->y, bmp->width, bmp->height,
+ x + bmp->x + xoff, glyph_y + bmp->y - yoff);
+ x += advance;
+
+ if (g->GlyphClass == OTF_GlyphClass0)
+ base = mark = g, base_width = advance;
+ else if (g->GlyphClass == OTF_GlyphClassMark)
+ mark = g;
+ else
+ base = g, base_width = advance;
+ }
+ free (gstring.glyphs);
+
+ XtSetArg (arg[0], XtNbitmap, seq_pixmap);
+ XtSetValues (seq_image, arg, 1);
+}
+
+
+void
update_render_area ()
{
int i;
Arg arg[1];
XFillRectangle (display, raw_pixmap, gc, 0, 0, render_width, render_height);
- XFillRectangle (display, seq_pixmap, gc, 0, 0, render_width, render_height);
for (i = 0, x = glyph_x; i < glyph_rec.n_glyphs; i++)
{
BitmapRec *bmp = bitmap + glyph_rec.glyphs[i];
XCopyArea (display, bmp->pixmap, raw_pixmap, gc,
0, 0, glyph_width, glyph_height,
- (glyph_width + 1) * i + 1, 1);
+ (glyph_width + 4) * i + 1, 1);
XDrawRectangle (display, raw_pixmap, gc_set,
- (glyph_width + 1) * i, 0,
+ (glyph_width + 4) * i, 0,
glyph_width + 1, glyph_height + 1);
XDrawLine (display, raw_pixmap, gc_set,
- (glyph_width + 1) * i + 1 + glyph_x, 1,
- (glyph_width + 1) * i + 1 + glyph_x, glyph_height + 1);
+ (glyph_width + 4) * i + 1 + glyph_x, 1,
+ (glyph_width + 4) * i + 1 + glyph_x, glyph_height + 1);
XDrawLine (display, raw_pixmap, gc_set,
- (glyph_width + 1) * i + 1 + glyph_x + bmp->advance, 1,
- (glyph_width + 1) * i + 1 + glyph_x + bmp->advance,
+ (glyph_width + 4) * i + 1 + glyph_x + bmp->advance, 1,
+ (glyph_width + 4) * i + 1 + glyph_x + bmp->advance,
glyph_height + 1);
sprintf (buf, "%04X", glyph_rec.codes[i]);
(glyph_width + 1) * i + 1
+ (glyph_width - XTextWidth (font, buf, 4)) / 2,
glyph_height + 2 + FONT_HEIGHT, buf, 4);
- XCopyArea (display, bmp->pixmap, seq_pixmap, gc_or,
- glyph_x + bmp->x, glyph_y + bmp->y, bmp->width, bmp->height,
- x + bmp->x, glyph_y + bmp->y);
- x += bmp->advance;
}
XtSetArg (arg[0], XtNbitmap, raw_pixmap);
XtSetValues (raw_image, arg, 1);
- XtSetArg (arg[0], XtNbitmap, seq_pixmap);
- XtSetValues (seq_image, arg, 1);
- if (! otf)
- return;
- XFillRectangle (display, gsub_pixmap, gc, 0, 0, render_width, render_height);
- XFillRectangle (display, gpos_pixmap, gc, 0, 0, render_width, render_height);
- XtSetArg (arg[0], XtNbitmap, gsub_pixmap);
- XtSetValues (gsub_image, arg, 1);
- XtSetArg (arg[0], XtNbitmap, gpos_pixmap);
- XtSetValues (gpos_image, arg, 1);
+ update_seq_area ();
}
void
}
void
+DumpProc (Widget w, XtPointer client_data, XtPointer call_data)
+{
+ int g_width, g_height;
+ float g_x, g_y;
+ /* unit in points (1/72 inch); to fit in both US-letter and A4 */
+ static int xoff = 30, yoff = 30;
+ static int unit = 30;
+ static int margin = 2;
+ static int title_height = 20, label_height = 10;
+ int total_width = (unit + margin * 2) * 16;
+ int total_height = (unit + margin * 2 + label_height) * 16 + title_height;
+ /* pixel size (dots) */
+ int size = 128;
+ int i, j, k, l;
+ char *name = alloca (strlen (filename) + 10);
+ FILE *fp;
+ int index = (glyph_index / 0x100) * 0x100;
+ float scale;
+
+ g_width = face->bbox.xMax - face->bbox.xMin;
+ g_height = face->bbox.yMax - face->bbox.yMin;
+ if (g_width > g_height)
+ {
+ scale = g_width * size;
+ g_x = face->bbox.xMin * unit / g_width;
+ g_y = face->bbox.yMin * unit / g_width;
+ }
+ else
+ {
+ scale = g_height * size;
+ g_x = face->bbox.xMin * unit / g_height;
+ g_y = face->bbox.yMin * unit / g_height;
+ }
+ scale /= face->units_per_EM;
+
+ FT_Set_Pixel_Sizes (face, 0, size);
+
+ sprintf (name, "%s-%04X.ps", face->family_name, index);
+ printf ("Writing %s ... ", name);
+ fflush (stdout);
+ fp = fopen (name, "w");
+
+ fprintf (fp, "%s\n", "%!PS-Adobe-2.0 EPSF-2.0");
+ fprintf (fp, "%s\n", "%%Creater: otfview");
+ fprintf (fp, "%s %s(%s)-%04X\n", "%%Title:",
+ face->family_name, face->style_name, index);
+ fprintf (fp, "%s\n", "%%Pages: 1");
+ fprintf (fp, "%s %d %d %d %d\n", "%%BoundingBox:",
+ xoff, yoff, xoff + total_width, yoff + total_height);
+ fprintf (fp, "%s\n", "%%EndComments");
+ fprintf (fp, "%s\n", "%%BeginProlog");
+ fprintf (fp, "/W %d def\n", unit + margin * 2);
+ fprintf (fp, "/H %d def\n", unit + margin * 2 + label_height);
+ fprintf (fp, "/STR 10 string def\n");
+ fprintf (fp, "/DrawIndex {\n");
+ 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");
+ fprintf (fp, "} def\n");
+ fprintf (fp, "/DrawTitle {\n");
+ fprintf (fp, " /Courier findfont 20 scalefont setfont\n");
+ fprintf (fp, " %d %d 4 add moveto\n", xoff + total_width / 2,
+ yoff + total_height - title_height + 2);
+ fprintf (fp, " (%s(%s)-%04X) dup stringwidth pop 2 div neg 0 rmoveto show\n",
+ face->family_name, face->style_name, index);
+ fprintf (fp, "} def\n");
+ fprintf (fp, "/DrawFrame { gsave %d %d translate 0 setlinewidth\n",
+ xoff, yoff);
+ fprintf (fp, " /Courier findfont 10 scalefont setfont\n");
+ fprintf (fp, " /I %d def\n", index);
+ fprintf (fp, " 0 1 16 { W mul 0 moveto 0 H 16 mul rlineto stroke } for\n");
+ fprintf (fp, " 0 1 16 { H mul 0 exch moveto W 16 mul 0 rlineto stroke } for\n");
+ fprintf (fp, " 0 1 15 { H mul %d add 0 exch moveto W 16 mul 0 rlineto stroke } for\n", label_height);
+ fprintf (fp, " 15 -1 0 { gsave H mul 0 exch translate 0 0 moveto\n");
+ fprintf (fp, " 0 1 15 { gsave W mul 0 moveto\n");
+ fprintf (fp, " 4 2 rmoveto DrawIndex /I I 1 add def grestore} for\n");
+ fprintf (fp, " grestore } for grestore } def\n");
+ fprintf (fp, "%s\n", "%%EndProlog");
+ fprintf (fp, "DrawTitle DrawFrame\n");
+
+ for (i = 0; i < 16; i++)
+ for (j = 0; j < 16; j++, index++)
+ {
+ int idx;
+
+ if (charmap_index >= 0)
+ idx = FT_Get_Char_Index (face, (FT_ULong) index);
+ else
+ idx = index;
+ if (idx > 0
+ && FT_Load_Glyph (face, idx, FT_LOAD_RENDER | FT_LOAD_MONOCHROME) == 0
+ && face->glyph->bitmap.rows > 0
+ && face->glyph->bitmap.width > 0)
+ {
+ unsigned char *p = face->glyph->bitmap.buffer;
+ int width = (face->glyph->bitmap.width - 1) / 8 + 1;
+
+ fprintf (fp, "gsave %f %f translate %d %d scale 0 0 moveto\n",
+ xoff + (unit + margin * 2) * j + margin - g_x,
+ yoff + (unit + label_height + margin * 2) * (15 - i) + label_height + margin - g_y,
+ unit, unit);
+ fprintf (fp, "%d %d true [%f 0 0 %f %d %d]\n",
+ width * 8, face->glyph->bitmap.rows,
+ scale, -scale, -face->glyph->bitmap_left,
+ face->glyph->bitmap_top);
+ fprintf (fp, "{< ");
+ for (k = 0; k < face->glyph->bitmap.rows;
+ k++, p += face->glyph->bitmap.pitch)
+ {
+ for (l = 0; l < width; l++)
+ fprintf (fp, "%02X", p[l]);
+ fprintf (fp, "\n");
+ }
+ fprintf (fp, ">} imagemask grestore\n");
+ }
+ else
+ {
+ int boxsize = unit + margin * 2;
+
+ fprintf (fp, "gsave 0 setlinewidth %d %d translate\n",
+ xoff + boxsize * j,
+ yoff + (boxsize + label_height) * (15 - i) + label_height);
+ fprintf (fp, "0 0 moveto %d %d lineto stroke\n",
+ boxsize, boxsize);
+ fprintf (fp, "0 %d moveto %d 0 lineto stroke grestore\n",
+ boxsize, boxsize);
+ }
+ }
+ fprintf (fp, "showpage\n");
+ fclose (fp);
+ printf ("done\n");
+
+ FT_Set_Pixel_Sizes (face, 0, (int) pixel_size);
+}
+
+
+void
GlyphProc (Widget w, XtPointer client_data, XtPointer call_data)
{
int old_glyph_index = glyph_index;
if ((int) client_data == -3 && glyph_index > 0)
glyph_index = 0;
else if ((int) client_data == -2 && glyph_index > 0)
- glyph_index = (glyph_index - 1) & 0xF000;
+ glyph_index = (glyph_index - 1) & 0x1FF000;
else if ((int) client_data == -1 && glyph_index > 0)
glyph_index -= 0x80;
- else if ((int) client_data == 1 && glyph_index < 0xFF80)
+ else if ((int) client_data == 1 && glyph_index < 0x10FF80)
glyph_index += 0x80;
- else if ((int) client_data == 2 && glyph_index < 0xF000)
- glyph_index = (glyph_index + 0x1000) & 0xF000;
- else if ((int) client_data == 3 && glyph_index < 0xF000)
- glyph_index = 0xFF80;
+ else if ((int) client_data == 2 && glyph_index < 0x10F000)
+ glyph_index = (glyph_index + 0x1000) & 0x1FF000;
+ else if ((int) client_data == 3 && glyph_index < 0x10F000)
+ glyph_index = 0x10FF80;
if (glyph_index != old_glyph_index)
update_glyph_area ();
}
{
if ((int) client_data < 0)
{
- glyph_rec.n_glyphs = 0;
- update_render_area ();
+ if (glyph_rec.n_glyphs > 0)
+ {
+ if ((int) client_data == -2)
+ glyph_rec.n_glyphs--;
+ else
+ glyph_rec.n_glyphs = 0;
+ update_render_area ();
+ }
}
else if (glyph_rec.n_glyphs < 64)
{
}
void
+BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
+{
+ Arg arg[1];
+
+ reversed = ! reversed;
+ if (reversed)
+ XtSetArg (arg[0], XtNlabel, "L<-R");
+ else
+ XtSetArg (arg[0], XtNlabel, "L->R");
+ XtSetValues (w, arg, 1);
+ update_seq_area ();
+}
+
+void
+AltSubstProc (Widget w, XtPointer client_data, XtPointer call_data)
+{
+ do_alternate_subst = ! do_alternate_subst;
+ update_seq_area ();
+}
+
+void
+FeatureProc (Widget w, XtPointer client_data, XtPointer call_data)
+{
+ FeatureRec *rec = (FeatureRec *) client_data;
+ int idx, i, j;
+ Arg arg[4];
+ char *label;
+
+ if (! rec->langsys)
+ return;
+ XtSetArg (arg[0], XtNlabel, &label);
+ XtGetValues (w, arg, 1);
+ if (! strcmp (label, "all"))
+ idx = -2;
+ else if (! strcmp (label, "none"))
+ idx = -1;
+ else
+ {
+ for (idx = 0; idx < rec->langsys->FeatureCount; idx++)
+ if (rec->features[idx].w == w)
+ break;
+ if (idx == rec->langsys->FeatureCount)
+ idx = -1;
+ }
+ if (idx < 0)
+ {
+ int on = idx == -2;
+
+ for (i = j = 0; j < rec->langsys->FeatureCount; j++)
+ {
+ int index = rec->langsys->FeatureIndex[j];
+
+ rec->features[j].tag
+ = rec->gsub_gpos->FeatureList.Feature[index].FeatureTag;
+ rec->features[j].on = on;
+ }
+ }
+ else
+ {
+ OTF_Tag tag = rec->features[idx].tag;
+
+ i = idx;
+ if (rec->features[i].on)
+ {
+ for (j = i + 1;
+ j < rec->langsys->FeatureCount && rec->features[j].on; j++)
+ rec->features[j - 1].tag = rec->features[j].tag;
+ rec->features[j - 1].tag = tag;
+ rec->features[j - 1].on = 0;
+ }
+ else
+ {
+ for (j = i + 1; i > 0 && ! rec->features[i - 1].on; i--)
+ rec->features[i].tag = rec->features[i - 1].tag;
+ rec->features[i].tag = tag;
+ rec->features[i].on = 1;
+ }
+ }
+
+ for (; i < j; i++)
+ {
+ char str[5];
+
+ if (rec->features[i].on)
+ {
+ XtSetArg (arg[0], XtNborderWidth, 3);
+ XtSetArg (arg[1], XtNinternalHeight, 2);
+ XtSetArg (arg[2], XtNinternalWidth, 2);
+ }
+ else
+ {
+ XtSetArg (arg[0], XtNborderWidth, 1);
+ XtSetArg (arg[1], XtNinternalHeight, 4);
+ XtSetArg (arg[2], XtNinternalWidth, 4);
+ }
+ OTF_tag_name (rec->features[i].tag, str);
+ XtSetArg (arg[3], XtNlabel, str);
+ XtSetValues (rec->features[i].w, arg, 4);
+ }
+ update_seq_area ();
+}
+
+void
+setup_feature_rec (FeatureRec *rec)
+{
+ int i, j;
+ Arg arg[10];
+
+ rec->langsys = NULL;
+ if (! rec->gsub_gpos)
+ return;
+ for (i = 0; i < rec->gsub_gpos->ScriptList.ScriptCount; i++)
+ if (rec->gsub_gpos->ScriptList.Script[i].ScriptTag == script_tag)
+ {
+ OTF_Script *script = rec->gsub_gpos->ScriptList.Script + i;
+
+ if (langsys_tag)
+ {
+ for (j = 0; j < script->LangSysCount; j++)
+ if (script->LangSysRecord[j].LangSysTag == langsys_tag)
+ {
+ rec->langsys = script->LangSys + j;
+ break;
+ }
+ }
+ if (! rec->langsys)
+ rec->langsys = &rec->gsub_gpos->ScriptList.Script[i].DefaultLangSys;
+ break;
+ }
+
+ if (! rec->langsys)
+ i = 0;
+ else
+ {
+ XtSetArg (arg[0], XtNborderWidth, 1);
+ XtSetArg (arg[1], XtNinternalHeight, 4);
+ XtSetArg (arg[2], XtNinternalWidth, 4);
+ XtSetArg (arg[3], XtNborderColor, foreground);
+ XtSetArg (arg[4], XtNsensitive, True);
+ for (i = 0; i < rec->langsys->FeatureCount; i++)
+ {
+ OTF_Feature *feature = rec->gsub_gpos->FeatureList.Feature;
+ int index = rec->langsys->FeatureIndex[i];
+ char label[5];
+
+ if (! rec->features[i].w)
+ {
+ Widget w = XtCreateManagedWidget ("", commandWidgetClass,
+ rec->parent, arg, 0);
+ XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
+ rec->features[i].w = w;
+ }
+
+ rec->features[i].tag = feature[index].FeatureTag;
+ rec->features[i].on = 0;
+ OTF_tag_name (rec->features[i].tag, label);
+ XtSetArg (arg[5], XtNlabel, label);
+ XtSetValues (rec->features[i].w, arg, 6);
+ }
+ }
+ XtSetArg (arg[0], XtNborderColor, background);
+ XtSetArg (arg[1], XtNsensitive, False);
+ XtSetArg (arg[2], XtNlabel, " ");
+ for (; i < rec->num_features; i++)
+ {
+ if (! rec->features[i].w)
+ {
+ Widget w = XtCreateManagedWidget ("", commandWidgetClass,
+ rec->parent, arg, 0);
+ XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
+ rec->features[i].w = w;
+ }
+ XtSetValues (rec->features[i].w, arg, 3);
+ }
+}
+
+void
+compose_script_langsys (OTF_Tag script, OTF_Tag langsys, char *name)
+{
+ OTF_tag_name (script, name);
+ if (langsys)
+ {
+ name[4] = '(';
+ OTF_tag_name (langsys, name + 5);
+ name[9] = ')';
+ name[10] = '\0';
+ }
+}
+
+void
+decompose_script_langsys (OTF_Tag *script, OTF_Tag *langsys, char *name)
+{
+ *script = OTF_tag (name);
+ if (name[4])
+ *langsys = OTF_tag (name + 5);
+ else
+ *langsys = 0;
+}
+
+void
+ScriptProc (Widget w, XtPointer client_data, XtPointer call_data)
+{
+ char *name;
+ OTF_Tag script, langsys;
+ Arg arg[1];
+
+ XtSetArg (arg[0], XtNlabel, &name);
+ XtGetValues (w, arg, 1);
+ decompose_script_langsys (&script, &langsys, name);
+ if (script_tag == script && langsys_tag == langsys)
+ return;
+ script_tag = script;
+ langsys_tag = langsys;
+ setup_feature_rec (&gsub);
+ setup_feature_rec (&gpos);
+ update_seq_area ();
+}
+
+Widget
+create_otf_script_widgets (Widget prev)
+{
+ Widget w;
+ Arg arg[10];
+ int n, prev_n, i, j;
+ struct {
+ OTF_Tag script;
+ OTF_Tag langsys;
+ } *script_langsys;
+ char name[11];
+ int nfeatures;
+
+ XtSetArg (arg[0], XtNborderWidth, 0);
+ XtSetArg (arg[1], XtNleft, XawChainLeft);
+ XtSetArg (arg[2], XtNright, XawChainLeft);
+ XtSetArg (arg[3], XtNtop, XawChainTop);
+ XtSetArg (arg[4], XtNbottom, XawChainTop);
+ XtSetArg (arg[5], XtNfromVert, prev);
+ XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
+ prev = XtCreateManagedWidget ("Script", boxWidgetClass, render_area, arg, 7);
+ XtCreateManagedWidget ("script(langsys)", labelWidgetClass, prev, arg, 1);
+
+ n = 0;
+ if (otf->gsub)
+ for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
+ n += otf->gsub->ScriptList.Script[i].LangSysCount + 1;
+ if (otf->gpos)
+ for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
+ n += otf->gpos->ScriptList.Script[i].LangSysCount + 1;
+ script_langsys = alloca ((sizeof script_langsys[0]) * n);
+ n = 0;
+ nfeatures = 0;
+ if (otf->gsub)
+ for (i = 0; i < otf->gsub->ScriptList.ScriptCount; i++)
+ {
+ OTF_Tag tag = otf->gsub->ScriptList.Script[i].ScriptTag;
+
+ script_langsys[n].script = tag;
+ script_langsys[n++].langsys = 0;
+ if (nfeatures
+ < otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount)
+ nfeatures
+ = otf->gsub->ScriptList.Script[i].DefaultLangSys.FeatureCount;
+ for (j = 0; j < otf->gsub->ScriptList.Script[i].LangSysCount; j++)
+ {
+ script_langsys[n].script = tag;
+ script_langsys[n++].langsys
+ = otf->gsub->ScriptList.Script[i].LangSysRecord[j].LangSysTag;
+ if (nfeatures
+ < otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount)
+ nfeatures
+ = otf->gsub->ScriptList.Script[i].LangSys[j].FeatureCount;
+ }
+ }
+ gsub.num_features = nfeatures;
+ if (nfeatures > 0)
+ {
+ gsub.num_features = nfeatures;
+ gsub.features = malloc ((sizeof (FeatureElement)) * nfeatures);
+ memset (gsub.features, 0, (sizeof (FeatureElement)) * nfeatures);
+ }
+ prev_n = n;
+ nfeatures = 0;
+ if (otf->gpos)
+ for (i = 0; i < otf->gpos->ScriptList.ScriptCount; i++)
+ {
+ OTF_Tag tag = otf->gpos->ScriptList.Script[i].ScriptTag;
+ int k;
+
+ if (nfeatures
+ < otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount)
+ nfeatures
+ = otf->gpos->ScriptList.Script[i].DefaultLangSys.FeatureCount;
+ for (k = 0; k < prev_n; k++)
+ if (tag == script_langsys[k].script)
+ break;
+ if (k == prev_n)
+ {
+ script_langsys[n].script = tag;
+ script_langsys[n++].langsys = 0;
+ }
+ for (j = 0; j < otf->gpos->ScriptList.Script[i].LangSysCount; j++)
+ {
+ int l;
+
+ if (k < prev_n)
+ {
+ OTF_Script *script = otf->gpos->ScriptList.Script + i;
+
+ for (l = k; l < prev_n && tag == script_langsys[l].script; l++)
+ if (script->LangSysRecord[j].LangSysTag
+ == script_langsys[l].langsys)
+ break;
+ }
+ else
+ l = prev_n;
+ if (l == prev_n)
+ {
+ script_langsys[n].script = tag;
+ script_langsys[n++].langsys = 0;
+ }
+ if (nfeatures
+ < otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount)
+ nfeatures
+ = otf->gpos->ScriptList.Script[i].LangSys[j].FeatureCount;
+ }
+ }
+
+ if (nfeatures > 0)
+ {
+ gpos.num_features = nfeatures;
+ gpos.features = malloc ((sizeof (FeatureElement)) * nfeatures);
+ memset (gpos.features, 0, (sizeof (FeatureElement)) * nfeatures);
+ }
+
+ if (n == 0)
+ return prev;
+
+ script_tag = script_langsys[0].script;
+ langsys_tag = script_langsys[0].langsys;
+ compose_script_langsys (script_tag, langsys_tag, name);
+
+ if (n == 1)
+ {
+ XtSetArg (arg[0], XtNforeground, background);
+ XtSetArg (arg[1], XtNbackground, foreground);
+ XtCreateManagedWidget (name, labelWidgetClass, prev, arg, 2);
+ }
+ else
+ {
+ XtSetArg (arg[0], XtNstate, True);
+ w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
+ XtAddCallback (w, XtNcallback, ScriptProc, NULL);
+ XtSetArg (arg[0], XtNradioGroup, w);
+ for (i = 1; i < n; i++)
+ {
+ compose_script_langsys (script_langsys[i].script,
+ script_langsys[i].langsys, name);
+ w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
+ XtAddCallback (w, XtNcallback, ScriptProc, NULL);
+ }
+ }
+ return prev;
+}
+
+
+Widget
+create_otf_widgets (Widget prev, FeatureRec *rec)
+{
+ Arg arg[10];
+ Widget w;
+
+ XtSetArg (arg[0], XtNborderWidth, 0);
+ XtSetArg (arg[1], XtNleft, XawChainLeft);
+ XtSetArg (arg[2], XtNright, XawChainLeft);
+ XtSetArg (arg[3], XtNtop, XawChainTop);
+ XtSetArg (arg[4], XtNbottom, XawChainTop);
+ XtSetArg (arg[5], XtNfromVert, prev);
+ XtSetArg (arg[6], XtNorientation, XtorientHorizontal);
+ prev = XtCreateManagedWidget (rec->label, boxWidgetClass, render_area,
+ arg, 7);
+ XtCreateManagedWidget (rec->label, labelWidgetClass, prev, arg, 1);
+ XtSetArg (arg[0], XtNborderWidth, 1);
+ XtSetArg (arg[1], XtNinternalHeight, 4);
+ XtSetArg (arg[2], XtNinternalWidth, 4);
+ w = XtCreateManagedWidget ("all", commandWidgetClass, prev, arg, 3);
+ XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
+ w = XtCreateManagedWidget ("none", commandWidgetClass, prev, arg, 3);
+ XtAddCallback (w, XtNcallback, FeatureProc, (XtPointer) rec);
+
+ rec->parent = prev;
+ setup_feature_rec (rec);
+ return prev;
+}
+
+void
create_widgets ()
{
String quit_action = "<KeyPress>q: set() notify() unset()";
- String FIRST_action = "~Shift<KeyPress>f: set() notify() unset()";
- String PREV_action = "Shift<KeyPress>p: set() notify() unset()";
- String prev_action = "~Shift<KeyPress>p: set() notify() unset()";
- String next_action = "~Shift<KeyPress>n: set() notify() unset()";
- String NEXT_action = "Shift<KeyPress>n: set() notify() unset()";
- String LAST_action = "~Shift<KeyPress>l: set() notify() unset()";
+ String FIRST_action = "<KeyPress>f: set() notify() unset()\n\
+ <KeyPress>Home: set() notify() unset()";
+ String PREV_action = "Shift<KeyPress>p: set() notify() unset()\n\
+ <KeyPress>Up: set() notify() unset()";
+ String prev_action = "~Shift<KeyPress>p: set() notify() unset()\n\
+ <KeyPress>Left: set() notify() unset()";
+ String next_action = "~Shift<KeyPress>n: set() notify() unset()\n\
+ <KeyPress>Right: set() notify() unset()";
+ String NEXT_action = "Shift<KeyPress>n: set() notify() unset()\n\
+ <KeyPress>Down: set() notify() unset()";
+ String LAST_action = "<KeyPress>l: set() notify() unset()\n\
+ <KeyPress>End: set() notify() unset()";
Arg arg[10];
int i, j;
- int glyph_widget_height;
+ Widget prev, w;
+ String trans = "<Expose>: Expose()";
+
+ XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans));
+ frame = XtCreateManagedWidget ("frame", formWidgetClass, shell, arg, 1);
- frame = XtCreateManagedWidget ("frame", formWidgetClass, shell, NULL, 0);
XtSetArg (arg[0], XtNleft, XawChainLeft);
XtSetArg (arg[1], XtNright, XawChainLeft);
XtSetArg (arg[2], XtNtop, XawChainTop);
XtSetArg (arg[6], XtNfromVert, command_area);
navi_area = XtCreateManagedWidget ("navi-area", boxWidgetClass,
frame, arg, 7);
- XtSetArg (arg[4], XtNborderWidth, 1);
+ XtSetArg (arg[4], XtNborderWidth, 0);
XtSetArg (arg[5], XtNfromVert, navi_area);
XtSetArg (arg[6], XtNdefaultDistance, 0);
glyph_area = XtCreateManagedWidget ("glyph-area", formWidgetClass,
frame, arg, 7);
- XtSetArg (arg[4], XtNborderWidth, 0);
XtSetArg (arg[5], XtNfromVert, glyph_area);
render_area = XtCreateManagedWidget ("render-area", formWidgetClass,
frame, arg, 6);
XtSetArg (arg[0], XtNaccelerators, XtParseAcceleratorTable (quit_action));
- quit = XtCreateManagedWidget ("quit", commandWidgetClass,
+ quit = XtCreateManagedWidget ("Quit", commandWidgetClass,
command_area, arg, 1);
XtAddCallback (quit, XtNcallback, QuitProc, NULL);
+ dump = XtCreateManagedWidget ("DumpImage", commandWidgetClass,
+ command_area, arg, 1);
+ XtAddCallback (dump, XtNcallback, DumpProc, NULL);
+
+ XtSetArg (arg[0], XtNborderWidth, 0);
+ XtSetArg (arg[1], XtNwidth, 10);
+ XtCreateManagedWidget ("spacer", boxWidgetClass, command_area, arg, 2);
+
charmap = alloca (sizeof (Widget) * (face->num_charmaps + 1));
XtSetArg (arg[0], XtNstate, True);
charmap[0] = XtCreateManagedWidget (charmap_rec[0].name, toggleWidgetClass,
navi_area, arg, 2);
XtAddCallback (prev, XtNcallback, GlyphProc, (XtPointer) -1);
XtSetArg (arg[0], XtNlabel, " 0000 ");
- label = XtCreateManagedWidget ("label", labelWidgetClass,
+ range = XtCreateManagedWidget ("range", labelWidgetClass,
navi_area, arg, 1);
+ XtSetArg (arg[0], XtNforeground, &foreground);
+ XtSetArg (arg[1], XtNbackground, &background);
+ XtGetValues (range, arg, 2);
+
XtSetArg (arg[0], XtNlabel, "> (n)");
XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (next_action));
next = XtCreateManagedWidget ("next", commandWidgetClass,
navi_area, arg, 2);
XtAddCallback (LAST, XtNcallback, GlyphProc, (XtPointer) 3);
- glyph_widget_height = glyph_height + 1 + FONT_HEIGHT;
XtSetArg (arg[0], XtNleft, XawChainLeft);
XtSetArg (arg[1], XtNright, XawChainLeft);
XtSetArg (arg[2], XtNtop, XawChainTop);
XtSetArg (arg[3], XtNbottom, XawChainTop);
+
for (i = 0; i < 8; i++)
- for (j = 0; j < 16; j++)
- {
- int k = i * 16 + j;
- int num_args = 4;
-
- XtSetArg (arg[num_args], XtNwidth, glyph_width), num_args++;
- XtSetArg (arg[num_args], XtNheight, glyph_widget_height), num_args++;
- if (j > 0)
- XtSetArg (arg[num_args], XtNfromHoriz, glyph[k - 1]), num_args++;
- if (i > 0)
- XtSetArg (arg[num_args], XtNfromVert, glyph[k - 16]), num_args++;
- XtSetArg (arg[num_args], XtNinternalWidth, 0), num_args++;
- glyph[k] = XtCreateManagedWidget ("glyph", commandWidgetClass,
- glyph_area, arg, num_args);
- XtAddCallback (glyph[k], XtNcallback, RenderProc, (XtPointer) k);
- }
+ {
+ char str[3];
+ int n = 4;
+ Widget head;
+
+ sprintf (str, "%XX", i);
+ XtSetArg (arg[n], XtNheight, glyph_height + 5), n++;
+ XtSetArg (arg[n], XtNlabel, str), n++;
+ XtSetArg (arg[n], XtNborderWidth, 0), n++;
+ if (i > 0)
+ XtSetArg (arg[n], XtNfromVert, w), n++;
+ head = XtCreateManagedWidget (str, labelWidgetClass, glyph_area, arg, n);
+ index_label[i] = head;
+ for (j = 0; j < 16; j++)
+ {
+ int k = i * 16 + j;
+
+ n = 4;
+ if (i > 0)
+ XtSetArg (arg[n], XtNfromVert, w), n++;
+ if (j == 0)
+ XtSetArg (arg[n], XtNfromHoriz, head), n++;
+ else
+ XtSetArg (arg[n], XtNfromHoriz, glyph[k - 1]), n++;
+ XtSetArg (arg[n], XtNbitmap, none_pixmap), n++;
+ glyph[k] = XtCreateManagedWidget ("glyph", commandWidgetClass,
+ glyph_area, arg, n);
+ XtAddCallback (glyph[k], XtNcallback, RenderProc, (XtPointer) k);
+ }
+ w = head;
+ }
+ /* 10 = (1 (border_width) + 4 (inner_width)) * 2 */
+ XtSetArg(arg[4], XtNwidth, glyph_width + 10);
+ XtSetArg (arg[5], XtNfromVert, glyph[112]);
+ XtSetArg (arg[6], XtNfromHoriz, w);
+ XtSetArg (arg[7], XtNborderWidth, 0);
+
+ for (j = 0; j < 16; j++)
+ {
+ char str[3];
+
+ sprintf (str, "X%X", j);
+ XtSetArg (arg[8], XtNlabel, str);
+ w = XtCreateManagedWidget ("idx", labelWidgetClass, glyph_area, arg, 9);
+ XtSetArg (arg[6], XtNfromHoriz, w);
+ }
XtSetArg (arg[0], XtNleft, XawChainLeft);
XtSetArg (arg[1], XtNright, XawChainLeft);
XtSetArg (arg[2], XtNtop, XawChainTop);
XtSetArg (arg[3], XtNbottom, XawChainTop);
- clear = XtCreateManagedWidget ("clear", commandWidgetClass,
- render_area, arg, 4);
+ XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
+ XtSetArg (arg[5], XtNborderWidth, 0);
+ w = XtCreateManagedWidget ("clear-box", boxWidgetClass, render_area, arg, 6);
+ clear = XtCreateManagedWidget ("clear", commandWidgetClass, w, arg, 0);
XtAddCallback (clear, XtNcallback, RenderProc, (XtPointer) -1);
+ del = XtCreateManagedWidget ("delete", commandWidgetClass, w, arg, 0);
+ XtAddCallback (del, XtNcallback, RenderProc, (XtPointer) -2);
+ bidi = XtCreateManagedWidget ("L->R", toggleWidgetClass, w, arg, 0);
+ XtAddCallback (bidi, XtNcallback, BidiProc, NULL);
+ alt_subst = XtCreateManagedWidget ("AltSubst", toggleWidgetClass, w, arg, 0);
+ XtAddCallback (alt_subst, XtNcallback, AltSubstProc, NULL);
+
XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
XtSetArg (arg[5], XtNborderWidth, 0);
- XtSetArg (arg[6], XtNfromVert, clear);
- raw = XtCreateManagedWidget ("raw", boxWidgetClass,
- render_area, arg, 7);
+ XtSetArg (arg[6], XtNfromVert, w);
+ raw = XtCreateManagedWidget ("raw", boxWidgetClass, render_area, arg, 7);
+
XtSetArg (arg[0], XtNborderWidth, 0);
XtSetArg (arg[1], XtNlabel, "raw: ");
raw_label = XtCreateManagedWidget ("raw-label", labelWidgetClass,
XtSetArg (arg[1], XtNbitmap, raw_pixmap);
raw_image = XtCreateManagedWidget ("raw-image", labelWidgetClass,
raw, arg, 2);
- XtSetArg (arg[6], XtNfromVert, raw);
- seq = XtCreateManagedWidget ("seq", boxWidgetClass,
- render_area, arg, 7);
+ w = raw;
+ if (otf)
+ {
+ OTF_get_table (otf, "GSUB");
+ OTF_get_table (otf, "GPOS");
+ w = create_otf_script_widgets (w);
+ if (otf->gsub)
+ {
+ gsub.label = "GSUB";
+ gsub.gsub_gpos = otf->gsub;
+ w = create_otf_widgets (w, &gsub);
+ }
+ if (otf->gpos)
+ {
+ gpos.label = "GPOS";
+ gpos.gsub_gpos = otf->gpos;
+ w = create_otf_widgets (w, &gpos);
+ }
+ }
+
+ XtSetArg (arg[6], XtNfromVert, w);
+ seq = XtCreateManagedWidget ("seq", boxWidgetClass, render_area, arg, 7);
XtSetArg (arg[0], XtNborderWidth, 0);
XtSetArg (arg[1], XtNlabel, "seq: ");
seq_label = XtCreateManagedWidget ("seq-label", labelWidgetClass,
- seq, arg, 2);
+ seq, arg, 2);
XtSetArg (arg[1], XtNbitmap, seq_pixmap);
seq_image = XtCreateManagedWidget ("seq-image", labelWidgetClass,
- seq, arg, 2);
- if (otf)
- {
- XtSetArg (arg[6], XtNfromVert, seq);
- gsub = XtCreateManagedWidget ("gsub", boxWidgetClass,
- render_area, arg, 7);
- XtSetArg (arg[0], XtNborderWidth, 0);
- XtSetArg (arg[1], XtNlabel, "gsub: ");
- gsub_label = XtCreateManagedWidget ("gsub-label", labelWidgetClass,
- gsub, arg, 2);
- gsub_image = XtCreateManagedWidget ("gsub-image", labelWidgetClass,
- gsub, arg, 1);
- XtSetArg (arg[6], XtNfromVert, gsub);
- gpos = XtCreateManagedWidget ("gpos", boxWidgetClass,
- render_area, arg, 7);
- XtSetArg (arg[0], XtNborderWidth, 0);
- XtSetArg (arg[1], XtNlabel, "gpos: ");
- gpos_label = XtCreateManagedWidget ("gpos-label", labelWidgetClass,
- gpos, arg, 2);
- gpos_image = XtCreateManagedWidget ("gpos-image", labelWidgetClass,
- gpos, arg, 1);
- }
-
+ seq, arg, 2);
XtInstallAllAccelerators (shell, shell);
}
+static void
+ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
+{
+ XTextProperty text_prop;
+ char *pname = "otfview";
+ char *fname = basename (filename);
+ char *name = alloca (strlen (fname) + 3 + strlen (pname) + 1);
+
+ sprintf (name, "%s - %s", pname, fname);
+ text_prop.value = (unsigned char *) name;
+ text_prop.encoding = XA_STRING;
+ text_prop.format = 8;
+ text_prop.nitems = strlen (name);
+ XSetWMName (display, XtWindow (shell), &text_prop);
+}
/* Format MSG by FMT and print the result to the stderr, and exit. */
exit (1); \
} while (0)
+static int
+x_error_handler (Display *display, XErrorEvent *error)
+{
+ return 0;
+}
+
+void
+help (char **argv, int err)
+{
+ FILE *fp = err ? stderr : stdout;
+
+ fprintf (fp, "Usage: %s [ X-OPTION ... ] OTF-FILE [INDEX]\n",
+ basename (argv[0]));
+ fprintf (fp, " Environment variable PIXEL_SIZE specifies the pixel size.\n");
+ fprintf (fp, " The default pixel size is %d, but is reduced\n",
+ DEFAULT_PIXEL_SIZE);
+ fprintf (fp, " if your screen is not that wide.\n");
+ exit (err);
+}
+
int
main (int argc, char **argv)
{
- FT_Library library;
+ XtActionsRec actions[] = { {"Expose", ExposeProc} };
+ Arg arg[10];
+ FT_Library library;
OTF_GlyphString gstring;
OTF_Glyph *g;
int err;
int i;
- int pixel_size = DEFAULT_PIXEL_SIZE;
+ int fixed_pixel_size = 0;
int display_width;
+ pixel_size = DEFAULT_PIXEL_SIZE;
{
char *str = getenv ("PIXEL_SIZE");
if (str && (i = atoi (str)) > 0)
- pixel_size = i;
+ {
+ pixel_size = i;
+ fixed_pixel_size = 1;
+ }
}
gstring.size = gstring.used = 256;
gstring.glyphs = g;
shell = XtOpenApplication (&context, "OTFView", NULL, 0, &argc, argv, NULL,
- shellWidgetClass, NULL, 0);
+ shellWidgetClass, arg, 0);
display = XtDisplay (shell);
+ /*XSynchronize (display, True);*/
+ XSetErrorHandler (x_error_handler);
display_width = DisplayWidth (display,
XScreenNumberOfScreen (XtScreen (shell)));
font = XLoadQueryFont (display, DEFAULT_FONT_NAME);
if (! font)
font = XLoadQueryFont (display, "fixed");
- if (argc != 2)
- FATAL_ERROR ("%s\n", "Usage: otfview [ X-OPTION ... ] OTF-FILE");
-
- if (strstr (argv[1], ".ttf")
- || strstr (argv[1], ".TTF")
- || strstr (argv[1], ".otf")
- || strstr (argv[1], ".OTF"))
+ if (argc < 2)
+ help (argv, 1);
+ if (!strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
+ help (argv, 0);
+ filename = argv[1];
+ if (argc > 2)
{
- otf = OTF_open (argv[1]);
- if (! otf
- || OTF_get_table (otf, "head") < 0
- || OTF_get_table (otf, "cmap") < 0
- || (OTF_get_table (otf, "gsub") < 0
- && OTF_get_table (otf, "gpos") < 0))
- otf = NULL;
+ fontindex = atoi (argv[2]);
+ if (fontindex < 0)
+ FATAL_ERROR ("Invalid font index: %d\n", fontindex);
}
if ((err = FT_Init_FreeType (&library)))
FATAL_ERROR ("%s\n", "FT_Init_FreeType: error");
- err = FT_New_Face (library, argv[1], 0, &face);
+ err = FT_New_Face (library, filename, fontindex, &face);
if (err == FT_Err_Unknown_File_Format)
FATAL_ERROR ("%s\n", "FT_New_Face: unknown file format");
else if (err)
- FATAL_ERROR ("%s\n", "FT_New_Face: unknown error");
+ FATAL_ERROR ("%s\n", "FT_New_Face: unknown error (invalid face index?)");
if ((err = FT_Set_Pixel_Sizes (face, 0, pixel_size)))
FATAL_ERROR ("%s\n", "FT_Set_Pixel_Sizes: error");
+ if (strstr (filename, ".ttf")
+ || strstr (filename, ".TTF")
+ || strstr (filename, ".otf")
+ || strstr (filename, ".OTF"))
+ {
+ otf = OTF_open_ft_face (face);
+ if (! otf
+ || OTF_get_table (otf, "head") < 0
+ || OTF_get_table (otf, "cmap") < 0
+ || (OTF_check_table (otf, "GSUB") < 0
+ && OTF_check_table (otf, "GPOS") < 0))
+ otf = NULL;
+ }
+
{
char title[256];
Arg arg[1];
+ filename = basename (filename);
sprintf (title, "%s family:%s style:%s",
- basename (argv[1]), face->family_name, face->style_name);
+ filename, face->family_name, face->style_name);
XtSetArg (arg[0], XtNtitle, title);
XtSetValues (shell, arg, 1);
}
glyph_width = ((face->bbox.xMax - face->bbox.xMin)
* pixel_size / face->units_per_EM);
- if (glyph_width * 16 > display_width * 0.8)
+ if (! fixed_pixel_size && glyph_width * 16 > display_width * 0.8)
{
pixel_size = (pixel_size * display_width * 0.8 / 16 / glyph_width);
FT_Set_Pixel_Sizes (face, 0, pixel_size);
* pixel_size / face->units_per_EM);
glyph_x = - (face->bbox.xMin * pixel_size / face->units_per_EM);
- glyph_y = face->ascender * pixel_size / face->units_per_EM;
-
- for (i = 0; i < 0x10000; i++)
- if (FT_Load_Glyph (face, i, FT_LOAD_RENDER | FT_LOAD_MONOCHROME) == 0)
- {
- if (glyph_x < - face->glyph->bitmap_left)
- glyph_x = - face->glyph->bitmap_left;
- if (glyph_y < face->glyph->bitmap_top)
- glyph_y = face->glyph->bitmap_top;
- if (glyph_width
- < glyph_x + face->glyph->bitmap_left + face->glyph->bitmap.width)
- glyph_width
- = glyph_x + face->glyph->bitmap_left + face->glyph->bitmap.width;
- if (glyph_height
- < glyph_y - face->glyph->bitmap_top + face->glyph->bitmap.rows)
- glyph_height
- = glyph_y - face->glyph->bitmap_top + face->glyph->bitmap.rows;
- }
-
+ glyph_y = face->bbox.yMax * pixel_size / face->units_per_EM;
none_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
- glyph_width, glyph_height + 1 + FONT_HEIGHT, 1);
+ glyph_width, glyph_height, 1);
{
unsigned long valuemask = GCFunction | GCLineWidth;
}
XFillRectangle (display, none_pixmap, gc, 0, 0,
- glyph_width, glyph_height + 1 + FONT_HEIGHT);
+ glyph_width, glyph_height);
XDrawString (display, none_pixmap, gc_inv,
(glyph_width - XTextWidth (font, "none", 4)) / 2,
glyph_height / 2, "none", 4);
- render_width = (glyph_width + 1) * 15 + 1;
- render_height = glyph_height + FONT_HEIGHT + 2;
+ render_width = (glyph_width + 4) * 15 + 1;
+ render_height = glyph_height + 2;
charmap_rec[0].platform_id = -1;
charmap_rec[0].encoding_id = -1;
render_width, render_height, 1);
seq_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
render_width, render_height, 1);
- gsub_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
- render_width, render_height, 1);
- gpos_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
- render_width, render_height, 1);
- for (i = 0; i < 0x10000; i++)
- create_pixmap (pixel_size, i);
+ memset (bitmap, 0, sizeof (bitmap));
create_widgets ();
glyph_index = 0;
charmap_index = -1;
update_glyph_area ();
update_render_area ();
+ XtAppAddActions (context, actions, XtNumber (actions));
XtRealizeWidget (shell);
XtAppMainLoop (context);
exit (0);
}
+
+#else /* not HAVE_X11_XAW_COMMAND_H */
+
+int
+main (int argc, char **argv)
+{
+ fprintf (stderr,
+ "Building of this program failed (lack of some header files)\n");
+ exit (1);
+}
+
+#endif