From 2ba98f9a00f1b34455b12ef44c361154b48000c6 Mon Sep 17 00:00:00 2001 From: Peter Breitenlohner Date: Mon, 2 May 2011 13:18:14 +0000 Subject: Add texk/ttf2pk2 (ttf2pk-frretype2), at the moment not built by default git-svn-id: svn://tug.org/texlive/trunk@22282 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/texk/ttf2pk2/pklib.c | 872 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 872 insertions(+) create mode 100644 Build/source/texk/ttf2pk2/pklib.c (limited to 'Build/source/texk/ttf2pk2/pklib.c') diff --git a/Build/source/texk/ttf2pk2/pklib.c b/Build/source/texk/ttf2pk2/pklib.c new file mode 100644 index 00000000000..5b5b380c277 --- /dev/null +++ b/Build/source/texk/ttf2pk2/pklib.c @@ -0,0 +1,872 @@ +/* + * pklib.c + * + * This file is part of the ttf2pk package. + * + * Copyright 1997-1999, 2000 by + * Frederic Loyer + * Werner Lemberg + */ + +/* + * This code has been derived from the program gsftopk. + * Here the original copyright. + */ + +/* + * Copyright (c) 1994 Paul Vojta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include /* for size_t */ +#include +#include +#include + +#include "newobj.h" +#include "pklib.h" +#include "errormsg.h" +#include "filesrch.h" + +#ifndef MAXPATHLEN +#define MAXPATHLEN 256 +#endif + +#define PK_PRE (char)247 +#define PK_ID 89 +#define PK_POST (char)245 +#define PK_NOP (char)246 + +int dpi; + +FILE *pk_file; + + +/* + * Information from the .tfm file. + */ + +int tfm_lengths[12]; + +#define lh tfm_lengths[1] +#define bc tfm_lengths[2] +#define ec tfm_lengths[3] +#define nw tfm_lengths[4] + +long checksum; +long design; +byte width_index[256]; +long tfm_widths[256]; + +/* + * Information on the bitmap currently being worked on. + */ + +byte *bitmap; +int width; +int skip; +int height; +int hoff; +int voff; +int bytes_wide; +size_t bm_size; +byte *bitmap_end; +int pk_len; + +/* + * Here's the path searching stuff. First the typedefs and variables. + */ + +static char searchpath[MAXPATHLEN + 1]; + +#define HUNKSIZE (MAXPATHLEN + 2) + +struct spacenode /* used for storage of directory names */ +{ + struct spacenode *next; + char *sp_end; /* end of data for this chunk */ + char sp[HUNKSIZE]; +} firstnode; + + + +static FILE * +search_tfm(char **name) +{ + char *p; + FILE *f; + + + p = TeX_search_tfm(name); + if (p == NULL) + return NULL; + strcpy(searchpath, p); + f = fopen(searchpath, "rb"); + return f; +} + + +static long +getlong(FILE *f) +{ + unsigned long value; + + + value = (unsigned long)getc(f) << 24; + value |= (unsigned long)getc(f) << 16; + value |= (unsigned long)getc(f) << 8; + value |= (unsigned long)getc(f); + return value; +} + + +char line[82]; + + +static byte masks[] = {0, 1, 3, 7, 017, 037, 077, 0177, 0377}; + +byte flag; +int pk_dyn_f; +int pk_dyn_g; +int base; /* cost of this character if pk_dyn_f = 0 */ +int deltas[13]; /* cost of increasing pk_dyn_f from i to i+1 */ + + +/* + * Add up statistics for putting out the given shift count. + */ + +static void +tallyup(int n) +{ + int m; + + + if (n > 208) + { + ++base; + n -= 192; + for (m = 0x100; m != 0 && m < n; m <<= 4) + base += 2; + if (m != 0 && (m = (m - n) / 15) < 13) + deltas[m] += 2; + } + else if (n > 13) + ++deltas[(208 - n) / 15]; + else + --deltas[n - 1]; +} + + +/* + * Routines for storing the shift counts. + */ + +static Boolean odd = False; +static byte part; + + +static void +pk_put_nyb(int n) +{ + if (odd) + { + *bitmap_end++ = (part << 4) | n; + odd = False; + } + else + { + part = n; + odd = True; + } +} + + +static void +pk_put_long(int n) +{ + if (n >= 16) + { + pk_put_nyb(0); + pk_put_long(n / 16); + } + pk_put_nyb(n % 16); +} + + +static void +pk_put_count(int n) +{ + if (n > pk_dyn_f) + { + if (n > pk_dyn_g) + pk_put_long(n - pk_dyn_g + 15); + else + { + pk_put_nyb(pk_dyn_f + (n - pk_dyn_f + 15) / 16); + pk_put_nyb((n - pk_dyn_f - 1) % 16); + } + } + else + pk_put_nyb(n); +} + + +static void +trim_bitmap(void) +{ + byte *p; + byte mask; + + + /* clear out garbage bits in bitmap */ + + if (width % 8 != 0) + { + mask = ~masks[8 - width % 8]; + for (p = bitmap + bytes_wide - 1; p < bitmap_end; p += bytes_wide) + *p &= mask; + } + + /* Find the bounding box of the bitmap. */ + + /* trim top */ + + skip = 0; + mask = 0; + + for (;;) + { + if (bitmap >= bitmap_end) /* if bitmap is empty */ + { + width = height = hoff = voff = 0; + return; + } + + p = bitmap + bytes_wide; + while (p > bitmap) + mask |= *--p; + if (mask) + break; + ++skip; + bitmap += bytes_wide; + } + + height -= skip; + voff -= skip; + +#ifdef DEBUG + if (skip < 2 || skip > 3) + printf("Character has %d empty rows at top\n", skip); +#endif + + /* trim bottom */ + + skip = 0; + mask = 0; + + for (;;) + { + p = bitmap_end - bytes_wide; + while (p < bitmap_end) + mask |= *p++; + if (mask) + break; + ++skip; + bitmap_end -= bytes_wide; + } + + height -= skip; + +#ifdef DEBUG + if (skip < 2 || skip > 3) + printf("Character has %d empty rows at bottom\n", skip); +#endif + + /* trim right */ + + skip = 0; + --width; + + for (;;) + { + mask = 0; + for (p = bitmap + width / 8; p < bitmap_end; p += bytes_wide) + mask |= *p; + if (mask & (0x80 >> (width % 8))) + break; + + --width; + ++skip; + } + + ++width; + +#ifdef DEBUG + if (skip < 2 || skip > 3) + printf("Character has %d empty columns at right\n", skip); +#endif + + /* trim left */ + + skip = 0; + + for (;;) + { + mask = 0; + for (p = bitmap + skip / 8; p < bitmap_end; p += bytes_wide) + mask |= *p; + if (mask & (0x80 >> (skip % 8))) + break; + + ++skip; + } + + width -= skip; + hoff -= skip; + +#ifdef DEBUG + if (skip < 2 || skip > 3) + printf("Character has %d empty columns at left\n", skip); +#endif + + bitmap += skip / 8; + skip = skip % 8; +} + + +/* + * Pack the bitmap using the rll method. (Return false if it's better + * to just pack the bits.) + */ + +static Boolean +pk_rll_cvt(void) +{ + static int *counts = NULL; /* area for saving bit counts */ + static int maxcounts = 0; /* size of this area */ + unsigned int ncounts; /* max to allow this time */ + int *nextcount; /* next count value */ + + int *counts_end; /* pointer to end */ + byte *rowptr; + byte *p; + byte mask; + byte *rowdup; /* last row checked for dup */ + byte paint_switch; /* 0 or 0xff */ + int bits_left; /* bits left in row */ + int cost; + int i; + + + /* Allocate space for bit counts. */ + + ncounts = (width * height + 3) / 4; + if (ncounts > maxcounts) + { + if (counts != NULL) + free(counts); + counts = (int *)mymalloc((ncounts + 2) * sizeof (int)); + maxcounts = ncounts; + } + counts_end = counts + ncounts; + + /* Form bit counts and collect statistics */ + + base = 0; + memset(deltas, 0, sizeof (deltas)); + rowdup = NULL; /* last row checked for duplicates */ + p = rowptr = bitmap; + mask = 0x80 >> skip; + flag = 0; + paint_switch = 0; + + if (*p & mask) + { + flag = 8; + paint_switch = 0xff; + } + + bits_left = width; + nextcount = counts; + + while (rowptr < bitmap_end) /* loop over shift counts */ + { + int shift_count = bits_left; + + + for (;;) + { + if (bits_left == 0) + { + if ((p = rowptr += bytes_wide) >= bitmap_end) + break; + mask = 0x80 >> skip; + bits_left = width; + shift_count += width; + } + if (((*p ^ paint_switch) & mask) != 0) + break; + --bits_left; + mask >>= 1; + if (mask == 0) + { + ++p; + while (*p == paint_switch && bits_left >= 8) + { + ++p; + bits_left -= 8; + } + mask = 0x80; + } + } + + if (nextcount >= counts_end) + return False; + shift_count -= bits_left; + *nextcount++ = shift_count; + tallyup(shift_count); + + /* check for duplicate rows */ + if (rowptr != rowdup && bits_left != width) + { + byte *p1 = rowptr; + byte *q = rowptr + bytes_wide; + int repeat_count; + + + while (q < bitmap_end && *p1 == *q) + { + ++p1; + ++q; + } + repeat_count = (p1 - rowptr) / bytes_wide; + if (repeat_count > 0) + { + *nextcount++ = -repeat_count; + if (repeat_count == 1) + --base; + else + { + ++base; + tallyup(repeat_count); + } + rowptr += repeat_count * bytes_wide; + } + rowdup = rowptr; + } + paint_switch = ~paint_switch; + } + +#ifdef DEBUG + /* + * Dump the bitmap + */ + + for (p = bitmap; p < bitmap_end; p += bytes_wide) + { + byte *p1 = p; + int j; + + + mask = 0x80 >> skip; + for (j = 0; j < width; ++j) + { + putchar(*p1 & mask ? '@' : '.'); + if ((mask >>= 1) == 0) + { + mask = 0x80; + ++p1; + } + } + putchar('\n'); + } + putchar('\n'); +#endif + + /* Determine the best pk_dyn_f */ + + pk_dyn_f = 0; + cost = base += 2 * (nextcount - counts); + + for (i = 1; i < 14; ++i) + { + base += deltas[i - 1]; + if (base < cost) + { + pk_dyn_f = i; + cost = base; + } + } + + /* last chance to bail out */ + + if (cost * 4 > width * height) + return False; + + /* Pack the bit counts */ + + pk_dyn_g = 208 - 15 * pk_dyn_f; + flag |= pk_dyn_f << 4; + bitmap_end = bitmap; + *nextcount = 0; + nextcount = counts; + + while (*nextcount != 0) + { + if (*nextcount > 0) + pk_put_count(*nextcount); + else + if (*nextcount == -1) + pk_put_nyb(15); + else + { + pk_put_nyb(14); + pk_put_count(-*nextcount); + } + ++nextcount; + } + + if (odd) + { + pk_put_nyb(0); + ++cost; + } + + if (cost != 2 * (bitmap_end - bitmap)) + printf("Cost miscalculation: expected %d, got %ld\n", + cost, (long)(2 * (bitmap_end - bitmap))); + pk_len = bitmap_end - bitmap; + return True; +} + + +static void +pk_bm_cvt(void) +{ + byte *rowptr; + byte *p; + int blib1; /* bits left in byte */ + int bits_left; /* bits left in row */ + byte *q; + int blib2; + byte nextbyte; + + + flag = 14 << 4; + q = bitmap; + blib2 = 8; + nextbyte = 0; + + for (rowptr = bitmap; rowptr < bitmap_end; rowptr += bytes_wide) + { + p = rowptr; + blib1 = 8 - skip; + bits_left = width; + + if (blib2 != 8) + { + int n; + + + if (blib1 < blib2) + { + nextbyte |= *p << (blib2 - blib1); + n = blib1; + } + else + { + nextbyte |= *p >> (blib1 - blib2); + n = blib2; + } + blib2 -= n; + if ((bits_left -= n) < 0) + { + blib2 -= bits_left; + continue; + } + if ((blib1 -= n) == 0) + { + blib1 = 8; + ++p; + if (blib2 > 0) + { + nextbyte |= *p >> (8 - blib2); + blib1 -= blib2; + bits_left -= blib2; + if (bits_left < 0) + { + blib2 = -bits_left; + continue; + } + } + } + *q++ = nextbyte; + } + + /* fill up whole (destination) bytes */ + + while (bits_left >= 8) + { + nextbyte = *p++ << (8 - blib1); + *q++ = nextbyte | (*p >> blib1); + bits_left -= 8; + } + + /* now do the remainder */ + + nextbyte = *p << (8 - blib1); + if (bits_left > blib1) + nextbyte |= p[1] >> blib1; + blib2 = 8 - bits_left; + } + + if (blib2 != 8) + *q++ = nextbyte; + + pk_len = q - bitmap; +} + + +static void +putshort(short w) +{ + putc(w >> 8, pk_file); + putc(w, pk_file); +} + + +static void +putmed(long w) +{ + putc(w >> 16, pk_file); + putc(w >> 8, pk_file); + putc(w, pk_file); +} + + +static void +putlong(long w) +{ + putc(w >> 24, pk_file); + putc(w >> 16, pk_file); + putc(w >> 8, pk_file); + putc(w, pk_file); +} + + +static char +xgetc(FILE *f) +{ + int c; + + + c = getc(f); + if (c == EOF) + oops("Premature end of file."); + return (byte)c; +} + + +/* + * Open and read the tfm file. + */ + +void +TFMopen(char **filename) +{ + FILE *tfm_file; + int i; + int cc; + + + tfm_file = search_tfm(filename); + if (tfm_file == NULL) + oops("Cannot find tfm file."); + + for (i = 0; i < 12; i++) + { + int j; + + + j = (int)((byte)getc(tfm_file)) << 8; + tfm_lengths[i] = j | (int)((byte)xgetc(tfm_file)); + } + + checksum = getlong(tfm_file); + design = getlong(tfm_file); + fseek(tfm_file, 4 * (lh + 6), 0); + + for (cc = bc; cc <= ec; ++cc) + { + width_index[cc] = (byte)xgetc(tfm_file); + + (void)xgetc(tfm_file); + (void)xgetc(tfm_file); + (void)xgetc(tfm_file); + } + + for (i = 0; i < nw; ++i) + tfm_widths[i] = getlong(tfm_file); + + fclose(tfm_file); +} + + +/* + * Create pk file and write preamble. + */ + +void +PKopen(char *filename, + char *ident, + int resolution) +{ + int ppp; + int i; + + + dpi = resolution; + + if ((pk_file = fopen(filename, "wb")) == NULL) + { + perror(filename); + exit(1); + } + + putc(PK_PRE, pk_file); + putc(PK_ID, pk_file); + + i = strlen(ident); + + putc(i, pk_file); + fwrite(ident, 1, i, pk_file); + putlong(design); + putlong(checksum); + ppp = dpi / 72.27 * 65536.0 + 0.5; + putlong(ppp); /* hppp */ + putlong(ppp); /* vppp */ +} + + +void +PKputglyph(int cc, + int llx, int lly, int urx, int ury, + int w, int h, + byte *b) +{ + float char_width; + + long dm; + long tfm_wid; + + + bitmap = b; + width = w; + height = h; + + hoff = -llx; + voff = ury - 2; /* Don't ask me why `-2' */ + /* Fred */ + + if (width != urx - llx || height != ury - lly) + oops("Dimensions do not match: (%d - %d) (%d - %d) <=> %d %d", + llx, lly, urx, ury, width, height); + + bytes_wide = (width + 7) / 8; + bm_size = bytes_wide * height; + bitmap_end = bitmap + bm_size; + + trim_bitmap(); + + if (height == 0 || !pk_rll_cvt()) + pk_bm_cvt(); + + if (!width_index[cc]) + return; + + tfm_wid = tfm_widths[width_index[cc]]; + char_width = tfm_wid / 1048576.0 * design / 1048576.0 * dpi / 72.27; + dm = (long)(char_width + 0.5) - (char_width < -0.5); + + if (pk_len + 8 < 4 * 256 && tfm_wid < (1<<24) && + dm >= 0 && dm < 256 && width < 256 && height < 256 && + hoff >= -128 && hoff < 128 && voff >= -128 && voff < 128) + { + putc(flag | ((pk_len + 8) >> 8), pk_file); + putc(pk_len + 8, pk_file); + putc(cc, pk_file); + putmed(tfm_wid); + putc(dm, pk_file); + putc(width, pk_file); + putc(height, pk_file); + putc(hoff, pk_file); + putc(voff, pk_file); + } + else if (pk_len + 13 < 3 * 65536L && tfm_wid < (1<<24) && + dm >= 0 && dm < 65536L && width < 65536L && height < 65536L && + hoff >= -65536L && hoff < 65536L && + voff >= -65536L && voff < 65536L) + { + putc(flag | 4 | ((pk_len + 13) >> 16), pk_file); + putshort(pk_len + 13); + putc(cc, pk_file); + putmed(tfm_wid); + putshort(dm); + putshort(width); + putshort(height); + putshort(hoff); + putshort(voff); + } + else + { + putc(flag | 7, pk_file); + putlong(pk_len + 28); + putlong(cc); + putlong(tfm_wid); + putlong((long)(char_width * 65536.0 + 0.5) - (char_width < -0.5)); + putlong(0); + putlong(width); + putlong(height); + putlong(hoff); + putlong(voff); + } + fwrite(bitmap, 1, pk_len, pk_file); +} + + +void +PKclose(void) +{ + putc(PK_POST, pk_file); + while (ftell(pk_file) % 4 != 0) + putc(PK_NOP, pk_file); + + fclose(pk_file); +} + + +/* end */ -- cgit v1.2.3