diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
commit | 487ca4806cc046076293cf6cc5fbba0db282bac7 (patch) | |
tree | 847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/ttf2pk/ttfaux.c | |
parent | a3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff) |
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/ttf2pk/ttfaux.c')
-rw-r--r-- | Build/source/texk/ttf2pk/ttfaux.c | 714 |
1 files changed, 714 insertions, 0 deletions
diff --git a/Build/source/texk/ttf2pk/ttfaux.c b/Build/source/texk/ttf2pk/ttfaux.c new file mode 100644 index 00000000000..c89134117a6 --- /dev/null +++ b/Build/source/texk/ttf2pk/ttfaux.c @@ -0,0 +1,714 @@ +/* + * ttfaux.c + * + * This file is part of the ttf2pk package. + * + * Copyright 1997-1999, 2000 by + * Frederic Loyer <loyer@ensta.fr> + * Werner Lemberg <wl@gnu.org> + */ + +#include <math.h> +#include <string.h> +#include <stdlib.h> + +#include "freetype.h" +#include "extend/ftxkern.h" /* we are in the FreeType package tree */ +#include "extend/ftxpost.h" +#include "extend/ftxopen.h" + +#include "ttf2tfm.h" +#include "newobj.h" +#include "ligkern.h" +#include "ttfenc.h" +#include "tfmaux.h" +#include "errormsg.h" +#include "ttfaux.h" +#include "filesrch.h" + + +#define Macintosh_platform 1 +#define Macintosh_encoding 0 + +#define Microsoft_platform 3 +#define Microsoft_Unicode_encoding 1 + +#define SCRIPT_kana MAKE_TT_TAG('k', 'a', 'n', 'a') +#define SCRIPT_hani MAKE_TT_TAG('h', 'a', 'n', 'i') +#define SCRIPT_hang MAKE_TT_TAG('h', 'a', 'n', 'g') + +#define LANGUAGE_JAN MAKE_TT_TAG('J', 'A', 'N', ' ') +#define LANGUAGE_CHN MAKE_TT_TAG('C', 'H', 'N', ' ') +#define LANGUAGE_KOR MAKE_TT_TAG('K', 'O', 'R', ' ') + +#define FEATURE_vert MAKE_TT_TAG('v', 'e', 'r', 't') + + +extern char progname[]; + +char *real_ttfname; + +TT_Engine engine; +TT_Face face; +TT_Instance instance; +TT_Glyph glyph; +TT_Outline outline; +TT_CharMap char_map; +TT_Matrix matrix1, matrix2; + +TT_Big_Glyph_Metrics metrics; +TT_Face_Properties properties; +TT_BBox bbox; + +TT_Kerning directory; +TT_Post post; + +TTO_GSUBHeader gsub_; +TTO_GSUBHeader *gsub; + +Boolean has_gsub; + + + +static void +readttf_kern(Font *fnt) +{ + register kern *nk; + register ttfinfo *ti; + TT_Kern_0_Pair* pairs0; + TT_Error error; + unsigned int i, j; + + + if ((error = TT_Get_Kerning_Directory(face, &directory))) + oops("Cannot get kerning directory (error code = 0x%x).", error); + + if (directory.nTables == 0) + return; + + for (i = 0; i < directory.nTables; i++) + { + if ((error = TT_Load_Kerning_Table(face, i))) + oops("Cannot load kerning table (error code = 0x%x).", error); + + switch (directory.tables[i].format) + { + case 0: + pairs0 = directory.tables[i].t.kern0.pairs; + for (j = 0; j < directory.tables[i].t.kern0.nPairs; j++, pairs0++) + { + ti = findglyph(pairs0->left, fnt->charlist); + if (ti == NULL) + warning("kern char not found"); + else + { + nk = newkern(); + nk->succ = findglyph(pairs0->right, fnt->charlist)->adobename; + nk->delta = transform(pairs0->value * 1000 / fnt->units_per_em, 0, + fnt->efactor, fnt->slant); + nk->next = ti->kerns; + ti->kerns = nk; + } + } + return; /* we stop after the first format 0 kerning table */ + + default: + break; + } + } + return; +} + + +void +readttf(Font *fnt, Boolean quiet, Boolean only_range) +{ + TT_Error error; + ttfinfo *ti, *Ti; + long Num, index; + unsigned int i, j; + long k, max_k; + unsigned short num_cmap; + unsigned short cmap_plat, cmap_enc; + int index_array[257]; + + static Boolean initialized = False; + + TT_UShort in_string[2]; + TTO_GSUB_String in, out; + + TT_UShort script_index, language_index, feature_index; + TT_UShort req_feature_index = 0xFFFF; + + + /* + * We allocate a placeholder boundary and the `.notdef' character. + */ + + if (!only_range) + { + ti = newchar(fnt); + ti->charcode = -1; + ti->adobename = ".notdef"; + + ti = newchar(fnt); + ti->charcode = -1; + ti->adobename = "||"; /* boundary character name */ + } + + /* + * Initialize FreeType engine. + */ + + if (!initialized) + { + if ((error = TT_Init_FreeType(&engine))) + oops("Cannot initialize engine (error code = 0x%x).", error); + + if ((error = TT_Init_Kerning_Extension(engine))) + oops("Cannot initialize kerning (error code = 0x%x).", error); + + if (fnt->PSnames) + if ((error = TT_Init_Post_Extension(engine))) + oops("Cannot initialize PS name support (error code = 0x%x).", error); + + if (fnt->rotate) + if ((error = TT_Init_GSUB_Extension(engine))) + oops("Cannot initialize GSUB support (error code = 0x%x).", error); + + /* + * Load face. + */ + + real_ttfname = TeX_search_ttf_file(&(fnt->ttfname)); + if (!real_ttfname) + oops("Cannot find `%s'.", fnt->ttfname); + + if ((error = TT_Open_Face(engine, real_ttfname, &face))) + oops("Cannot open `%s'.", real_ttfname); + + /* + * Get face properties and allocate preload arrays. + */ + + TT_Get_Face_Properties(face, &properties); + + /* + * Now we try to open the proper font in a collection. + */ + + if (fnt->fontindex != 0) + { + if (properties.num_Faces == 1) + { + warning("This isn't a TrueType collection.\n" + "Parameter `-f' is ignored."); + fnt->fontindex = 0; + fnt->fontindexparam = NULL; + } + else + { + TT_Close_Face(face); + if ((error = TT_Open_Collection(engine, real_ttfname, + fnt->fontindex, &face))) + oops("Cannot open font %lu in TrueType Collection `%s'.", + fnt->fontindex, real_ttfname); + } + } + + /* + * Create instance. + */ + + if ((error = TT_New_Instance(face, &instance))) + oops("Cannot create instance for `%s' (error code = 0x%x).", + real_ttfname, error); + + /* + * We use a dummy glyph size of 10pt. + */ + + if ((error = TT_Set_Instance_CharSize(instance, 10 * 64))) + oops("Cannot set character size (error code = 0x%x).", error); + + matrix1.xx = (TT_Fixed)(floor(fnt->efactor * 1024) * (1L<<16)/1024); + matrix1.xy = (TT_Fixed)(floor(fnt->slant * 1024) * (1L<<16)/1024); + matrix1.yx = (TT_Fixed)0; + matrix1.yy = (TT_Fixed)(1L<<16); + + if (fnt->rotate) + { + matrix2.xx = 0; + matrix2.yx = 1L << 16; + matrix2.xy = -matrix2.yx; + matrix2.yy = matrix2.xx; + } + + if ((error = TT_Set_Instance_Transform_Flags( + instance, + fnt->rotate ? 1 : 0, + fnt->efactor != 1.0 ? 1 : 0))) + oops("Cannot set transform flags (error code = 0x%x).", error); + + /* + * Create glyph container. + */ + + if ((error = TT_New_Glyph(face, &glyph))) + oops("Cannot create glyph container (error code = 0x%x).", error); + + fnt->units_per_em = properties.header->Units_Per_EM; + fnt->fixedpitch = properties.postscript->isFixedPitch; + fnt->italicangle = properties.postscript->italicAngle / 65536.0; + + if (fnt->PSnames != Only) + { + num_cmap = properties.num_CharMaps; + for (i = 0; i < num_cmap; i++) + { + if ((error = TT_Get_CharMap_ID(face, i, &cmap_plat, &cmap_enc))) + oops("Cannot query cmap (error code = 0x%x).", error); + if (cmap_plat == fnt->pid && cmap_enc == fnt->eid) + break; + } + if (i == num_cmap) + { + fprintf(stderr, "%s: ERROR: Invalid platform and/or encoding ID.\n", + progname); + if (num_cmap == 1) + fprintf(stderr, " The only valid PID/EID pair is"); + else + fprintf(stderr, " Valid PID/EID pairs are:\n"); + for (i = 0; i < num_cmap; i++) + { + TT_Get_CharMap_ID(face, i, &cmap_plat, &cmap_enc); + fprintf(stderr, " (%i,%i)\n", cmap_plat, cmap_enc); + } + fprintf(stderr, "\n"); + exit(1); + } + + if ((error = TT_Get_CharMap(face, i, &char_map))) + oops("Cannot load cmap (error code = 0x%x).", error); + } + + if (fnt->PSnames) + { + if ((error = TT_Load_PS_Names(face, &post))) + oops("Cannot load TrueType PS names (error code = 0x%x).", error); + } + else if (cmap_plat == Microsoft_platform && + cmap_enc == Microsoft_Unicode_encoding) + set_encoding_scheme(encUnicode, fnt); + else if (cmap_plat == Macintosh_platform && + cmap_enc == Macintosh_encoding) + set_encoding_scheme(encMac, fnt); + else + set_encoding_scheme(encFontSpecific, fnt); + + if (fnt->rotate) + { + gsub = &gsub_; + + error = TT_Load_GSUB_Table(face, gsub, NULL); + if (!error) + has_gsub = True; + else if (error != TT_Err_Table_Missing) + warning("Cannot load GSUB table (error code = 0x%x).", error); + else + warning("No GSUB data available " + "for vertical glyph presentation forms."); + + /* we check for the `vert' feature in Chinese, Japanese, and Korean */ + + error = TT_GSUB_Select_Script(gsub, + SCRIPT_kana, + &script_index); + if (error) + goto check_hani; + error = TT_GSUB_Select_Feature(gsub, + FEATURE_vert, + script_index, + 0xFFFF, + &feature_index); + if (error) + { + error = TT_GSUB_Select_Language(gsub, + LANGUAGE_JAN, + script_index, + &language_index, + &req_feature_index); + if (error) + goto check_hani; + error = TT_GSUB_Select_Feature(gsub, + FEATURE_vert, + script_index, + language_index, + &feature_index); + if (error) + goto check_hani; + else + goto Done; + } + else + goto Done; + + check_hani: + error = TT_GSUB_Select_Script(gsub, + SCRIPT_hani, + &script_index); + if (error) + goto check_hang; + error = TT_GSUB_Select_Feature(gsub, + FEATURE_vert, + script_index, + 0xFFFF, + &feature_index); + if (error) + { + error = TT_GSUB_Select_Language(gsub, + LANGUAGE_CHN, + script_index, + &language_index, + &req_feature_index); + if (error) + goto check_hang; + error = TT_GSUB_Select_Feature(gsub, + FEATURE_vert, + script_index, + language_index, + &feature_index); + if (error) + goto check_hang; + else + goto Done; + } + else + goto Done; + + check_hang: + error = TT_GSUB_Select_Script(gsub, + SCRIPT_hang, + &script_index); + if (error) + goto Done; + error = TT_GSUB_Select_Feature(gsub, + FEATURE_vert, + script_index, + 0xFFFF, + &feature_index); + if (error) + { + error = TT_GSUB_Select_Language(gsub, + LANGUAGE_KOR, + script_index, + &language_index, + &req_feature_index); + if (error) + goto Done; + error = TT_GSUB_Select_Feature(gsub, + FEATURE_vert, + script_index, + language_index, + &feature_index); + } + + Done: + if (error) + { + warning("There is no data for vertical typesetting in GSUB table."); + has_gsub = False; + } + + if (req_feature_index != 0xFFFF) + TT_GSUB_Add_Feature(gsub, req_feature_index, ALL_GLYPHS); + TT_GSUB_Add_Feature(gsub, feature_index, ALL_GLYPHS); + + in.length = 1; + in.pos = 0; + in.string = in_string; + in.properties = NULL; + + out.pos = 0; + out.allocated = 0; + out.string = NULL; + out.properties = NULL; + } + + initialized = True; + } + + if (!quiet) + { + if (only_range) + printf("\n\n%s:\n", fnt->fullname); + printf("\n"); + printf("Glyph Code Glyph Name "); + printf("Width llx lly urx ury\n"); + printf("---------------------------------------"); + printf("---------------------------------\n"); + } + + /* + * We load only glyphs with a valid cmap entry. Nevertheless, for + * the default mapping, we use the first 256 glyphs addressed by + * ascending code points, followed by glyphs not in the cmap. + * + * If we compute a range, we take the character codes given in + * the fnt->sf_code array. + * + * If the -N flag is set, no cmap is used at all. Instead, the + * first 256 glyphs (with a valid PS name) are used for the default + * mapping. + */ + + if (!only_range) + for (i = 0; i < 257; i++) + index_array[i] = 0; + else + for (i = 0; i < 256; i++) + fnt->inencptrs[i] = 0; + + j = 0; + if (fnt->PSnames == Only) + max_k = properties.num_Glyphs - 1; + else + max_k = only_range ? 0xFF : 0x16FFFF; + + for (k = 0; k <= max_k; k++) + { + char *an; + + + if (fnt->PSnames != Only) + { + if (only_range) + { + index = fnt->sf_code[k]; + if (index < 0) + continue; + j = k; + } + else + index = k; + + Num = TT_Char_Index(char_map, index); + + /* now we try to get a vertical glyph form */ + + if (has_gsub) + { + in_string[0] = Num; + error = TT_GSUB_Apply_String(gsub, &in, &out); + if (error && error != TTO_Err_Not_Covered) + warning("Cannot get the vertical glyph form for glyph index %d.", + Num); + else + Num = out.string[0]; + } + + if (Num < 0) + oops("Failure on cmap mapping from %s.", fnt->ttfname); + if (Num == 0) + continue; + if (!only_range) + if (Num <= 256) + index_array[Num] = 1; + } + else + { + Num = k; + index = 0; + } + + error = TT_Load_Glyph(instance, glyph, Num, 0); + if (!error) + error = TT_Get_Glyph_Big_Metrics(glyph, &metrics); + if (!error) + error = TT_Get_Glyph_Outline(glyph, &outline); + if (!error) + { + if (fnt->efactor != 1.0 || fnt->slant != 0.0 ) + TT_Transform_Outline(&outline, &matrix1); + if (fnt->rotate) + TT_Transform_Outline(&outline, &matrix2); + } + if (!error) + error = TT_Get_Outline_BBox(&outline, &bbox); /* we need the non- + grid-fitted bbox */ + if (!error) + { + if (fnt->PSnames) + (void)TT_Get_PS_Name(face, Num, &an); + else + an = code_to_adobename(index); + + /* ignore characters not usable for typesetting with TeX */ + + if (strcmp(an, ".notdef") == 0) + continue; + if (strcmp(an, ".null") == 0) + continue; + if (strcmp(an, "nonmarkingreturn") == 0) + continue; + + ti = newchar(fnt); + ti->charcode = index; + ti->glyphindex = Num; + ti->adobename = an; + ti->llx = bbox.xMin * 1000 / fnt->units_per_em; + ti->lly = bbox.yMin * 1000 / fnt->units_per_em; + ti->urx = bbox.xMax * 1000 / fnt->units_per_em; + ti->ury = bbox.yMax * 1000 / fnt->units_per_em; + + /* + * We must now shift the rotated character both horizontally + * and vertically. The vertical amount is 25% by default. + */ + + if (fnt->rotate) + { + ti->llx += (metrics.vertBearingY - bbox.xMin) * + 1000 / fnt->units_per_em; + ti->lly -= 1000 * fnt->y_offset; + ti->urx += (metrics.vertBearingY - bbox.xMin) * + 1000 / fnt->units_per_em; + ti->ury -= 1000 * fnt->y_offset; + } + + /* + * We need to avoid negative heights or depths. They break accents + * in math mode, among other things. + */ + + if (ti->lly > 0) + ti->lly = 0; + if (ti->ury < 0) + ti->ury = 0; + if (fnt->rotate) + ti->width = metrics.vertAdvance * 1000 / fnt->units_per_em; + else + ti->width = transform(metrics.horiAdvance * 1000 / fnt->units_per_em, + 0, fnt->efactor, fnt->slant); + + if (!quiet) + printf("%5ld %05lx %-25s %5d % 5d,% 5d -- % 5d,% 5d\n", + Num, index, ti->adobename, + ti->width, + ti->llx, ti->lly, ti->urx, ti->ury); + + if (j < 256) + { + fnt->inencptrs[j] = ti; + ti->incode = j; + } + j++; + } + } + + /* + * Now we load glyphs without a cmap entry, provided some slots are + * still free -- we skip this if we have to compute a range or use + * PS names. + */ + + if (!only_range && !fnt->PSnames) + { + for (i = 1; i <= properties.num_Glyphs; i++) + { + char *an; + + + if (index_array[i] == 0) + { + error = TT_Load_Glyph(instance, glyph, i, 0); + if (!error) + error = TT_Get_Glyph_Big_Metrics(glyph, &metrics); + if (!error) + error = TT_Get_Glyph_Outline(glyph, &outline); + if (!error) + error = TT_Get_Outline_BBox(&outline, &bbox); + if (!error) + { + an = code_to_adobename(i | 0x1000000); + + ti = newchar(fnt); + ti->charcode = i | 0x1000000; + ti->glyphindex = i; + ti->adobename = an; + ti->llx = bbox.xMin * 1000 / fnt->units_per_em; + ti->lly = bbox.yMin * 1000 / fnt->units_per_em; + ti->urx = bbox.xMax * 1000 / fnt->units_per_em; + ti->ury = bbox.yMax * 1000 / fnt->units_per_em; + + if (ti->lly > 0) + ti->lly = 0; + if (ti->ury < 0) + ti->ury = 0; + ti->width = transform(metrics.horiAdvance*1000 / fnt->units_per_em, + 0, fnt->efactor, fnt->slant); + + if (!quiet) + printf("%5d %-25s %5d % 5d,% 5d -- % 5d,% 5d\n", + i, ti->adobename, + ti->width, + ti->llx, ti->lly, ti->urx, ti->ury); + + if (j < 256) + { + fnt->inencptrs[j] = ti; + ti->incode = j; + } + else + break; + j++; + } + } + } + } + + /* Finally, we construct a `Germandbls' glyph if necessary */ + + if (!only_range) + { + if (NULL == findadobe("Germandbls", fnt->charlist) && + NULL != (Ti = findadobe("S", fnt->charlist))) + { + pcc *np, *nq; + + + ti = newchar(fnt); + ti->charcode = properties.num_Glyphs | 0x1000000; + ti->glyphindex = properties.num_Glyphs; + ti->adobename = "Germandbls"; + ti->width = Ti->width << 1; + ti->llx = Ti->llx; + ti->lly = Ti->lly; + ti->urx = Ti->width + Ti->urx; + ti->ury = Ti->ury; + ti->kerns = Ti->kerns; + + np = newpcc(); + np->partname = "S"; + nq = newpcc(); + nq->partname = "S"; + nq->xoffset = Ti->width; + np->next = nq; + ti->pccs = np; + ti->constructed = True; + + if (!quiet) + printf("* %-25s %5d % 5d,% 5d -- % 5d,% 5d\n", + ti->adobename, + ti->width, + ti->llx, ti->lly, ti->urx, ti->ury); + } + } + + /* kerning between subfonts isn't available */ + if (!only_range) + readttf_kern(fnt); +} + + +/* end */ |