[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Devel] Re: Supported Compression Algorithms.
From: |
Albert Chin |
Subject: |
Re: [Devel] Re: Supported Compression Algorithms. |
Date: |
Sun, 29 Feb 2004 10:38:29 -0600 |
User-agent: |
Mutt/1.4i |
On Sat, Feb 28, 2004 at 12:06:52PM -0600, Albert Chin wrote:
> On Fri, Feb 27, 2004 at 09:59:17PM -0500, James H. Cloos Jr. wrote:
> > >>>>> "Keith" == Keith Packard <address@hidden> writes:
> >
> > Keith> so I'm not really excited about switching
> > Keith> back. What a mess. Setuid programs suck.
> >
> > If it is any better, gzip(1) (unlike zlib) does include code to
> > decompress lzw. From gzip-1.3.3/unlzw.c:
> >
> > /* unlzw.c -- decompress files in LZW format.
> > * The code in this file is directly derived from the public domain
> > 'compress'
> > * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve
> > Davies,
> > * Ken Turkowski, Dave Mack and Peter Jannesen.
> >
> > so there should be some public domain code out there (I bet it was
> > posted to either comp.sources.unix or comp.sources.misc at some point)
> > that can be used in freetype....
>
> I initially emailed Jean-loup Gailly, the individual with the RCS id
> on that file, but didn't hear anything back. Anyway, I've integrated
> the NetBSD code and it's mostly working except for some bugs :(
Ok, patch to add reading .pcf.Z files below. The patch is against
2.1.4.
--
albert chin (address@hidden)
-- snip snip
--- /dev/null 2004-02-28 17:48:53.000000000 -0600
+++ include/freetype/ftlzw.h 2004-02-28 17:57:13.159442000 -0600
@@ -0,0 +1,83 @@
+/***************************************************************************/
+/* */
+/* ftgzip.h */
+/* */
+/* Gzip-compressed stream support. */
+/* */
+/* Copyright 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __FTLZW_H__
+#define __FTLZW_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+FT_BEGIN_HEADER
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* gzip */
+ /* */
+ /* <Title> */
+ /* LZW Streams */
+ /* */
+ /* <Abstract> */
+ /* Using gzip-compressed font files */
+ /* */
+ /* <Description> */
+ /* This section contains the declaration of Gzip-specific functions. */
+ /* */
+ /*************************************************************************/
+
+ /************************************************************************
+ *
+ * @type: FT_Stream_OpenLZW
+ *
+ * @description:
+ * open a new stream to parse lzw-compressed font files. This is
+ * mainly used to support the compressed *.pcf.Z fonts that come
+ * with XFree86
+ *
+ * @input:
+ * stream :: target embedding stream
+ * source :: source stream, used to
+ *
+ * @return:
+ * error code. 0 means success
+ *
+ * @note:
+ * the source stream must be opened _before_ calling this function.
+ *
+ * calling @FT_Stream_Close on the new stream will *not* call
+ * @FT_Stream_Close on the source stream. None of the stream objects
+ * will be released to the heap.
+ *
+ * the stream implementation is very basic, and resets the decompression
+ * process each time seeking backwards is needed within the stream
+ *
+ * in certain builds of the library, gzip compression recognition is
+ * automatic when calling @FT_New_Face or @FT_Open_Face. This means that
+ * if no font driver is capable of handling the raw compressed file,
+ * the library will try to open a gzip stream from it and re-open
+ * the face with it.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stream_OpenLZW( FT_Stream stream,
+ FT_Stream source );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTLZW_H__ */
--- /dev/null 2004-02-29 10:29:44.000000000 -0600
+++ src/lzw/rules.mk 2004-02-28 17:53:17.665255000 -0600
@@ -0,0 +1,69 @@
+#
+# FreeType 2 LZW support configuration rules
+#
+
+
+# Copyright 2004 by
+# Albert Chin-A-Young.
+#
+# Based on src/lzw/rules.mk, Copyright 2002 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# lzw driver directory
+#
+LZW_DIR := $(SRC_)lzw
+LZW_DIR_ := $(LZW_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+LZW_COMPILE := $(FT_COMPILE) $I$(LZW_DIR)
+
+
+# lzw support sources (i.e., C files)
+#
+LZW_DRV_SRC := $(LZW_DIR_)ftlzw.c $(LZW_DIR_)zopen.c
+
+# lzw support headers
+#
+LZW_DRV_H :=
+
+
+# lzw driver object(s)
+#
+# LZW_DRV_OBJ_M is used during `multi' builds
+# LZW_DRV_OBJ_S is used during `single' builds
+#
+LZW_DRV_OBJ_M := $(OBJ_)ftlzw.$O
+LZW_DRV_OBJ_S := $(OBJ_)ftlzw.$O
+
+# lzw support source file for single build
+#
+LZW_DRV_SRC_S := $(LZW_DIR_)ftlzw.c
+
+
+# lzw support - single object
+#
+$(LZW_DRV_OBJ_S): $(LZW_DRV_SRC_S) $(LZW_DRV_SRC) $(FREETYPE_H) $(LZW_DRV_H)
+ $(LZW_COMPILE) $T$@ $(LZW_DRV_SRC_S)
+
+
+# lzw support - multiple objects
+#
+$(OBJ_)%.$O: $(LZW_DIR_)%.c $(FREETYPE_H) $(LZW_DRV_H)
+ $(LZW_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(LZW_DRV_OBJ_S)
+DRV_OBJS_M += $(LZW_DRV_OBJ_M)
+
+# EOF
--- /dev/null 2004-02-29 10:29:44.000000000 -0600
+++ src/lzw/zopen.c 2004-02-29 10:30:23.494189000 -0600
@@ -0,0 +1,395 @@
+/* $NetBSD: zopen.c,v 1.8 2003/08/07 11:13:29 agc Exp $ */
+
+/*-
+ * Copyright (c) 1985, 1986, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Diomidis Spinellis and James A. Woods, derived from original
+ * work by Spencer Thomas and Joseph Orost.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*-
+ *
+ * Copyright (c) 2004
+ * Albert Chin-A-Young.
+ *
+ * Modified to work with FreeType's PCF driver.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)zopen.c 8.1 (Berkeley) 6/27/93";
+#else
+static char rcsid[] = "$NetBSD: zopen.c,v 1.8 2003/08/07 11:13:29 agc Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*-
+ * fcompress.c - File compression ala IEEE Computer, June 1984.
+ *
+ * Compress authors:
+ * Spencer W. Thomas (decvax!utah-cs!thomas)
+ * Jim McKie (decvax!mcvax!jim)
+ * Steve Davies (decvax!vax135!petsd!peora!srd)
+ * Ken Turkowski (decvax!decwrl!turtlevax!ken)
+ * James A. Woods (decvax!ihnp4!ames!jaw)
+ * Joe Orost (decvax!vax135!petsd!joe)
+ *
+ * Cleaned up and converted to library returning I/O streams by
+ * Diomidis Spinellis <address@hidden>.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static char_type magic_header[] =
+ { 0x1f, 0x9d }; /* 1F 9D */
+
+#define BIT_MASK 0x1f /* Defines for third byte of
header. */
+#define BLOCK_MASK 0x80
+
+/*
+ * Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
+ * a fourth header byte (for expansion).
+ */
+#define INIT_BITS 9 /* Initial number of bits/code.
*/
+
+#define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
+
+/* Definitions to retain old variable names */
+#define fp zs->zs_fp
+#define state zs->zs_state
+#define n_bits zs->zs_n_bits
+#define maxbits zs->zs_maxbits
+#define maxcode zs->zs_maxcode
+#define maxmaxcode zs->zs_maxmaxcode
+#define htab zs->zs_htab
+#define codetab zs->zs_codetab
+#define hsize zs->zs_hsize
+#define free_ent zs->zs_free_ent
+#define block_compress zs->zs_block_compress
+#define clear_flg zs->zs_clear_flg
+#define offset zs->zs_offset
+#define in_count zs->zs_in_count
+#define buf_len zs->zs_buf_len
+#define buf zs->zs_buf
+#define stackp zs->u.r.zs_stackp
+#define finchar zs->u.r.zs_finchar
+#define code zs->u.r.zs_code
+#define oldcode zs->u.r.zs_oldcode
+#define incode zs->u.r.zs_incode
+#define roffset zs->u.r.zs_roffset
+#define size zs->u.r.zs_size
+#define gbuf zs->u.r.zs_gbuf
+
+/*
+ * To save much memory, we overlay the table used by compress() with those
+ * used by decompress(). The tab_prefix table is the same size and type as
+ * the codetab. The tab_suffix table needs 2**BITS characters. We get this
+ * from the beginning of htab. The output stack uses the rest of htab, and
+ * contains characters. There is plenty of room for any possible stack
+ * (stack used to be 8000 characters).
+ */
+
+#define htabof(i) htab[i]
+#define codetabof(i) codetab[i]
+
+#define tab_prefixof(i) codetabof(i)
+#define tab_suffixof(i) ((char_type *)(htab))[i]
+#define de_stack ((char_type *)&tab_suffixof(1 << BITS))
+
+#define CHECK_GAP 10000 /* Ratio check interval. */
+
+/*
+ * the next two codes should not be changed lightly, as they must not
+ * lie within the contiguous general code space.
+ */
+#define FIRST 257 /* First free entry. */
+#define CLEAR 256 /* Table clear output code. */
+
+/*-
+ * Algorithm from "A Technique for High Performance Data Compression",
+ * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
+ *
+ * Algorithm:
+ * Modified Lempel-Ziv method (LZW). Basically finds common
+ * substrings and replaces them with a variable size code. This is
+ * deterministic, and can be done on the fly. Thus, the decompression
+ * procedure needs no input table, but tracks the way the table was built.
+ */
+
+static int
+zclose(s_zstate_t *zs)
+{
+ free(zs);
+ return (0);
+}
+
+/*-
+ * Output the given code.
+ * Inputs:
+ * code: A n_bits-bit integer. If == -1, then EOF. This assumes
+ * that n_bits =< (long)wordsize - 1.
+ * Outputs:
+ * Outputs code to the file.
+ * Assumptions:
+ * Chars are 8 bits long.
+ * Algorithm:
+ * Maintain a BITS character long buffer (so that 8 codes will
+ * fit in it exactly). Use the VAX insv instruction to insert each
+ * code in turn. When the buffer fills up empty it and start over.
+ */
+
+static char_type rmask[9] =
+ {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+
+/*
+ * Decompress read. This routine adapts to the codes in the file building
+ * the "string" table on-the-fly; requiring no table to be stored in the
+ * compressed file. The tables used herein are shared with those of the
+ * compress() routine. See the definitions above.
+ */
+static int
+zread(s_zstate_t *zs)
+{
+ unsigned int count;
+ unsigned char *bp;
+
+ if (in_count == 0)
+ return -1;
+ if (zs->avail_out == 0)
+ return 0;
+
+ count = zs->avail_out;
+ switch (state) {
+ case S_START:
+ state = S_MIDDLE;
+ break;
+ case S_MIDDLE:
+ goto middle;
+ case S_EOF:
+ goto eof;
+ }
+
+ maxbits = *(zs->next_in); /* Set -b from file. */
+ zs->avail_in--;
+ zs->next_in++;
+ zs->total_in++;
+ in_count--;
+ block_compress = maxbits & BLOCK_MASK;
+ maxbits &= BIT_MASK;
+ maxmaxcode = 1L << maxbits;
+ if (maxbits > BITS) {
+ return -1;
+ }
+ /* As above, initialize the first 256 entries in the table. */
+ maxcode = MAXCODE(n_bits = INIT_BITS);
+ for (code = 255; code >= 0; code--) {
+ tab_prefixof(code) = 0;
+ tab_suffixof(code) = (char_type) code;
+ }
+ free_ent = block_compress ? FIRST : 256;
+
+ finchar = oldcode = getcode(zs);
+ if (oldcode == -1) /* EOF already? */
+ return 0; /* Get out of here */
+
+ /* First code must be 8 bits = char. */
+ *(zs->next_out)++ = (unsigned char)finchar;
+ zs->total_out++;
+ count--;
+ stackp = de_stack;
+
+ while ((code = getcode(zs)) > -1) {
+ if ((code == CLEAR) && block_compress) {
+ for (code = 255; code >= 0; code--)
+ tab_prefixof(code) = 0;
+ clear_flg = 1;
+ free_ent = FIRST - 1;
+ if ((code = getcode(zs)) == -1)
+ /* O, untimely death! */
+ break;
+ }
+ incode = code;
+
+ /* Special case for KwKwK string. */
+ if (code >= free_ent) {
+ *stackp++ = finchar;
+ code = oldcode;
+ }
+
+ /* Generate output characters in reverse order. */
+ while (code >= 256) {
+ *stackp++ = tab_suffixof(code);
+ code = tab_prefixof(code);
+ }
+ *stackp++ = finchar = tab_suffixof(code);
+
+ /* And put them out in forward order. */
+middle:
+ if (stackp == de_stack)
+ continue;
+
+ do {
+ if (count-- == 0) {
+ return zs->avail_out;
+ }
+ *(zs->next_out)++ = *--stackp;
+ zs->total_out++;
+ } while (stackp > de_stack);
+
+ /* Generate the new entry. */
+ if ((code = free_ent) < maxmaxcode) {
+ tab_prefixof(code) = (unsigned short) oldcode;
+ tab_suffixof(code) = finchar;
+ free_ent = code + 1;
+ }
+
+ /* Remember previous code. */
+ oldcode = incode;
+ }
+ /* state = S_EOF; */
+eof: return (zs->avail_out - count);
+}
+
+/*-
+ * Read one code from the standard input. If EOF, return -1.
+ * Inputs:
+ * stdin
+ * Outputs:
+ * code or -1 is returned.
+ */
+static code_int
+getcode(s_zstate_t *zs)
+{
+ code_int gcode;
+ int r_off, bits;
+ char_type *bp;
+
+ bp = gbuf;
+ if (clear_flg > 0 || roffset >= size || free_ent > maxcode) {
+ /*
+ * If the next entry will be too big for the current gcode
+ * size, then we must increase the size. This implies reading
+ * a new buffer full, too.
+ */
+ if (free_ent > maxcode) {
+ n_bits++;
+ if (n_bits == maxbits) /* Won't get any bigger now. */
+ maxcode = maxmaxcode;
+ else
+ maxcode = MAXCODE(n_bits);
+ }
+ if (clear_flg > 0) {
+ maxcode = MAXCODE(n_bits = INIT_BITS);
+ clear_flg = 0;
+ }
+ if ( zs->avail_in < n_bits && in_count > n_bits ) {
+ memcpy (buf, zs->next_in, zs->avail_in);
+ buf_len = zs->avail_in;
+ zs->avail_in = 0;
+ return -1;
+ }
+ if (buf_len) {
+ memcpy (gbuf, buf, buf_len);
+ memcpy (gbuf + buf_len, zs->next_in,
+ n_bits - buf_len);
+ zs->next_in += n_bits - buf_len;
+ zs->avail_in -= n_bits - buf_len;
+ buf_len = 0;
+ zs->total_in += n_bits;
+ size = n_bits;
+ in_count -= n_bits;
+ } else {
+ if (in_count > n_bits) {
+ memcpy (gbuf, zs->next_in, n_bits);
+ zs->next_in += n_bits;
+ zs->avail_in -= n_bits;
+ zs->total_in += n_bits;
+ size = n_bits;
+ in_count -= n_bits;
+ } else {
+ memcpy (gbuf, zs->next_in, in_count);
+ zs->next_in += in_count;
+ zs->avail_in -= in_count;
+ zs->total_in += in_count;
+ size = in_count;
+ in_count = 0;
+ }
+ }
+ roffset = 0;
+ /* Round size down to integral number of codes. */
+ size = (size << 3) - (n_bits - 1);
+ }
+ r_off = roffset;
+ bits = n_bits;
+
+ /* Get to the first byte. */
+ bp += (r_off >> 3);
+ r_off &= 7;
+
+ /* Get first part (low order bits). */
+ gcode = (*bp++ >> r_off);
+ bits -= (8 - r_off);
+ r_off = 8 - r_off; /* Now, roffset into gcode word. */
+
+ /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
+ if (bits >= 8) {
+ gcode |= *bp++ << r_off;
+ r_off += 8;
+ bits -= 8;
+ }
+
+ /* High order bits. */
+ gcode |= (*bp & rmask[bits]) << r_off;
+ roffset += n_bits;
+
+ return (gcode);
+}
+
+static void
+zinit(s_zstate_t *zs)
+{
+ memset(zs, 0, sizeof (s_zstate_t));
+
+ maxbits = BITS; /* User settable max # bits/code. */
+ maxmaxcode = 1 << maxbits; /* Should NEVER generate this code. */
+ hsize = HSIZE; /* For dynamic table sizing. */
+ free_ent = 0; /* First unused entry. */
+ block_compress = BLOCK_MASK;
+ clear_flg = 0;
+ state = S_START;
+ roffset = 0;
+ size = 0;
+}
--- /dev/null 2004-02-29 10:29:44.000000000 -0600
+++ src/lzw/zopen.h 2004-02-29 10:30:23.514589000 -0600
@@ -0,0 +1,101 @@
+/* $NetBSD: zopen.c,v 1.8 2003/08/07 11:13:29 agc Exp $ */
+
+/*-
+ * Copyright (c) 1985, 1986, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Diomidis Spinellis and James A. Woods, derived from original
+ * work by Spencer Thomas and Joseph Orost.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)zopen.c 8.1 (Berkeley) 6/27/93";
+#else
+static char rcsid[] = "$NetBSD: zopen.c,v 1.8 2003/08/07 11:13:29 agc Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+
+#define BITS 16 /* Default bits. */
+#define HSIZE 69001 /* 95% occupancy */
+
+/* A code_int must be able to hold 2**BITS values of type int, and also -1. */
+typedef long code_int;
+typedef long count_int;
+
+typedef unsigned char char_type;
+
+typedef struct {
+ unsigned char *next_in;
+ unsigned int avail_in;
+ unsigned long total_in;
+
+ unsigned char *next_out;
+ unsigned int avail_out;
+ unsigned long total_out;
+
+ enum {
+ S_START, S_MIDDLE, S_EOF
+ } zs_state; /* State of computation */
+ int zs_n_bits; /* Number of bits/code. */
+ int zs_maxbits; /* User settable max # bits/code. */
+ code_int zs_maxcode; /* Maximum code, given n_bits. */
+ code_int zs_maxmaxcode; /* Should NEVER generate this code. */
+ count_int zs_htab [HSIZE];
+ unsigned short zs_codetab [HSIZE];
+ code_int zs_hsize; /* For dynamic table sizing. */
+ code_int zs_free_ent; /* First unused entry. */
+ /*
+ * Block compression parameters -- after all codes are used up,
+ * and compression rate changes, start over.
+ */
+ int zs_block_compress;
+ int zs_clear_flg;
+ int zs_offset;
+ long zs_in_count; /* Remaining uncompressed bytes. */
+ char_type zs_buf_len;
+ char_type zs_buf[BITS]; /* Temporary buffer if we need
+ to read more to accumulate
+ n_bits. */
+ union {
+ struct {
+ char_type *zs_stackp;
+ int zs_finchar;
+ code_int zs_code, zs_oldcode, zs_incode;
+ int zs_roffset, zs_size;
+ char_type zs_gbuf[BITS];
+ } r; /* Read parameters */
+ } u;
+} s_zstate_t;
+
+static code_int getcode(s_zstate_t *);
+static int zclose(s_zstate_t *);
+static void zinit(s_zstate_t *);
+static int zread(s_zstate_t *);
--- /dev/null 2004-02-29 10:29:44.000000000 -0600
+++ src/lzw/ftlzw.c 2004-02-29 10:32:45.159078000 -0600
@@ -0,0 +1,422 @@
+/***************************************************************************/
+/* */
+/* ftlzw.c */
+/* */
+/* FreeType support for .Z compressed files */
+/* */
+/* this optional component relies on NetBSD's zopen(). It should */
+/* mainly be used to parse compressed PCF fonts, as found with */
+/* many X11 server distributions. */
+/* */
+/* Copyright 2004 by */
+/* Albert Chin-A-Young. */
+/* */
+/* Based on code in src/gzip/ftgzip.c, Copyright 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#include <ft2build.h>
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_DEBUG_H
+#include <string.h>
+#include <stdio.h>
+#include "zopen.h"
+
+/***************************************************************************/
+/***************************************************************************/
+/***** *****/
+/***** M E M O R Y M A N A G E M E N T *****/
+/***** *****/
+/***************************************************************************/
+/***************************************************************************/
+
+/***************************************************************************/
+/***************************************************************************/
+/***** *****/
+/***** F I L E D E S C R I P T O R *****/
+/***** *****/
+/***************************************************************************/
+/***************************************************************************/
+
+#define FT_LZW_BUFFER_SIZE 4096
+
+ typedef struct FT_LZWFileRec_
+ {
+ FT_Stream source; /* parent/source stream */
+ FT_Stream stream; /* embedding stream */
+ FT_Memory memory; /* memory allocator */
+ s_zstate_t zstream; /* lzw input stream */
+
+ FT_ULong start; /* starting position, after .Z header */
+ FT_Byte input[ FT_LZW_BUFFER_SIZE ]; /* input buffer */
+
+ FT_Byte buffer[ FT_LZW_BUFFER_SIZE ]; /* output buffer */
+ FT_ULong pos; /* position in output */
+ FT_Byte* cursor;
+ FT_Byte* limit;
+ } FT_LZWFileRec, *FT_LZWFile;
+
+
+ /* check and skip .Z header */
+ static FT_Error
+ ft_lzw_check_header( FT_Stream stream )
+ {
+ FT_Error error = 0;
+ FT_Byte head[2];
+
+ if ( FT_STREAM_SEEK( 0 ) ||
+ FT_STREAM_READ( head, 2 ) )
+ goto Exit;
+
+ /* head[0] && head[1] are the magic numbers */
+ if ( head[0] != 0x1f ||
+ head[1] != 0x9d )
+ {
+ error = FT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+
+ static FT_Error
+ ft_lzw_file_init( FT_LZWFile zip,
+ FT_Stream stream,
+ FT_Stream source )
+ {
+ s_zstate_t* zstream = &zip->zstream;
+ FT_Error error = 0;
+
+ zip->stream = stream;
+ zip->source = source;
+ zip->memory = stream->memory;
+
+ zip->limit = zip->buffer + FT_LZW_BUFFER_SIZE;
+ zip->cursor = zip->limit;
+ zip->pos = 0;
+
+ /* check and skip .Z header */
+ {
+ stream = source;
+
+ error = ft_lzw_check_header( source );
+ if (error)
+ goto Exit;
+
+ zip->start = FT_STREAM_POS();
+ }
+
+ /* initialize internal lzw variable */
+ zinit( zstream );
+
+ zstream->avail_in = 0;
+ zstream->next_in = zip->buffer;
+ zstream->zs_in_count = source->size - 2;
+
+ if ( zstream->next_in == NULL )
+ {
+ error = FT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+
+ static void
+ ft_lzw_file_done( FT_LZWFile zip )
+ {
+ s_zstate_t* zstream = &zip->zstream;
+
+ /* clear the rest */
+ zstream->next_in = NULL;
+ zstream->next_out = NULL;
+ zstream->avail_in = 0;
+ zstream->avail_out = 0;
+ zstream->total_in = 0;
+ zstream->total_out = 0;
+
+ zip->memory = NULL;
+ zip->source = NULL;
+ zip->stream = NULL;
+ }
+
+
+ static FT_Error
+ ft_lzw_file_reset( FT_LZWFile zip )
+ {
+ FT_Stream stream = zip->source;
+ FT_Error error;
+
+ if ( !FT_STREAM_SEEK( zip->start ) )
+ {
+ s_zstate_t* zstream = &zip->zstream;
+
+ zinit( zstream );
+
+ zstream->avail_in = 0;
+ zstream->next_in = zip->input;
+ zstream->total_in = 0;
+ zstream->avail_out = 0;
+ zstream->next_out = zip->buffer;
+ zstream->total_out = 0;
+ zstream->zs_in_count = zip->source->size - 2;
+
+ zip->limit = zip->buffer + FT_LZW_BUFFER_SIZE;
+ zip->cursor = zip->limit;
+ zip->pos = 0;
+ }
+ return error;
+ }
+
+
+ static FT_Error
+ ft_lzw_file_fill_input( FT_LZWFile zip )
+ {
+ s_zstate_t* zstream = &zip->zstream;
+ FT_Stream stream = zip->source;
+ FT_ULong size;
+
+ if ( stream->read )
+ {
+ size = stream->read( stream, stream->pos, zip->input,
+ FT_LZW_BUFFER_SIZE );
+ if ( size == 0 )
+ return FT_Err_Invalid_Stream_Operation;
+ }
+ else
+ {
+ size = stream->size - stream->pos;
+ if ( size > FT_LZW_BUFFER_SIZE )
+ size = FT_LZW_BUFFER_SIZE;
+
+ if ( size == 0 )
+ return FT_Err_Invalid_Stream_Operation;
+
+ FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
+ }
+ stream->pos += size;
+
+ zstream->next_in = zip->input;
+ zstream->avail_in = size;
+
+ return 0;
+ }
+
+
+
+ static FT_Error
+ ft_lzw_file_fill_output( FT_LZWFile zip )
+ {
+ s_zstate_t* zstream = &zip->zstream;
+ FT_Error error = 0;
+
+ zip->cursor = zip->buffer;
+ zstream->next_out = zip->cursor;
+ zstream->avail_out = FT_LZW_BUFFER_SIZE;
+
+ while ( zstream->avail_out > 0 )
+ {
+ int num_read = 0;
+
+ if ( zstream->avail_in == 0 )
+ {
+ error = ft_lzw_file_fill_input( zip );
+ if ( error )
+ break;
+ }
+
+ num_read = zread( zstream );
+
+ if ( num_read == -1 && zstream->zs_in_count == 0 )
+ {
+ zip->limit = zstream->next_out;
+ if ( zip->limit == zip->cursor )
+ error = FT_Err_Invalid_Stream_Operation;
+ break;
+ }
+ else if ( num_read == -1 )
+ {
+ break;
+ }
+ else
+ {
+ zstream->avail_out -= num_read;
+ }
+ }
+ return error;
+ }
+
+
+ /* fill output buffer, 'count' must be <= FT_LZW_BUFFER_SIZE */
+ static FT_Error
+ ft_lzw_file_skip_output( FT_LZWFile zip,
+ FT_ULong count )
+ {
+ FT_Error error = 0;
+ FT_ULong delta;
+
+ for (;;)
+ {
+ delta = (FT_ULong)( zip->limit - zip->cursor );
+ if ( delta >= count )
+ delta = count;
+
+ zip->cursor += delta;
+ zip->pos += delta;
+
+ count -= delta;
+ if ( count == 0 )
+ break;
+
+ error = ft_lzw_file_fill_output( zip );
+ if ( error )
+ break;
+ }
+
+ return error;
+ }
+
+
+ static FT_ULong
+ ft_lzw_file_io( FT_LZWFile zip,
+ FT_ULong pos,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ FT_ULong result = 0;
+ FT_Error error;
+
+ /* reset inflate stream if we're seeking backwards */
+ /* yes, that's not too efficient, but it saves memory :-) */
+ if ( pos < zip->pos )
+ {
+ error = ft_lzw_file_reset( zip );
+ if ( error ) goto Exit;
+ }
+
+ /* skip unwanted bytes */
+ if ( pos > zip->pos )
+ {
+ error = ft_lzw_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( count == 0 )
+ goto Exit;
+
+ /* now read the data */
+ for (;;)
+ {
+ FT_ULong delta;
+
+ delta = (FT_ULong)( zip->limit - zip->cursor );
+ if ( delta >= count )
+ delta = count;
+
+ FT_MEM_COPY( buffer, zip->cursor, delta );
+ buffer += delta;
+ result += delta;
+ zip->cursor += delta;
+ zip->pos += delta;
+
+ count -= delta;
+ if ( count == 0 )
+ break;
+
+ error = ft_lzw_file_fill_output( zip );
+ if ( error )
+ break;
+ }
+
+ Exit:
+ return result;
+ }
+
+
+/***************************************************************************/
+/***************************************************************************/
+/***** *****/
+/***** E M B E D D I N G S T R E A M *****/
+/***** *****/
+/***************************************************************************/
+/***************************************************************************/
+
+ static void
+ ft_lzw_stream_close( FT_Stream stream )
+ {
+ FT_LZWFile zip = stream->descriptor.pointer;
+ FT_Memory memory = stream->memory;
+
+ if ( zip )
+ {
+ /* finalize lzw file descriptor */
+ ft_lzw_file_done( zip );
+
+ FT_FREE( zip );
+
+ stream->descriptor.pointer = NULL;
+ }
+ }
+
+
+ static FT_ULong
+ ft_lzw_stream_io( FT_Stream stream,
+ FT_ULong pos,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ FT_LZWFile zip = stream->descriptor.pointer;
+
+ return ft_lzw_file_io( zip, pos, buffer, count );
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stream_OpenLZW( FT_Stream stream,
+ FT_Stream source )
+ {
+ FT_Error error;
+ FT_Memory memory = source->memory;
+ FT_LZWFile zip;
+
+ FT_ZERO( stream );
+ stream->memory = memory;
+
+ if ( !FT_NEW( zip ) )
+ {
+ error = ft_lzw_file_init( zip, stream, source );
+ if ( error )
+ {
+ FT_FREE( zip );
+ goto Exit;
+ }
+
+ stream->descriptor.pointer = zip;
+ }
+
+ stream->size = 0x7FFFFFFFL; /* don't know the real size !! */
+ stream->pos = 0;
+ stream->base = 0;
+ stream->read = ft_lzw_stream_io;
+ stream->close = ft_lzw_stream_close;
+
+ Exit:
+ return error;
+ }
+
+#include "zopen.c"
--- include/freetype/config/ftheader.h.orig Sat Feb 28 18:01:02 2004
+++ include/freetype/config/ftheader.h Sat Feb 28 17:59:10 2004
@@ -372,6 +372,17 @@
/* */
#define FT_GZIP_H <freetype/ftgzip.h>
+ /*************************************************************************/
+ /* */
+ /* @macro: */
+ /* FT_LZW_H */
+ /* */
+ /* @description: */
+ /* A macro used in #include statements to name the file containing */
+ /* the definitions of an API to support for lzw-compressed files. */
+ /* */
+#define FT_LZW_H <freetype/ftlzw.h>
+
/*************************************************************************/
/* */
--- src/pcf/pcfdriver.c.orig Thu Feb 26 15:09:36 2004
+++ src/pcf/pcfdriver.c Sat Feb 28 18:15:20 2004
@@ -31,6 +31,7 @@
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_OBJECTS_H
#include FT_GZIP_H
+#include FT_LZW_H
#include FT_ERRORS_H
#include FT_BDF_H
@@ -212,7 +213,7 @@
FT_TRACE4(( "PCF_Face_Done: done face\n" ));
- /* close gzip stream if any */
+ /* close gzip/lzw stream if any */
if ( face->root.stream == &face->gzip_stream )
{
FT_Stream_Close( &face->gzip_stream );
@@ -236,7 +237,6 @@
FT_UNUSED( params );
FT_UNUSED( face_index );
-
error = pcf_load_font( stream, face );
if ( error )
{
@@ -249,16 +249,37 @@
error = error2;
if ( error )
- goto Fail;
+ {
+ FT_Error error3;
- face->gzip_source = stream;
- face->root.stream = &face->gzip_stream;
+ /* this didn't work, try lzw support !! */
+ error3 = FT_Stream_OpenLZW( &face->gzip_stream, stream );
+ if ( error3 == FT_Err_Unimplemented_Feature )
+ goto Fail;
+
+ error = error3;
+ if ( error )
+ goto Fail;
+
+ face->gzip_source = stream;
+ face->root.stream = &face->gzip_stream;
+
+ stream = face->root.stream;
+
+ error = pcf_load_font( stream, face );
+ if ( error )
+ goto Fail;
+ } else
+ {
+ face->gzip_source = stream;
+ face->root.stream = &face->gzip_stream;
- stream = face->root.stream;
+ stream = face->root.stream;
- error = pcf_load_font( stream, face );
- if ( error )
- goto Fail;
+ error = pcf_load_font( stream, face );
+ if ( error )
+ goto Fail;
+ }
}
/* set-up charmap */