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); }
int main(int argc, char** argv) { size_t l; unsigned int i; long index, code; FILE *config_file; char *configline, *oldconfigline, *p, *q; Font font; encoding *enc; long inenc_array[256]; char *fontname; size_t fontname_len; char *pk_filename, *tfm_filename, *enc_filename, *cfg_filename; char *real_ttfname, *real_cfg_filename; int dpi = 0, ptsize; Boolean hinting = True; Boolean quiet = False; Boolean no_dpi = False; Boolean testing = False; TeX_search_init(argv[0], "ttf2pk", "TTF2PK"); if (argc == 1) oops("Need at least two arguments.\n" "Try `ttf2pk --help' for more information."); if (argc == 2) { if (strcmp(argv[1], "--help") == 0) usage(); else if (strcmp(argv[1], "--version") == 0) version(); } while (argv[1][0] == '-') { if (argv[1][1] == 'q') quiet = True; else if (argv[1][1] == 'n') no_dpi = True; else if (argv[1][1] == 't') testing = True; else oops("Unknown option `%s'.\n" "Try `ttf2pk --help' for more information.", argv[1]); argv++; argc--; } if (testing) { if (argc != 2) oops("Need exactly one parameter for `-t' option.\n" "Try `ttf2pk --help' for more information."); } else if (argc != 3) oops("Need at most two arguments.\n" "Try `ttf2pk --help' for more information."); if (!quiet) printf("This is %s\n", ident); if (!testing) if ((dpi = atoi(argv[2])) <= 50) oops("dpi value must be larger than 50."); fontname = argv[1]; fontname_len = strlen(fontname); enc_filename = NULL; ptsize = 10; init_font_structure(&font); cfg_filename = newstring("ttfonts.map"); real_cfg_filename = TeX_search_config_file(&cfg_filename); if (!real_cfg_filename) oops("Cannot find file ttfonts.map."); config_file = fopen(real_cfg_filename, "rt"); if (config_file == NULL) oops("Cannot open file ttfonts.map."); do { configline = get_line(config_file); if (!configline) oops("Error while reading ttfonts.map."); if (!*configline) { /* * This is the only error message we suppress if the -q flag * is set, making it possible to call ttf2pk silently. */ if (!quiet) fprintf(stdout, "%s: ERROR: Cannot find font %s in ttfonts.map.\n", progname, fontname); exit(2); } } while (compare(&font, configline, fontname)); fclose(config_file); if (testing) { if (!quiet) fprintf(stdout, "%s\n", configline); exit(0); } /* * Parse the line from the config file. We split the config line buffer * into substrings according to the given options. */ l = strlen(configline); if (configline[l - 1] == '\n') configline[l - 1] = '\0'; /* strip newline */ oldconfigline = newstring(configline); p = configline; while (isspace(*p)) p++; while (*p && !isspace(*p)) p++; q = p; while (*p && isspace(*p)) p++; if (!*p) boops(oldconfigline, q - configline, "TTF file missing."); font.ttfname = p; while (*p && !isspace(*p)) p++; if (*p) *p++ = '\0'; for (; *p; p++) { if (isspace(*p)) continue; if (!strncmp(p, "Slant", 5)) { p = strip_equal(configline, oldconfigline, p + 5); if (sscanf(p, "%f", &(font.slant)) == 0) boops(oldconfigline, p - configline, "Bad `Slant' parameter."); } else if (!strncmp(p, "Encoding", 8)) { if (have_sfd) boops(oldconfigline, p - configline, "No `Encoding' parameter allowed for subfonts."); p = strip_equal(configline, oldconfigline, p + 8); if (!*p) boops(oldconfigline, p - configline, "Bad `Encoding' parameter."); enc_filename = p; } else if (!strncmp(p, "Extend", 6)) { p = strip_equal(configline, oldconfigline, p + 6); if (sscanf(p, "%f", &(font.efactor)) == 0) boops(oldconfigline, p - configline, "Bad `Extend' parameter."); } else if (!strncmp(p, "Fontindex", 9)) { p = strip_equal(configline, oldconfigline, p + 9); if (sscanf(p, "%lu", &(font.fontindex)) < 0) boops(oldconfigline, p - configline, "Bad `Fontindex' parameter."); } else if (!strncmp(p, "Pid", 3)) { p = strip_equal(configline, oldconfigline, p + 3); if (sscanf(p, "%hu", &(font.pid)) < 0) boops(oldconfigline, p - configline, "Bad `Pid' parameter."); have_pid = True; } else if (!strncmp(p, "Eid", 3)) { p = strip_equal(configline, oldconfigline, p + 3); if (sscanf(p, "%hu", &(font.eid)) < 0) boops(oldconfigline, p - configline, "Bad `Eid' parameter."); have_eid = True; } else if (!strncmp(p, "Hinting", 7)) { p = strip_equal(configline, oldconfigline, p + 7); if (p[1] == 'N' || p[1] == 'n' || p[0] == 'Y' || p[1] == 'y' || p[0] == '1') hinting = True; else if (p[1] == 'F' || p[1] == 'f' || p[0] == 'N' || p[1] == 'n' || p[0] == '0') hinting = False; else boops(oldconfigline, p - configline, "Bad `Hinting' parameter."); } else if (!strncmp(p, "PS", 2)) { p = strip_equal(configline, oldconfigline, p + 2); if (p[1] != '\0' && (p[2] == 'l' || p[2] == 'L')) font.PSnames = Only; else if (p[1] == 'N' || p[1] == 'n' || p[0] == 'Y' || p[0] == 'y' || p[0] == '1') font.PSnames = Yes; else if (p[1] == 'F' || p[1] == 'f' || p[0] == 'N' || p[0] == 'n' || p[0] == '0') font.PSnames = No; else boops(oldconfigline, p - configline, "Bad `PS' parameter."); if (have_sfd) boops(oldconfigline, p - configline, "No `PS' parameter allowed for subfonts."); } else if (!strncmp(p, "Rotate", 6)) { p = strip_equal(configline, oldconfigline, p + 6); if (p[1] == 'N' || p[1] == 'n' || p[0] == 'Y' || p[1] == 'y' || p[0] == '1') font.rotate = True; else if (p[1] == 'F' || p[1] == 'f' || p[0] == 'N' || p[1] == 'n' || p[0] == '0') font.rotate = False; else boops(oldconfigline, p - configline, "Bad `Rotate' parameter."); if (!have_sfd) boops(oldconfigline, p - configline, "No `Rotate' parameter allowed for non-subfonts."); } else if (!strncmp(p, "Y-Offset", 8)) { p = strip_equal(configline, oldconfigline, p + 8); if (sscanf(p, "%f", &(font.y_offset)) == 0) boops(oldconfigline, p - configline, "Bad `Y-Offset' parameter."); } else if (!strncmp(p, "Replacement", 11)) { p = strip_equal(configline, oldconfigline, p + 11); if (!*p) boops(oldconfigline, p - configline, "Bad `Replacement' parameter."); font.replacementname = p; } else { char *new_name, *old_name; stringlist *sl; old_name = p; while (*p && !isspace(*p) && *p != '=') p++; q = p; p = strip_equal(configline, oldconfigline, p); *q = '\0'; new_name = p; while (*p && !isspace(*p)) p++; if (*p) *p++ = '\0'; sl = newstringlist(); sl->new_name = new_name; sl->old_name = old_name; sl->next = font.replacements; font.replacements = sl; p--; /* to make the next while loop work */ } while (*p && !isspace(*p)) p++; if (*p) *p = '\0'; } if (font.PSnames == Only) if (have_pid || have_eid) boops(oldconfigline, 0, "No `Pid' or `Eid' parameters allowed if `PS=Only' is set."); font.replacementname = newstring(font.replacementname); get_replacements(&font); tfm_filename = newstring(fontname); TFMopen(&tfm_filename); pk_filename = mymalloc(fontname_len + 10); if (no_dpi) sprintf(pk_filename, "%s.pk", fontname); else sprintf(pk_filename, "%s.%dpk", fontname, dpi); PKopen(pk_filename, fontname, dpi); font.ttfname = newstring(font.ttfname); real_ttfname = TeX_search_ttf_file(&(font.ttfname)); if (!real_ttfname) oops("Cannot find `%s'.", font.ttfname); TTFopen(real_ttfname, &font, dpi, ptsize, quiet); enc_filename = newstring(enc_filename); enc = readencoding(&enc_filename, &font, True); if (enc) { char *name; restore_glyph(enc, &font); for (i = 0; i <= 0xFF; i++) { name = enc->vec[i]; if (!font.PSnames) { code = adobename_to_code(name); if (code < 0 && strcmp(name, ".notdef") != 0) warning("Cannot map character `%s'.", name); inenc_array[i] = code; } else { /* we search the glyph index */ index = TTFsearch_PS_name(name); if (index < 0) warning("Cannot map character `%s'.", name); inenc_array[i] = index | 0x10000; } } } else { if (font.replacements) warning("Replacement glyphs will be ignored."); if (have_sfd) TTFget_subfont(&font, inenc_array); else /* get the table of glyph names too */ enc = TTFget_first_glyphs(&font, inenc_array); } for (i = 0; i <= 0xFF; i++) { byte *bitmap; int w, h, hoff, voff; if ((code = inenc_array[i]) >= 0) { if (!quiet) { printf("Processing glyph %3ld %s index 0x%04x %s\n", (long)i, (code >= 0x10000) ? "glyph" : "code", (unsigned int)(code & 0xFFFF), enc ? enc->vec[i] : ""); fflush(stdout); } if (TTFprocess(&font, code, &bitmap, &w, &h, &hoff, &voff, hinting, quiet)) PKputglyph(i, -hoff, -voff, w - hoff, h - voff, w, h, bitmap); else warning("Cannot render glyph with %s index 0x%x.", (code >= 0x10000) ? "glyph" : "code", (unsigned int)(code & 0xFFFF)); } } PKclose(); exit(0); /* for safety reasons */ return 0; /* never reached */ }
void readttf(Font *fnt, Boolean quiet, Boolean only_range) { FT_Error error; ttfinfo *ti, *Ti; long Num, index; unsigned int i, j; long k, max_k; int index_array[257]; static Boolean initialized = False; /* * 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) { /* * We use a dummy glyph size of 10pt. */ dpi = 92; ptsize = 10 * 64; real_ttfname = TeX_search_ttf_file(&(fnt->ttfname)); if (!real_ttfname) oops("Cannot find `%s'.", fnt->ttfname); FTopen(real_ttfname, fnt, True, True); 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 = face->num_glyphs - 1; else max_k = only_range ? 0xFF : 0x16FFFF; for (k = 0; k <= max_k; k++) { char buff[128]; const char *an; if (fnt->PSnames != Only) { if (only_range) { index = fnt->sf_code[k]; if (index < 0) continue; j = k; } else index = k; Num = FT_Get_Char_Index(face, index); /* now we try to get a vertical glyph form */ if (has_gsub) Num = Get_Vert(Num); 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 = FT_Load_Glyph(face, Num, flags); if (!error) { if (fnt->efactor != 1.0 || fnt->slant != 0.0 ) FT_Outline_Transform(&face->glyph->outline, &matrix1); if (fnt->rotate) FT_Outline_Transform(&face->glyph->outline, &matrix2); error = FT_Outline_Get_BBox(&face->glyph->outline, &bbox); /* we need the non- grid-fitted bbox */ } if (!error) { if (fnt->PSnames) { (void)FT_Get_Glyph_Name(face, Num, buff, 128); an = newstring(buff); } 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; ti->fntnum = fnt->subfont_num; /* * We must now shift the rotated character both horizontally * and vertically. The vertical amount is 25% by default. */ if (fnt->rotate) { ti->llx += (face->glyph->metrics.vertBearingY - bbox.xMin) * 1000 / fnt->units_per_em; ti->lly -= 1000 * fnt->y_offset; ti->urx += (face->glyph->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 = face->glyph->metrics.vertAdvance * 1000 / fnt->units_per_em; else ti->width = transform(face->glyph->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 <= face->num_glyphs; i++) { const char *an; if (index_array[i] == 0) { error = FT_Load_Glyph(face, i, flags); if (!error) error = FT_Outline_Get_BBox(&face->glyph->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(face->glyph->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 = face->num_glyphs | 0x1000000; ti->glyphindex = face->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); }