freetype-devel
[Top][All Lists]
Advanced

[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 */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]