X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=example%2Fotfview.c;h=82c3cfeda47683fe3f077966c4059f76312a3061;hb=bf40bc427bf292f450654ae2ab1195428caa00b1;hp=c5287375caa19b67b8a574f3a83fc3a483774bae;hpb=6fff48ff317c06e5a268b42cec1ec3b19be84dfe;p=m17n%2Flibotf.git diff --git a/example/otfview.c b/example/otfview.c index c528737..82c3cfe 100644 --- a/example/otfview.c +++ b/example/otfview.c @@ -1,6 +1,6 @@ /* otfview.c -- View glyphs of OpenType fonts. -Copyright (C) 2003, 2004, 2005 +Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H15PRO167 @@ -47,6 +47,19 @@ write to the Free Software Foundation, Inc., 59 Temple Place, Suite #include +#define CAST_FROM_XTPOINTER(TYPE, DATA, VAR) \ + do { \ + long TYPE temp = (long TYPE) (DATA); \ + (VAR) = temp; \ + } while (0) + +#define XtAddCallbackWithCast(TYPE, W, PROC, VAR) \ + do { \ + long TYPE temp = (long TYPE) (VAR); \ + XtAddCallback (W, XtNcallback, PROC, (XtPointer) temp); \ + } while (0) + + #define DEFAULT_PIXEL_SIZE 30 int pixel_size; @@ -72,6 +85,12 @@ XtAppContext context; | | idxh[7] glyph[112] ... glyph[127]| | | | idxl[0] ... idxl[15] | | | +--------------------------------------+ | + | +--- script_area (box) ----------------+ | + | | script(langsys) DFLT ... | | + | +--------------------------------------+ | + | +---- uvs_area (box) (optional) -------+ | + | | uvs[?].w ... | | + | +--------------------------------------+ | | +--- render_area (form) ---------------+ | | | clear del bidi alt_subst | | | | +--- raw (box) --------------------+ | | @@ -82,14 +101,18 @@ XtAppContext context; | | +--- seq (box) --------------------+ | | | | | seq_label seq_image | | | | | +----------------------------------+ | | + | | +--- code (box) -------------------+ | | + | | | code_label code_list ... | | | + | | +----------------------------------+ | | | +--------------------------------------+ | +------------------------------------------+ */ Widget shell, frame; 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 uvs_area, uvs_label; +Widget render_area, clear, del, bidi, alt_subst, raw, seq, code; +Widget raw_label, raw_image, seq_label, seq_image, code_label, code_list; unsigned long foreground, background; typedef struct @@ -126,7 +149,7 @@ typedef struct { int advance; } BitmapRec; -BitmapRec bitmap[0x10000]; +BitmapRec bitmap[0x110000]; int render_width, render_height; Pixmap raw_pixmap, seq_pixmap, gsub_pixmap, gpos_pixmap; @@ -154,8 +177,16 @@ struct { int codes[64]; } glyph_rec; +OTF_EncodingSubtable14 *sub14 = NULL; + +struct { + Widget w; + int c; +} uvs[256]; + OTF *otf; char *filename; +int fontindex; void create_pixmap (int index) @@ -233,40 +264,65 @@ update_glyph_area () XtSetValues (index_label[i], arg, 2); } - sprintf (buf, " %04X-%04X ", glyph_index, glyph_index + 0x7F); + 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 (range, arg, 1); } +void +update_uvs_area (int c) +{ + OTF_GlyphID code[256]; + Arg arg[1]; + int i; + + OTF_get_variation_glyphs (otf, c, code); + + for (i = 0; i < 256; i++) + if (uvs[i].w) + { + if (code[i]) + XtSetArg (arg[0], XtNsensitive, True); + else + XtSetArg (arg[0], XtNsensitive, False); + XtSetValues (uvs[i].w, 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) + if (! rec->langsys || ! rec->features) return NULL; for (i = n = 0; i < rec->langsys->FeatureCount; i++) - { - if (rec->features[i].on) - n++; - else - break; - } + if (rec->features[i].on) + n++; + if (n == 0) + return NULL; str = malloc (n * 5); - for (i = 0, p = str; i < n; i++, p += 5) - { - OTF_tag_name (rec->features[i].tag, p); - p[4] = ','; - } + for (i = 0, p = str; i < rec->langsys->FeatureCount; i++) + if (rec->features[i].on) + { + OTF_tag_name (rec->features[i].tag, p); + p[4] = ','; + p += 5; + } p[-1] = '\0'; return str; } -#define DEVICE_DELTA(table, size) \ - (((size) >= (table).StartSize && (size) <= (table).EndSize) \ - ? (table).DeltaValue[(size) >= (table).StartSize] \ +#define DEVICE_DELTA(table, size) \ + (((table).DeltaValue \ + && ((size) >= (table).StartSize && (size) <= (table).EndSize)) \ + ? (table).DeltaValue[(size) >= (table).StartSize] \ : 0) void @@ -303,19 +359,38 @@ update_seq_area () int len = glyph_rec.n_glyphs; Arg arg[1]; int unitsPerEm = face->units_per_EM; + OTF_Tag *log = NULL; + int logsize; 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]; + { + gstring.glyphs[i].c = glyph_rec.codes[i]; + if (charmap_index < 0) + 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 *script_name = NULL, *langsys_name = NULL, buf[10]; char *str; + if (script_tag) + { + script_name = buf; + OTF_tag_name (script_tag, script_name); + } + if (langsys_tag) + { + langsys_name = buf + 5; + OTF_tag_name (langsys_tag, langsys_name); + } + + OTF_drive_cmap (otf, &gstring); OTF_drive_gdef (otf, &gstring); if (otf->gsub) { @@ -323,9 +398,23 @@ update_seq_area () if (str) { if (do_alternate_subst) - OTF_drive_gsub_alternate (otf, &gstring, NULL, NULL, str); + OTF_drive_gsub_alternate (otf, &gstring, + script_name, langsys_name, str); else - OTF_drive_gsub (otf, &gstring, NULL, NULL, str); + { + OTF_drive_gsub_with_log (otf, &gstring, + script_name, langsys_name, str); + logsize = gstring.used * 2; + log = alloca (sizeof (OTF_Tag) * logsize); + for (i = 0; i < gstring.used; i++) + { + int idx = gstring.glyphs[i].positioning_type >> 4; + if (idx) + log[i] = otf->gsub->FeatureList.Feature[idx - 1].FeatureTag; + else + log[i] = 0; + } + } free (str); } } @@ -334,7 +423,32 @@ update_seq_area () str = get_features (&otf->gpos->FeatureList, &gpos); if (str) { - OTF_drive_gpos (otf, &gstring, NULL, NULL, str); + OTF_drive_gpos_with_log (otf, &gstring, + script_name, langsys_name, str); + if (log) + { + if (logsize < gstring.used) + { + OTF_Tag *log2 = alloca (sizeof (OTF_Tag) * gstring.used); + memset (log2, 0, sizeof (OTF_Tag) * gstring.used); + memcpy (log2, log, sizeof (OTF_Tag) * logsize); + logsize = gstring.used; + log = log2; + } + } + else + { + logsize = gstring.used; + log = alloca (sizeof (OTF_Tag) * logsize); + memset (log, 0, sizeof (OTF_Tag) * logsize); + } + for (i = 0; i < gstring.used; i++) + { + int idx = gstring.glyphs[i].positioning_type >> 4; + if (idx) + log[i] = otf->gpos->FeatureList.Feature[idx - 1].FeatureTag; + + } free (str); } } @@ -370,69 +484,78 @@ update_seq_area () int prev_width; int advance = bmp->advance; - if (! bmp->pixmap) + if (gstring.glyphs[i].glyph_id && ! bmp->pixmap) { create_pixmap (gstring.glyphs[i].glyph_id); if (! bmp->pixmap) continue; advance = bmp->advance; } - switch (g->positioning_type) + if (g->positioning_type & 0xF) { - 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; + while (1) + { + switch (g->positioning_type & 0xF) + { + 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; - } + 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; + } + } + if (i + 1 == gstring.used + || gstring.glyphs[i + 1].glyph_id + || ! (gstring.glyphs[i + 1].positioning_type & 0xF)) + break; + i++, g++; + } } - + 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); @@ -445,10 +568,43 @@ update_seq_area () else base = g, base_width = advance; } - free (gstring.glyphs); XtSetArg (arg[0], XtNbitmap, seq_pixmap); XtSetValues (seq_image, arg, 1); + + if (gstring.used > 0) + { + int size = render_width / FONT_WIDTH; + char *buf = alloca (size + 1); + char name[5]; + + sprintf (buf, "%04X", gstring.glyphs[0].glyph_id); + if (log && log[0]) + { + OTF_tag_name (log[0], name); + sprintf (buf + 4, " (%s)", name); + x = 11; + } + else + x = 4; + for (i = 1; i < gstring.used && x + 5 < size; i++, x += 5) + { + sprintf (buf + x, " %04X", gstring.glyphs[i].glyph_id); + if (log && log[i] && x + 11 < size) + { + OTF_tag_name (log[i], name); + sprintf (buf + x + 5, "(%s)", name); + x += 6; + } + } + while (x < size) + buf[x++] = ' '; + buf[x] = '\0'; + XtSetArg (arg[0], XtNlabel, buf); + XtSetValues (code_list, arg, 1); + } + + free (gstring.glyphs); } @@ -462,28 +618,50 @@ update_render_area () XFillRectangle (display, raw_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]; - char buf[5]; - - XCopyArea (display, bmp->pixmap, raw_pixmap, gc, - 0, 0, glyph_width, glyph_height, - (glyph_width + 4) * i + 1, 1); - XDrawRectangle (display, raw_pixmap, gc_set, - (glyph_width + 4) * i, 0, - glyph_width + 1, glyph_height + 1); - XDrawLine (display, raw_pixmap, gc_set, - (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 + 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]); - XDrawString (display, raw_pixmap, gc_inv, - (glyph_width + 1) * i + 1 - + (glyph_width - XTextWidth (font, buf, 4)) / 2, - glyph_height + 2 + FONT_HEIGHT, buf, 4); + if (glyph_rec.glyphs[i] >= 0) + { + BitmapRec *bmp = bitmap + glyph_rec.glyphs[i]; + char buf[5]; + + XCopyArea (display, bmp->pixmap, raw_pixmap, gc, + 0, 0, glyph_width, glyph_height, + (glyph_width + 4) * i + 1, 1); + XDrawRectangle (display, raw_pixmap, gc_set, + (glyph_width + 4) * i, 0, + glyph_width + 1, glyph_height + 1); + XDrawLine (display, raw_pixmap, gc_set, + (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 + 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]); + XDrawString (display, raw_pixmap, gc_inv, + (glyph_width + 4) * i + 1 + + (glyph_width - XTextWidth (font, buf, 4)) / 2, + glyph_height + 2 + FONT_HEIGHT, buf, 4); + } + else + { + /* Variation Selector */ + int idx = - glyph_rec.glyphs[i]; + char buf[4]; + + sprintf (buf, "%03d", idx); + XDrawRectangle (display, raw_pixmap, gc_set, + (glyph_width + 4) * i, 0, + glyph_width + 1, glyph_height + 1); + XDrawString (display, raw_pixmap, gc_set, + (glyph_width + 4) * i + 1 + + (glyph_width - XTextWidth (font, "VS", 2)) / 2, + 1 + glyph_height / 2, "VS", 2); + XDrawString (display, raw_pixmap, gc_set, + (glyph_width + 4) * i + 1 + + (glyph_width - XTextWidth (font, buf, 3)) / 2, + 1 + glyph_height / 2 + FONT_ASCENT, buf, 3); + } } XtSetArg (arg[0], XtNbitmap, raw_pixmap); XtSetValues (raw_image, arg, 1); @@ -635,19 +813,22 @@ void GlyphProc (Widget w, XtPointer client_data, XtPointer call_data) { int old_glyph_index = glyph_index; + int data; + + CAST_FROM_XTPOINTER (int, client_data, data); - if ((int) client_data == -3 && glyph_index > 0) + if (data == -3 && glyph_index > 0) glyph_index = 0; - else if ((int) client_data == -2 && glyph_index > 0) - glyph_index = (glyph_index - 1) & 0xF000; - else if ((int) client_data == -1 && glyph_index > 0) + else if (data == -2 && glyph_index > 0) + glyph_index = (glyph_index - 1) & 0x1FF000; + else if (data == -1 && glyph_index > 0) glyph_index -= 0x80; - else if ((int) client_data == 1 && glyph_index < 0xFF80) + else if (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 (data == 2 && glyph_index < 0x10F000) + glyph_index = (glyph_index + 0x1000) & 0x1FF000; + else if (data == 3 && glyph_index < 0x10F000) + glyph_index = 0x10FF80; if (glyph_index != old_glyph_index) update_glyph_area (); } @@ -655,22 +836,60 @@ GlyphProc (Widget w, XtPointer client_data, XtPointer call_data) void CharmapProc (Widget w, XtPointer client_data, XtPointer call_data) { - if (charmap_index == (int) client_data) + int data; + + CAST_FROM_XTPOINTER (int, client_data, data); + + if (charmap_index == data) return; - charmap_index = (int) client_data; + charmap_index = data; if (charmap_index >= 0) FT_Set_Charmap (face, face->charmaps[charmap_index]); update_glyph_area (); } void +UVSProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + unsigned idx; + int selector; + OTF_VariationSelectorRecord *record; + int i; + + CAST_FROM_XTPOINTER (unsigned, client_data, idx); + selector = uvs[idx].c; + + if (glyph_rec.n_glyphs >= 64) + return; + for (i = 0; i < sub14->nRecords; i++) + { + record = sub14->Records + i; + if (record->varSelector == selector) + break; + } + if (i < sub14->nRecords) + { + if (glyph_rec.n_glyphs > 0 + && glyph_rec.glyphs[glyph_rec.n_glyphs - 1] < 0) + glyph_rec.n_glyphs--; + glyph_rec.codes[glyph_rec.n_glyphs] = selector; + glyph_rec.glyphs[glyph_rec.n_glyphs++] = - idx - 1; + update_render_area (); + } +} + +void RenderProc (Widget w, XtPointer client_data, XtPointer call_data) { - if ((int) client_data < 0) + int data; + + CAST_FROM_XTPOINTER (int, client_data, data); + + if (data < 0) { if (glyph_rec.n_glyphs > 0) { - if ((int) client_data == -2) + if (data == -2) glyph_rec.n_glyphs--; else glyph_rec.n_glyphs = 0; @@ -679,14 +898,16 @@ RenderProc (Widget w, XtPointer client_data, XtPointer call_data) } else if (glyph_rec.n_glyphs < 64) { - int index = glyph_index + (int) client_data; + int index = glyph_index + data; if (charmap_index >= 0) index = FT_Get_Char_Index (face, (FT_ULong) index); if (bitmap[index].pixmap) { - glyph_rec.codes[glyph_rec.n_glyphs] = glyph_index + (int) client_data; + glyph_rec.codes[glyph_rec.n_glyphs] = glyph_index + data; glyph_rec.glyphs[glyph_rec.n_glyphs++] = index; + if (otf) + update_uvs_area (glyph_index + data); update_render_area (); } } @@ -740,43 +961,35 @@ FeatureProc (Widget w, XtPointer client_data, XtPointer call_data) if (idx < 0) { int on = idx == -2; + char str[5]; - 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; - } + for (i = 0; i < rec->langsys->FeatureCount; i++) + if (rec->features[i].on != on) + { + rec->features[i].on = on; + if (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); + } } 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) + rec->features[idx].on = ! rec->features[idx].on; + if (rec->features[idx].on) { XtSetArg (arg[0], XtNborderWidth, 3); XtSetArg (arg[1], XtNinternalHeight, 2); @@ -788,9 +1001,9 @@ FeatureProc (Widget w, XtPointer client_data, XtPointer call_data) XtSetArg (arg[1], XtNinternalHeight, 4); XtSetArg (arg[2], XtNinternalWidth, 4); } - OTF_tag_name (rec->features[i].tag, str); + OTF_tag_name (rec->features[idx].tag, str); XtSetArg (arg[3], XtNlabel, str); - XtSetValues (rec->features[i].w, arg, 4); + XtSetValues (rec->features[idx].w, arg, 4); } update_seq_area (); } @@ -1042,15 +1255,20 @@ create_otf_script_widgets (Widget prev) } else { + Widget box; + XtSetArg (arg[0], XtNborderWidth, 0); + XtSetArg (arg[1], XtNwidth, render_width - (FONT_WIDTH * 15)); + XtSetArg (arg[2], XtNorientation, XtorientHorizontal); + box = XtCreateManagedWidget ("scritp-list", boxWidgetClass, prev, arg, 2); XtSetArg (arg[0], XtNstate, True); - w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1); + w = XtCreateManagedWidget (name, toggleWidgetClass, box, 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); + w = XtCreateManagedWidget (name, toggleWidgetClass, box, arg, 1); XtAddCallback (w, XtNcallback, ScriptProc, NULL); } } @@ -1127,7 +1345,41 @@ create_widgets () XtSetArg (arg[6], XtNdefaultDistance, 0); glyph_area = XtCreateManagedWidget ("glyph-area", formWidgetClass, frame, arg, 7); + XtSetArg (arg[5], XtNfromVert, glyph_area); + if (sub14) + { + Arg arg2[3]; + + XtSetArg (arg[6], XtNorientation, XtorientHorizontal); + uvs_area = XtCreateManagedWidget ("uvs-area", boxWidgetClass, + frame, arg, 7); + XtSetArg (arg2[0], XtNborderWidth, 0); + XtSetArg (arg2[1], XtNlabel, "Variation Selector: "); + uvs_label = XtCreateManagedWidget ("uvs-label", labelWidgetClass, + uvs_area, arg2, 2); + XtSetArg (arg2[0], XtNborderWidth, 1); + for (i = 0; i < sub14->nRecords; i++) + { + OTF_VariationSelectorRecord *record = sub14->Records + i; + unsigned selector = record->varSelector; + unsigned idx; + char lbl[4]; + + idx = (selector <= 0xFE0F ? selector - 0xFE00 + : selector - 0xE0100 + 16); + if (uvs[idx].c) + continue; + uvs[idx].c = selector; + sprintf (lbl, "%03d", idx + 1); + XtSetArg (arg2[1], XtNlabel, lbl); + XtSetArg (arg2[2], XtNsensitive, False); + uvs[idx].w = XtCreateManagedWidget ("lbl", commandWidgetClass, + uvs_area, arg2, 3); + XtAddCallbackWithCast (unsigned, uvs[idx].w, UVSProc, idx); + } + XtSetArg (arg[5], XtNfromVert, uvs_area); + } render_area = XtCreateManagedWidget ("render-area", formWidgetClass, frame, arg, 6); @@ -1155,7 +1407,7 @@ create_widgets () charmap[i + 1] = XtCreateManagedWidget (charmap_rec[i + 1].name, toggleWidgetClass, command_area, arg, 1); - XtAddCallback (charmap[i + 1], XtNcallback, CharmapProc, (XtPointer) i); + XtAddCallbackWithCast (int, charmap[i + 1], CharmapProc, i); } XtSetArg (arg[0], XtNlabel, " |< (f)"); @@ -1229,7 +1481,7 @@ create_widgets () XtSetArg (arg[n], XtNbitmap, none_pixmap), n++; glyph[k] = XtCreateManagedWidget ("glyph", commandWidgetClass, glyph_area, arg, n); - XtAddCallback (glyph[k], XtNcallback, RenderProc, (XtPointer) k); + XtAddCallbackWithCast (int, glyph[k], RenderProc, k); } w = head; } @@ -1306,6 +1558,16 @@ create_widgets () XtSetArg (arg[1], XtNbitmap, seq_pixmap); seq_image = XtCreateManagedWidget ("seq-image", labelWidgetClass, seq, arg, 2); + XtSetArg (arg[6], XtNfromVert, seq); + code = XtCreateManagedWidget ("code", boxWidgetClass, render_area, arg, 7); + XtSetArg (arg[0], XtNborderWidth, 0); + XtSetArg (arg[1], XtNlabel, "code:"); + code_label = XtCreateManagedWidget ("code-label", labelWidgetClass, + code, arg, 2); + XtSetArg (arg[1], XtNlabel, ""); + XtSetArg (arg[2], XtNwidth, render_width); + code_list = XtCreateManagedWidget ("code-list", labelWidgetClass, + code, arg, 3); XtInstallAllAccelerators (shell, shell); } @@ -1339,6 +1601,19 @@ 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) @@ -1381,39 +1656,54 @@ main (int argc, char **argv) if (! font) font = XLoadQueryFont (display, "fixed"); - if (argc != 2 || !strcmp (argv[1], "-h") || !strcmp (argv[1], "--help")) - { - fprintf (stderr, "Usage: %s [ X-OPTION ... ] OTF-FILE\n", - basename (argv[0])); - fprintf (stderr, - " Pixel size is decided by the environment variable PIXEL_SIZE ((default %d).\n", DEFAULT_PIXEL_SIZE); - exit (argc != 2); - } + if (argc < 2) + help (argv, 1); + if (!strcmp (argv[1], "-h") || !strcmp (argv[1], "--help")) + help (argv, 0); filename = argv[1]; - if (strstr (filename, ".ttf") - || strstr (filename, ".TTF") - || strstr (filename, ".otf") - || strstr (filename, ".OTF")) + if (argc > 2) { - otf = OTF_open (filename); - 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; + 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, filename, 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) + { + if (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_close (otf); + otf = NULL; + } + } + if (otf) + for (i = 0; i < otf->cmap->numTables; i++) + if (otf->cmap->EncodingRecord[i].subtable.format == 14) + { + sub14 = otf->cmap->EncodingRecord[i].subtable.f.f14; + break; + } + } + { char title[256]; Arg arg[1]; @@ -1450,9 +1740,11 @@ main (int argc, char **argv) XGCValues values; gc = XCreateGC (display, none_pixmap, (unsigned long) 0, NULL); + XSetFont (display, gc, font->fid); values.function = GXset; values.line_width = 1; gc_set = XCreateGC (display, none_pixmap, valuemask, &values); + XSetFont (display, gc_set, font->fid); values.function = GXor; gc_or = XCreateGC (display, none_pixmap, valuemask, &values); values.function = GXcopyInverted;