diff options
author | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
commit | ad547a6b5986815fda458221149728d9d9ab1d87 (patch) | |
tree | 16296910eb3eca724371474ea9aea3994dc69614 /Build/source/texk/ttf2pk2/tfmaux.c | |
parent | 947b43de3dd21d58ccc2ffadefc4441ea1c2a813 (diff) |
restore Build,TODO from r57911
git-svn-id: svn://tug.org/texlive/trunk@57915 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/ttf2pk2/tfmaux.c')
-rw-r--r-- | Build/source/texk/ttf2pk2/tfmaux.c | 639 |
1 files changed, 639 insertions, 0 deletions
diff --git a/Build/source/texk/ttf2pk2/tfmaux.c b/Build/source/texk/ttf2pk2/tfmaux.c new file mode 100644 index 00000000000..d0fe18cf14a --- /dev/null +++ b/Build/source/texk/ttf2pk2/tfmaux.c @@ -0,0 +1,639 @@ +/* + * tfmaux.c + * + * This file is part of the ttf2pk package. + * + * Copyright 1997-1999, 2000, 2002 by + * Frederic Loyer <loyer@ensta.fr> + * Werner Lemberg <wl@gnu.org> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "ttf2tfm.h" +#include "newobj.h" +#include "tfmaux.h" +#include "errormsg.h" + + +#undef PI +#define PI 3.14159265358979323846264338327 + + +struct sf /* we need this for subfont ligatures */ +{ + long sf_code; + int position; +}; + + +static long nextd; /* smallest value that will give a different mincover */ + + +static int lf, lh, nw, nh, nd, ni, nl, nk, ne, np; +static int bc, ec; + +static long *header, *charinfo, + *width, *height, *depth, + *ligkern, *kerns, *tparam, + *italic; + + +static int source[257]; /* utility variables for sorting tfm arrays */ +static int unsort[257]; + + +/* + * A simple function for sorting sf_array (in inverse order) + */ + +static int +compare_sf(const void *a, const void *b) +{ + return (int)(((const struct sf *)b)->sf_code - ((const struct sf *)a)->sf_code); +} + + +/* + * The next routine simply scales something. + * Input is in TFM units per em. Output is in FIXFACTORths of units + * per em. We use 1 em = 1000 TFM units. + */ + +static long +scale(long what) +{ + return ((what / 1000) * FIXFACTOR) + + (((what % 1000) * FIXFACTOR) + 500) / 1000; +} + + +/* + * Next we need a routine to reduce the number of distinct dimensions + * in a TFM file. Given an array what[0]..what[oldn-1], we want to + * group its elements into newn clusters, in such a way that the maximum + * difference between elements of a cluster is as small as possible. + * Furthermore, what[0]=0, and this value must remain in a cluster by + * itself. Data such as `0 4 6 7 9' with newn=3 shows that an iterative + * scheme in which 6 is first clustered with 7 will not work. So we + * borrow a neat algorithm from METAFONT to find the true optimum. + * Memory location what[oldn] is set to 0x7FFFFFFFL for convenience. + */ + + +/* + * Tells how many clusters result, given max difference d. + */ + +static int +mincover(long *what, + register long d) +{ + register int m; + register long l; + register long *p; + + + nextd = 0x7FFFFFFFL; + p = what+1; + m = 1; + + while (*p < 0x7FFFFFFFL) + { + m++; + l = *p; + while (*++p <= l + d) + ; + if (*p - l < nextd) + nextd = *p - l; + } + return m; +} + + +static void +remap(long *what, + int oldn, + int newn, + int *source, + int *unsort) +{ + register int i, j; + register long d, l; + + what[oldn] = 0x7FFFFFFFL; + for (i = oldn-1; i > 0; i--) + { + d = what[i]; + for (j = i; what[j+1] < d; j++) + { + what[j] = what[j+1]; + source[j] = source[j+1]; + } + what[j] = d; + source[j] = i; + } + + i = mincover(what, 0L); + d = nextd; + while (mincover(what, d + d) > newn) + d += d; + while (mincover(what, d) > newn) + d = nextd; + + i = 1; + j = 0; + while (i < oldn) + { + j++; + l = what[i]; + unsort[source[i]] = j; + while (what[++i] <= l + d) + { + unsort[source[i]] = j; + if (i - j == oldn - newn) + d = 0; + } + what[j] = (l + what[i-1])/2; + } +} + + +static void +write16(int what, FILE *out) +{ + (void)fputc(what >> 8, out); + (void)fputc(what & 0xFF, out); +} + + +static void +writearr(register long *p, + register int n, + register FILE *out) +{ + while (n) + { + write16((short)(*p >> 16), out); + write16((short)(*p & 65535), out); + p++; + n--; + } +} + + +static void +writesarr(long *what, + int len, + FILE *out) +{ + register long *p; + int i; + + + p = what; + i = len; + while (i) + { + *p = scale(*p); + (void)scale(*p); /* need this kludge for some compilers */ + p++; + i--; + } + writearr(what, len, out); +} + + +static long * +makebcpl(register long *p, + register const char *s, + register int n) +{ + register long t; + register long sc; + + + if (strlen(s) < n) + n = strlen(s); + t = ((long)n) << 24; + sc = 16; + + while (n > 0) + { + t |= ((long)(*(unsigned const char *)s++)) << sc; + sc -= 8; + if (sc < 0) + { + *p++ = t; + t = 0; + sc = 24; + } + n--; + } + if (t) + *p++ = t; + + return p; +} + + +static long +checksum(ttfinfo **array) +{ + int i; + unsigned long s1 = 0, s2 = 0; + const char *p; + ttfinfo *ti; + + + for (i = 0; i < 256; i++) + if (NULL != (ti = array[i])) + { + s1 = ((s1 << 1) ^ (s1 >> 31)) ^ ti->width; /* cyclic left shift */ + s1 &= 0xFFFFFFFF; /* in case we're on a 64-bit machine */ + + for (p = ti->adobename; *p; p++) + s2 = (s2 * 3) + *p; + } + + s1 = (s1 << 1) ^ s2; + return s1; +} + + +int +transform(register int x, register int y, + float ef, float sl) +{ + register double acc; + + + acc = ef * x + sl * y; + return (int)(acc >= 0 ? floor(acc + 0.5) : ceil(acc - 0.5)); +} + + +int +buildtfm(Font *fnt) +{ + register int i, j; + register ttfinfo *ti; + int byte1, old_byte1, byte2; + double Slant; + char buffer[256]; + struct sf sf_array[256]; + + + if (fnt->subfont_ligs) + { + if (fnt->ligname) + { + for (i = 0; i < 256; i++) + { + sf_array[i].sf_code = fnt->sf_code[i]; + sf_array[i].position = (fnt->sf_code[i] == -1 ? -1 : i); + } + } + else + { + for (i = 0; i < 256; i++) + { + ti = fnt->inencptrs[i]; + if (ti) + { + sf_array[i].sf_code = ti->charcode; + sf_array[i].position = i; + } + else + { + sf_array[i].sf_code = -1; + sf_array[i].position = -1; + } + } + } + /* we sort the subfont character codes before we build a ligkern list */ + qsort(sf_array, 256, sizeof (struct sf), compare_sf); + + /* we need to create dummy characters for the ligatures in case the + character slots of the affected codes are unused */ + i = 0; + while (i < 256 && sf_array[i].sf_code > -1) + { + byte1 = sf_array[i].sf_code >> 8; + byte2 = sf_array[i].sf_code & 0xFF; + if (!fnt->inencptrs[byte1]) + { + ti = newchar(fnt); + ti->llx = ti->lly = 0; + ti->urx = ti->ury = 0; + ti->width = 0; + fnt->inencptrs[byte1] = ti; + ti->incode = byte1; + ti->adobename = ".dummy"; + } + if (!fnt->inencptrs[byte2]) + { + ti = newchar(fnt); + ti->llx = ti->lly = 0; + ti->urx = ti->ury = 0; + ti->width = 0; + fnt->inencptrs[byte2] = ti; + ti->incode = byte2; + ti->adobename = ".dummy"; + } + i++; + } + } + + for (i = 0; i <= 0xFF && fnt->inencptrs[i] == NULL; i++) + ; + bc = i; + for (i = 0xFF; i >= 0 && fnt->inencptrs[i] == NULL; i--) + ; + ec = i; + + if (ec < bc) + { + if (fnt->sfdname) + return 0; + else + oops("No TTF characters."); + } + + header = (long *)mycalloc(40000L, sizeof(char)); + fnt->cksum = checksum(fnt->inencptrs); + header[0] = fnt->cksum; + header[1] = 0xA00000; /* 10pt design size */ + + (void)makebcpl(header + 2, fnt->codingscheme, 39); + (void)makebcpl(header + 12, fnt->fullname, 19); + + /* 4 bytes are left free for the unused FACE value */ + + buffer[0] = '\0'; + strncat(buffer, "Created by `", 12); + strncat(buffer, fnt->titlebuf, 255 - 12 - 1); + strncat(buffer, "'", 1); + charinfo = makebcpl(header + 18, buffer, 255); + lh = charinfo - header; + + width = charinfo + (ec - bc + 1); + width[0] = 0; + nw = 1; + + for (i = bc; i <= ec; i++) + if (NULL != (ti = fnt->inencptrs[i])) + { + width[nw] = ti->width; + for (j = 1; width[j] != ti->width; j++) + ; + ti->wptr = j; + if (j == nw) + nw++; + } + if (nw > 256) + oops("256 chars with different widths."); + + depth = width + nw; + depth[0] = 0; + nd = 1; + + for (i = bc; i <= ec; i++) + if (NULL != (ti = fnt->inencptrs[i])) + { + depth[nd] = -ti->lly; + for (j = 0; depth[j] != -ti->lly; j++) + ; + ti->dptr = j; + if (j == nd) + nd++; + } + + if (nd > 16) + { + remap(depth, nd, 16, source, unsort); + nd = 16; + for (i = bc; i <= ec; i++) + if (NULL != (ti = fnt->inencptrs[i])) + ti->dptr = unsort[ti->dptr]; + } + + height = depth + nd; + height[0] = 0; + nh = 1; + + for (i = bc; i <= ec; i++) + if (NULL != (ti = fnt->inencptrs[i])) + { + height[nh] = ti->ury; + for (j = 0; height[j] != ti->ury; j++) + ; + ti->hptr = j; + if (j == nh) + nh++; + } + + if (nh > 16) + { + remap(height, nh, 16, source, unsort); + nh = 16; + for (i = bc; i <= ec; i++) + if (NULL != (ti = fnt->inencptrs[i])) + ti->hptr = unsort[ti->hptr]; + } + + italic = height + nh; + italic[0] = 0; + ni = 1; + + for (i = bc; i <= ec; i++) + if (NULL != (ti = fnt->inencptrs[i])) + { + italic[ni] = ti->urx - ti->width; + if (italic[ni] < 0) + italic[ni] = 0; + for (j = 0; italic[j] != italic[ni]; j++) + ; + ti->iptr = j; + if (j == ni) + ni++; + } + + if (ni > 64) + { + remap(italic, ni, 64, source, unsort); + ni = 64; + for (i = bc; i <= ec; i++) + if (NULL != (ti = fnt->inencptrs[i])) + ti->iptr = unsort[ti->iptr]; + } + + for (i = bc; i <= ec; i++) + if (NULL != (ti = fnt->inencptrs[i])) + charinfo[i - bc] = ((long)(ti->wptr) << 24) + + ((long)(ti->hptr) << 20) + + ((long)(ti->dptr) << 16) + + ((long)(ti->iptr) << 10); + else + charinfo[i - bc] = 0; + + ligkern = italic + ni; + nl = 0; + + if (fnt->subfont_ligs) + { + /* Now we build the ligature list. The ligature consisting of character + code byte1 + byte2 should yield the actual character. The fonts of + the HLaTeX package for Korean use this mechanism. */ + + old_byte1 = -1; + while (nl < 256 && sf_array[nl].sf_code > -1) + { + byte1 = sf_array[nl].sf_code >> 8; + byte2 = sf_array[nl].sf_code & 0xFF; + if (byte1 != old_byte1) + { + charinfo[byte1 - bc] += 0x100L + /* set the lig tag */ + nl; /* set the position in array */ + if (old_byte1 > -1) + ligkern[nl - 1] |= 0x80000000L; /* set the STOP byte in previous + ligkern command */ + } + + ligkern[nl] = ((long)byte2 << 16) + + (long)sf_array[nl].position; + old_byte1 = byte1; + nl++; + } + if (nl > 0) + ligkern[nl - 1] |= 0x80000000L; + } + + kerns = ligkern + nl; + nk = 0; /* kerns are omitted from raw TeX font */ + + Slant = fnt->slant - fnt->efactor * tan(fnt->italicangle * (PI / 180.0)); + + tparam = kerns + nk; + tparam[0] = (long)(FIXFACTOR * Slant + 0.5); + tparam[1] = scale((long)fnt->fontspace); + tparam[2] = (fnt->fixedpitch ? 0 : scale((long)(300 * fnt->efactor + 0.5))); + tparam[3] = (fnt->fixedpitch ? 0 : scale((long)(100 * fnt->efactor + 0.5))); + tparam[4] = scale((long)fnt->xheight); + tparam[5] = scale((long)(1000 * fnt->efactor + 0.5)); + np = 6; + + return 1; +} + + +void +writetfm(Font *fnt) +{ + FILE *out; + char *tfm_name; + int len = 0; + + + if (fnt->tfm_path) + len += strlen(fnt->tfm_path); + len += strlen(fnt->fullname); + len += strlen(fnt->tfm_ext); + len++; + + tfm_name = (char *)mymalloc(len); + tfm_name[0] = '\0'; + if (fnt->tfm_path) + strcat(tfm_name, fnt->tfm_path); + strcat(tfm_name, fnt->fullname); + strcat(tfm_name, fnt->tfm_ext); + + if ((out = fopen(tfm_name, "wb")) == NULL) + oops("Cannot open tfm file `%s'.", tfm_name); + + free(tfm_name); + + + lf = 6 + lh + (ec - bc + 1) + nw + nh + nd + ni + nl + nk + ne + np; + + write16(lf, out); + write16(lh, out); + write16(bc, out); + write16(ec, out); + write16(nw, out); + write16(nh, out); + write16(nd, out); + write16(ni, out); + write16(nl, out); + write16(nk, out); + write16(ne, out); + write16(np, out); + writearr(header, lh, out); + writearr(charinfo, ec - bc + 1, out); + writesarr(width, nw, out); + writesarr(height, nh, out); + writesarr(depth, nd, out); + writesarr(italic, ni, out); + writearr(ligkern, nl, out); + writesarr(kerns, nk, out); + writearr(tparam, np, out); + + free(header); + fclose(out); +} + + +void +writeenc(Font *fnt) +{ + FILE *out; + char *enc_name; + int i, len = 0; + + + if (fnt->tfm_path) + len += strlen(fnt->tfm_path); + len += strlen(fnt->fullname); + len += 5; /* ".enc" + 1 */ + + enc_name = (char *)mymalloc(len); + enc_name[0] = '\0'; + if (fnt->tfm_path) + strcat(enc_name, fnt->tfm_path); + strcat(enc_name, fnt->fullname); + strcat(enc_name, ".enc"); + + if ((out = fopen(enc_name, "wb")) == NULL) + oops("Cannot open enc file `%s'.", enc_name); + + free(enc_name); + + fprintf(out, "/%sEncoding [", fnt->fullname); + for (i = 0; i < 256; i++) + { + if (i % 4 == 0) + fputc('\n', out); + if (fnt->inencptrs[i] == NULL) + fputs("/.notdef ", out); + else if (strcmp(fnt->inencptrs[i]->adobename, ".notdef") == 0 || + strcmp(fnt->inencptrs[i]->adobename, ".null") == 0 || + strcmp(fnt->inencptrs[i]->adobename, ".nonmarkingreturn") == 0 || + strcmp(fnt->inencptrs[i]->adobename, ".dummy") == 0) + fputs("/.notdef ", out); + else + fprintf(out, "/index0x%04X ", fnt->inencptrs[i]->glyphindex); + } + fputs("\n] def\n", out); + + fclose(out); +} + + +/* end */ |