From 60be24aece73b82bdb895ee9a5e2831110bb307f Mon Sep 17 00:00:00 2001 From: handa Date: Tue, 13 Jul 2004 01:48:03 +0000 Subject: [PATCH] (DEVICE_DELTA): New macro. (adjust_anchor): New function. (mfont__ft_drive_gsub): Renamed from mfont__ft_drive_otf. Drive only GSUB. (mfont__ft_drive_gpos): New function. --- src/font-ft.c | 255 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 179 insertions(+), 76 deletions(-) diff --git a/src/font-ft.c b/src/font-ft.c index 0f6a451..716d363 100644 --- a/src/font-ft.c +++ b/src/font-ft.c @@ -886,58 +886,94 @@ mfont__ft_unparse_name (MFont *font) } #endif /* HAVE_FONTCONFIG */ + +#ifdef HAVE_OTF + +#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, + MGlyph *prev, int size, int *x, int *y) +{ + if (anchor->AnchorFormat == 2 && prev) + { + FT_Outline *outline; + int ap = anchor->f.f1.AnchorPoint; + + FT_Load_Glyph (ft_face, (FT_UInt) prev->code, 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, size); + *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, size); + } +} + int -mfont__ft_drive_otf (MGlyphString *gstring, int from, int to, - MRealizedFont *rfont, - MSymbol script, MSymbol langsys, - MSymbol gsub_features, MSymbol gpos_features) +mfont__ft_drive_gsub (MGlyphString *gstring, int from, int to) { int len = to - from; MGlyph g; int i; -#ifdef HAVE_OTF MFTInfo *ft_info; OTF *otf; OTF_GlyphString otf_gstring; OTF_Glyph *otfg; char *script_name, *language_name; - char *gsub_feature_names, *gpos_feature_names; + char *gsub_feature_names; int from_pos, to_pos; - int unitsPerEm; + int need_cmap; if (len == 0) return from; - ft_info = (MFTInfo *) rfont->info; + g = gstring->glyphs[from]; + ft_info = g.rface->rfont->info; if (ft_info->otf_flag < 0) goto simple_copy; otf = ft_info->otf; - if (! otf && (otf = OTF_open (ft_info->filename))) + if (! otf) { - if (OTF_get_table (otf, "head") < 0 - || (OTF_check_table (otf, "GSUB") < 0 - && OTF_check_table (otf, "GPOS") < 0)) + otf = OTF_open (ft_info->filename); + if (otf && OTF_get_table (otf, "head") < 0) { OTF_close (otf); + otf = NULL; + } + if (! otf) + { ft_info->otf_flag = -1; - ft_info->otf = NULL; goto simple_copy; } ft_info->otf = otf; } - script_name = msymbol_name (script); - language_name = langsys != Mnil ? msymbol_name (langsys) : NULL; + if (g.otf_cmd->script != Mnil) + script_name = msymbol_name (g.otf_cmd->script); + else + script_name = NULL; + if (g.otf_cmd->langsys != Mnil) + language_name = msymbol_name (g.otf_cmd->langsys); + else + language_name = NULL; gsub_feature_names - = (gsub_features == Mt ? "*" - : gsub_features == Mnil ? NULL - : msymbol_name (gsub_features)); - gpos_feature_names - = (gpos_features == Mt ? "*" - : gpos_features == Mnil ? NULL - : msymbol_name (gpos_features)); + = (g.otf_cmd->gsub_features == Mt ? "*" + : g.otf_cmd->gsub_features == Mnil ? NULL + : msymbol_name (g.otf_cmd->gsub_features)); + if (gsub_feature_names && OTF_check_table (otf, "GSUB") < 0) + gsub_feature_names = NULL; + if (! gsub_feature_names) + goto simple_copy; - g = gstring->glyphs[from]; from_pos = g.pos; to_pos = g.to; for (i = from + 1; i < to; i++) @@ -948,11 +984,10 @@ mfont__ft_drive_otf (MGlyphString *gstring, int from, int to, to_pos = gstring->glyphs[i].to; } - unitsPerEm = otf->head->unitsPerEm; otf_gstring.size = otf_gstring.used = len; otf_gstring.glyphs = (OTF_Glyph *) alloca (sizeof (OTF_Glyph) * len); memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len); - for (i = 0; i < len; i++) + for (i = 0, need_cmap = 0; i < len; i++) { if (gstring->glyphs[from + i].otf_encoded) { @@ -962,12 +997,16 @@ mfont__ft_drive_otf (MGlyphString *gstring, int from, int to, else { otf_gstring.glyphs[i].c = gstring->glyphs[from + i].code; + need_cmap++; } } - - if (OTF_drive_tables (otf, &otf_gstring, script_name, language_name, - gsub_feature_names, gpos_feature_names) < 0) + if (need_cmap + && OTF_drive_cmap (otf, &otf_gstring) < 0) + goto simple_copy; + if (OTF_drive_gsub (otf, &otf_gstring, script_name, language_name, + gsub_feature_names) < 0) goto simple_copy; + g.pos = from_pos; g.to = to_pos; for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++) @@ -977,49 +1016,6 @@ mfont__ft_drive_otf (MGlyphString *gstring, int from, int to, if (otfg->glyph_id) { g.code = otfg->glyph_id; - switch (otfg->positioning_type) - { - case 1: case 2: - { - int off_x = 128, off_y = 128; - - if (otfg->f.f1.format & OTF_XPlacement) - off_x = ((double) (otfg->f.f1.value->XPlacement) - * 100 / unitsPerEm + 128); - if (otfg->f.f1.format & OTF_YPlacement) - off_y = ((double) (otfg->f.f1.value->YPlacement) - * 100 / unitsPerEm + 128); - g.combining_code - = MAKE_COMBINING_CODE (3, 2, 3, 0, off_y, off_x); - if ((otfg->f.f1.format & OTF_XAdvance) - || (otfg->f.f1.format & OTF_YAdvance)) - off_y--; - } - break; - case 3: - /* Not yet supported. */ - break; - case 4: - { - int off_x, off_y; - - off_x = ((double) (otfg->f.f4.base_anchor->XCoordinate - - otfg->f.f4.mark_anchor->XCoordinate) - * 100 / unitsPerEm + 128); - off_y = ((double) (otfg->f.f4.base_anchor->YCoordinate - - otfg->f.f4.mark_anchor->YCoordinate) - * 100 / unitsPerEm + 128); - g.combining_code - = MAKE_COMBINING_CODE (3, 0, 3, 0, off_y, off_x); - } - break; - case 5: - /* Not yet supported. */ - break; - default: /* i.e case 6 */ - /* Not yet supported. */ - break; - } g.otf_encoded = 1; } else @@ -1032,7 +1028,6 @@ mfont__ft_drive_otf (MGlyphString *gstring, int from, int to, return to; simple_copy: -#endif /* HAVE_OTF */ for (i = 0; i < len; i++) { g = gstring->glyphs[from + i]; @@ -1042,16 +1037,124 @@ mfont__ft_drive_otf (MGlyphString *gstring, int from, int to, } int +mfont__ft_drive_gpos (MGlyphString *gstring, int from, int to) +{ + int len = to - from; + MGlyph *g, *prev; + int i; + MFTInfo *ft_info; + OTF *otf; + OTF_GlyphString otf_gstring; + OTF_Glyph *otfg; + char *script_name, *language_name; + char *gpos_feature_names; + int u; + int size10, size; + + if (len == 0) + return from; + + g = MGLYPH (from); + ft_info = g->rface->rfont->info; + if (ft_info->otf_flag < 0) + return to; + otf = ft_info->otf; + if (! otf) + return to; + if (g->otf_cmd->script != Mnil) + script_name = msymbol_name (g->otf_cmd->script); + else + script_name = NULL; + if (g->otf_cmd->langsys != Mnil) + language_name = msymbol_name (g->otf_cmd->langsys); + else + language_name = NULL; + gpos_feature_names + = (g->otf_cmd->gpos_features == Mt ? "*" + : g->otf_cmd->gpos_features == Mnil ? NULL + : msymbol_name (g->otf_cmd->gpos_features)); + if (gpos_feature_names && OTF_check_table (otf, "GPOS") < 0) + gpos_feature_names = NULL; + if (! gpos_feature_names) + return to; + + otf_gstring.size = otf_gstring.used = len; + otf_gstring.glyphs = (OTF_Glyph *) alloca (sizeof (OTF_Glyph) * len); + memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len); + for (i = 0; i < len; i++) + { + otf_gstring.glyphs[i].c = gstring->glyphs[from + i].c; + otf_gstring.glyphs[i].glyph_id = gstring->glyphs[from + i].code; + } + if (OTF_drive_gpos (otf, &otf_gstring, script_name, language_name, + gpos_feature_names) < 0) + return to; + + u = otf->head->unitsPerEm; + size10 = g->rface->rfont->font.property[MFONT_SIZE]; + size = size10 / 10; + prev = NULL; + for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; + prev = g++, i++, otfg++) + switch (otfg->positioning_type) + { + case 0: + break; + case 1: case 2: + { + int format = otfg->f.f1.format; + + if (format & OTF_XPlacement) + g->xoff = otfg->f.f1.value->XPlacement * size10 / u / 10; + if (format & OTF_XPlaDevice) + g->xoff += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, size); + if (format & OTF_YPlacement) + g->yoff = otfg->f.f1.value->YPlacement * size10 / u / 10; + if (format & OTF_YPlaDevice) + g->yoff += DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, size); + } + break; + case 3: + /* Not yet supported. */ + break; + case 4: + { + int base_x, base_y, mark_x, mark_y; + + base_x = otfg->f.f4.base_anchor->XCoordinate * size10 / u / 10; + base_y = otfg->f.f4.base_anchor->YCoordinate * size10 / u / 10; + mark_x = otfg->f.f4.mark_anchor->XCoordinate * size10 / u / 10; + mark_y = otfg->f.f4.mark_anchor->YCoordinate * size10 / u / 10; + + if (otfg->f.f4.base_anchor->AnchorFormat != 1) + adjust_anchor (otfg->f.f4.base_anchor, ft_info->ft_face, + prev, size, &base_x, &base_y); + if (otfg->f.f4.mark_anchor->AnchorFormat != 1) + adjust_anchor (otfg->f.f4.mark_anchor, ft_info->ft_face, + prev, size, &mark_x, &mark_y); + g->xoff = (base_x - prev->width) - mark_x; + g->yoff = base_y - mark_y; + } + break; + case 5: + /* Not yet supported. */ + break; + default: /* i.e case 6 */ + /* Not yet supported. */ + break; + } + return to; +} + +int mfont__ft_decode_otf (MGlyph *g) { -#ifdef HAVE_OTF MFTInfo *ft_info = (MFTInfo *) g->rface->rfont->info; int c = OTF_get_unicode (ft_info->otf, (OTF_GlyphID) g->code); return (c ? c : -1); -#else /* not HAVE_OTF */ - return -1; -#endif /* not HAVE_OTF */ } +#endif /* HAVE_OTF */ + #endif /* HAVE_FREETYPE */ -- 1.7.10.4