📄 ttf2pfb.c
字号:
/* * ttf2pfb.c -- TrueType to PostScript Type 1 Font converter. * * Author: Chun-Yu Lee <d791013@ce.ntu.edu.tw> * Maintainer: Werner Lemberg <wl@gnu.org> * * The generated output is in a raw Type 1 Font format. An encoder * (e.g. t1asm or t1binary) is needed to convert it into PFA or PFB format. * * This program was adapted from the ntu2cjk package (which was part of the * LaTeX2e CJK package (by Werner Lemberg <wl@gnu.org>)). * * * Modified by Joachim H. Kaiser <jhk@cmpnetmail.com> to include real glyph * names and other font infos (see PS_Head function). * The test programs of the FreeType distribution have been heavily used as * templates. * *//* * Requirements: * - the FreeType library. * - t1asm or a similar converter if PFA or PFB format is required. * - getafm or a similar program if AFM font metrics are required. * - afm2tfm or a similar program if TFM font metrics are required. * - for compact fonts: the CJK package for typesetting LaTeX documents. * - dvips 5.66 or higher if self-contained PostScript document * outputs with partially downloaded fonts are required. Note that * the partial download code in dvips is still buggy, causing strange * error messages during loading of the created PS fonts. * - Ghostscript 3.33 or newer (this is optional). */#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <unistd.h>#include <time.h>#ifdef TM_IN_SYS_TIME#include <sys/time.h>#endif#include <ctype.h>#include "freetype.h"#include "extend/ftxpost.h" /* we are in the FreeType package tree */char rcsid[] = "$Id: ttf2pfb.c,v 1.1.1.1 2000/04/14 17:53:50 davidT Exp $";#define PID_UNICODE 3#define EID_UNICODE 1#define PID_SJIS 3#define EID_SJIS 2#define PID_GB 3#define EID_GB 3#define PID_BIG5 3#define EID_BIG5 4#define PID_KS 3 /* KS is also called Wansung */#define EID_KS 5#define PID_JOHAB 3#define EID_JOHAB 6/* Set default values */#ifndef DEFAULT_PLATFORM_ID#define DEFAULT_PLATFORM_ID PID_UNICODE /* MS platform */#endif#ifndef DEFAULT_ENCODING_ID#define DEFAULT_ENCODING_ID EID_UNICODE#endif/* The possible values for the `force_enc' variable. */typedef enum enc_type_{ GB = 1, Big5, JIS, KS, Johab, SJIS, X} enc_type;/* A variable to enforce a certain font encoding (if > 0). */enc_type force_enc = 0;#ifndef TRUE#define TRUE 1#endif#ifndef FALSE#define FALSE 0#endif#ifndef FAILURE#define FAILURE -1#endif#define LINELEN 40 /* max # of columns of code range file */#define NAMELEN 80 /* max length of name used from LookUp *//* * Flags and globals */int verbose = FALSE; /* messages should be printed or not. */int compact = FALSE; /* generate compact font? */int keep = FALSE; /* keep output font in case of error? */int mapping = FALSE; /* use encoding file as mapping? */float fontShift = 0;#ifndef UShorttypedef unsigned short UShort;#endif#ifndef UChartypedef unsigned char UChar;#endif#define TT_Flag_On_Curve 1/* default platform and encoding ID's. */int pid = DEFAULT_PLATFORM_ID;int eid = DEFAULT_ENCODING_ID;char* prog; /* program name *//* for orthogonality with fprintf */#define Fputs(_string_) fprintf(out, "%s\n", _string_)/* Postscript font related defines and functions */TT_F26Dot6 lastpsx, lastpsy;#define Coord(x) (int)(x)#define PS_LastPt(x, y) lastpsx = x; lastpsy = y#define PS_Moveto(x, y) \ fprintf(out, "%d %d rmoveto\n", \ Coord(x - lastpsx), Coord(y - lastpsy)); \ PS_LastPt(x, y)#define PS_Lineto(x, y) \ fprintf(out, "%d %d rlineto\n", \ Coord(x - lastpsx), Coord(y - lastpsy)); \ PS_LastPt(x, y)/* * Freetype globals. */TT_Engine engine;TT_Face face;TT_Instance instance;TT_Glyph glyph;TT_CharMap cmap;TT_Error error;TT_Post post;TT_Outline outline;TT_Glyph_Metrics metrics;TT_Face_Properties properties;/* * Data structures defined for encoding vectors *//* * A code range file for the encoding vector of a font contains code * range pairs, each pair a line. The values for the begin and end of the * ranges are separated by ` - '. Note that the spaces before and after the * minus sign are significant. The possible syntax is as follows: * * (Note that code ranges must appear in ascending order.) * * 1. Absolute range, i.e., the code is at least a two-byte number, e.g.: * * 0xA140 - 0xA17E * 41280 - 41342 * 0xE00000 - 0xE000FF * * The first two lines represent the same range. * * 2. Relative range, i.e., the code is a one-byte number. If the line ends * with a colon `:', it designates the high byte(s) range, otherwise the * low byte range. If there is no high byte(s) range declared before the low * byte range, the last defined high byte(s) range or `0x00 - 0x00:' will be * used. e.g.: * * 0xA1 - 0xFE: * 0x40 - 0x7E * 0xA1 - 0xFE * * which is Big-5 Encoding. * * 3. Single code. Similar to absolute or relative range but the second * number of the range is the same as the first number. E.g.: * * 0xA141 == 0xA141 - 0xA141 * 0xA1: == 0xA1 - 0xA1: * 0xA1 == 0xA1 - 0xA1 * * 4. If the high byte range is declared and there is no low byte range * declared consecutively, the assumed low byte range is `0x00 - 0xFF'. * * 5. Comment line. A line starting with a hash mark `#' followed by any * characters up to the end of the line is ignored. Blank lines are also * discarded. */typedef struct _EVHigh{ UShort start, end;} EVHigh;typedef struct _EVLow{ UChar start, end;} EVLow;typedef struct _EVcRange{ EVHigh high; UShort numLowRanges; EVLow* low;} EVcRange;typedef struct _EncVec{ UShort numCodeRanges; EVcRange* codeRange;} EncVec;/* Select encoding vector with respect to pid and eid */EncVec* eVecMap[5][10];/* Select encoding vector with respect to force_enc */EncVec* eVecMap_force[10];/*************//* Functions *//*************/voidmesg(const char *msg, ...){ va_list ap; va_start(ap, msg); vfprintf(stderr, msg, ap); va_end(ap);}/* * Usage. */voidUsage(int eval){#ifdef DEBUG mesg("Usage: %s [-h][-v][-c][-k][-m][-d charcode][-l][-ng][-nc]\n", prog);#else mesg("Usage: %s [-h][-v][-c][-k][-m]\n", prog);#endif mesg("\t[-pid id] [-eid id] [-force enc] [-enc file]\n"); mesg("\t[-plane pl] [-f fname] [-uid id] [-s shift]\n"); mesg("\t[-o output] [-ttf font.ttf | font.ttf]\n"); mesg("-h\t\tThis message.\n"); mesg("-v\t\tPrint messages during conversion.\n"); mesg("-c\t\tCompact font"); mesg(" (256 chars per font; useful for the CJK package).\n"); mesg("-k\t\tKeep output file in case of error.\n"); mesg("-m\t\tUse encoding file as mapping file.\n");#ifdef DEBUG mesg("-d charcode\tDebug CharString for the given character code.\n"); mesg("-l\t\tDisplay point labels.\n"); mesg("-ng\t\tDo not show glyph outline.\n"); mesg("-nc\t\tDo not show control paths.\n");#endif mesg("-pid id\t\tSet the platform ID [%d].\n", DEFAULT_PLATFORM_ID); mesg("-eid id\t\tSet the encoding ID [%d].\n", DEFAULT_ENCODING_ID); mesg("\t\t(Use a strange pid,eid pair to list all possible pid,eid)\n"); mesg("-force enc\tForce a certain encoding [none].\n"); mesg("\t\t(Possible values are `GB', `JIS', `KS', `SJIS', and `X').\n"); mesg("-enc file\tFile contains code ranges [none].\n"); mesg("-plane pl\tA single font plane [0x0].\n"); mesg("-f fname\tFont name [UNKNOWN].\n"); mesg("-uid id\t\tUnique font ID, for private fonts 4000000-4999999 [4999999].\n"); mesg("-s shift\tY-offset factor [%5.3f].\n", fontShift); mesg("-o outfile\tSet the output filename [stdout].\n"); mesg("-ttf ttfpath\tThe TTF font pathname.\n"); exit(eval);}voidfatal(const char *msg, ...){ va_list ap; va_start(ap, msg); fprintf(stderr, "%s: ", prog); vfprintf(stderr, msg, ap); fprintf(stderr, "\n"); va_end(ap); exit(FAILURE);}voidfatal_error(const char *msg, ...){ va_list ap; va_start(ap, msg); fprintf(stderr, "%s: Error code 0x%04lx: ", prog, error); vfprintf(stderr, msg, ap); fprintf(stderr, "\n"); va_end(ap); exit(FAILURE);}/* * Reallocate a pointer. */void *re_alloc(void* ptr, size_t size, char* sub){ register void* value = realloc(ptr, size); if (value == NULL) fatal("%s: Virtual memory exhausted", sub); return value;}/* * We have to introduce the `dummy' integer to assure correct handling of * the stack. Using `UShort' as the first parameter may fail in case * this type is promoted to a different type (as happens e.g. under * emx for DOS). */EncVec*Alloc_EncVec(int dummy, ...){ va_list vp; EncVec* encVec = NULL; EVcRange* cRange = NULL; EVLow* evLow = NULL; UShort numCR, numLows; int i, j; va_start(vp, dummy); numCR = (UShort)va_arg(vp, int); encVec = re_alloc(encVec, 1 * sizeof (EncVec), "Alloc_EncVec"); encVec->numCodeRanges = numCR; cRange = re_alloc(cRange, numCR * sizeof (EVcRange), "Alloc_EncVec"); for (i = 0; i < numCR; i++) { (cRange + i)->high.start = (UShort)va_arg(vp, int); (cRange + i)->high.end = (UShort)va_arg(vp, int); (cRange + i)->numLowRanges = numLows = (UShort)va_arg(vp, int); evLow = NULL; evLow = re_alloc(evLow, numLows * sizeof (EVLow), "Alloc_EncVec"); for (j = 0; j < numLows; j++) { (evLow + j)->start = (UChar)va_arg(vp, int); (evLow + j)->end = (UChar)va_arg(vp, int); } (cRange + i)->low = evLow; } encVec->codeRange = cRange; va_end(vp); return encVec;}voidKnown_Encodings(void){ EncVec* encVec; /* Big-5 encoding */ encVec = Alloc_EncVec(1, 1, 0xA1, 0xFE, 2, 0x40, 0x7E, 0xA1, 0xFE); eVecMap[PID_BIG5][EID_BIG5] = encVec; eVecMap_force[Big5] = encVec; /* GB encoding */ encVec = Alloc_EncVec(2, 1, 0xA1, 0xF7, 1, 0xA1, 0xFE); eVecMap[PID_GB][EID_GB] = encVec; eVecMap_force[GB] = encVec; /* KS encoding */ encVec = Alloc_EncVec(3, 1, 0xA1, 0xFE, 1, 0xA1, 0xFE); eVecMap[PID_KS][EID_KS] = encVec; eVecMap_force[KS] = encVec; /* Johab encoding */ encVec = Alloc_EncVec(4, 3, 0x84, 0xD3, 2, 0x41, 0x7E, 0x81, 0xFE, 0xD8, 0xDE, 2, 0x31, 0x7E, 0x91, 0xFE, 0xE0, 0xF9, 2, 0x31, 0x7E, 0x91, 0xFE); eVecMap[PID_JOHAB][EID_JOHAB] = encVec; eVecMap_force[Johab] = encVec; /* JIS encoding */ encVec = Alloc_EncVec(5, 1, 0xA1, 0xF4, 1, 0xA1, 0xFE); eVecMap_force[JIS] = encVec; eVecMap_force[X] = encVec; /* will be internally translated to SJIS */ /* Unicode encoding */ encVec = Alloc_EncVec(6, 1, 0x00, 0xFF, 1, 0x00, 0xFF); eVecMap[PID_UNICODE][EID_UNICODE] = encVec; /* SJIS encoding */ encVec = Alloc_EncVec(7, 3, 0x0, 0x0, 1, 0xA1, 0xDF, 0x81, 0x9F, 2, 0x40, 0x7E, 0x80, 0xFC, 0xE0, 0xEF, 2, 0x40, 0x7E, 0x80, 0xFC); eVecMap[PID_SJIS][EID_SJIS] = encVec; eVecMap_force[SJIS] = encVec;}/* * Convert JIS to SJIS encoding. */UShortJIS_to_SJIS(UShort code){ UShort index; UShort cc0 = (code >> 8) & 0xFF; UShort cc1 = code & 0xFF; index = (cc0 - 0xa1) * (0xfe - 0xa1 + 1) + (cc1 - 0xa1); cc0 = index / ((0x7e - 0x40 + 1) + (0xfc - 0x80 + 1)); cc1 = index % ((0x7e - 0x40 + 1) + (0xfc - 0x80 + 1)); if (cc0 < (0x9f - 0x81 + 1)) cc0 += 0x81; else cc0 += 0xe0 - (0x9f - 0x81 + 1); if (cc1 < (0x7e - 0x40 + 1)) cc1 += 0x40; else cc1 += 0x80 - (0x7E - 0x40 + 1); return (cc0 << 8) + cc1;}/* * Open TTF file and select cmap. */intInit_Font_Engine(char* infile){ UShort cmapindex, platformID, encodingID, num_cmap; if (verbose) printf("Initializing TrueType font engine...\n"); /* initialization of the FreeType engine */ error = TT_Init_FreeType(&engine); if (error) fatal_error("Couldn't initialize FreeType engine"); /* initialization of the post extension */ error = TT_Init_Post_Extension(engine); if (error) fatal_error("Couldn't initialize the post extension"); /* open the input file */ error = TT_Open_Face(engine, infile, &face); if (error) fatal_error("Unable to open input file `%s'", infile); /* load full post table */ error = TT_Load_PS_Names(face, &post); if (error) fatal_error("Unable to load post table"); /* get face properties */ TT_Get_Face_Properties(face, &properties); /* Load the instance. */ error = TT_New_Instance(face, &instance); if (error) fatal_error("Couldn't create instance"); error = TT_Set_Instance_Resolutions(instance, 600, 600); if (error) fatal_error("Error setting resolutions"); error = TT_Set_Instance_CharSize(instance, 120 * 64); if (error) fatal_error("Error setting character size"); error = TT_New_Glyph(face, &glyph); if (error) fatal_error("Couldn't create new glyph"); /* Get the requested cmap. */ num_cmap = TT_Get_CharMap_Count(face); for (cmapindex = 0; cmapindex < num_cmap; cmapindex++) { TT_Get_CharMap_ID(face, cmapindex, &platformID, &encodingID); if (platformID == pid && encodingID == eid) break; } if (cmapindex == num_cmap) { mesg("Possible platform and encoding ID pairs:"); for (cmapindex = 0; cmapindex < num_cmap; cmapindex++) { TT_Get_CharMap_ID(face, cmapindex, &platformID, &encodingID); mesg(" (%d, %d)", platformID, encodingID); } mesg ("\n"); fatal("No character map for given platform %d, encoding %d", pid, eid); } /* malloc for glyph data */ error = TT_Get_CharMap(face, cmapindex, &cmap); if (error) fatal_error("Cannot load cmap"); return TRUE;}/* * Get font infos: name, version, copyright. */char*LookUp_Name(int index){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -