parent
7110f2144a
commit
d464139d60
4 changed files with 1045 additions and 0 deletions
@ -0,0 +1,462 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* 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 2004 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" |
||||
|
||||
|
||||
#include FT_MODULE_ERRORS_H |
||||
|
||||
#undef __FTERRORS_H__ |
||||
|
||||
#define FT_ERR_PREFIX LZW_Err_ |
||||
#define FT_ERR_BASE FT_Mod_Err_LZW |
||||
|
||||
#include FT_ERRORS_H |
||||
|
||||
|
||||
#ifdef FT_CONFIG_OPTION_USE_LZW |
||||
|
||||
|
||||
/***************************************************************************/ |
||||
/***************************************************************************/ |
||||
/***** *****/ |
||||
/***** 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; |
||||
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 = LZW_Err_Invalid_File_Format; |
||||
|
||||
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 = LZW_Err_Ok; |
||||
|
||||
|
||||
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 = LZW_Err_Invalid_File_Format; |
||||
|
||||
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 LZW_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 LZW_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 LZW_Err_Ok; |
||||
} |
||||
|
||||
|
||||
|
||||
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 = LZW_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 = LZW_Err_Ok; |
||||
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; |
||||
|
||||
|
||||
/* Teset inflate stream if we're seeking backwards. */ |
||||
/* Yes, that is 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; |
||||
} |
||||
|
||||
|
||||
/***************************************************************************/ |
||||
/***************************************************************************/ |
||||
/***** *****/ |
||||
/***** L Z W 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 = (FT_LZWFile)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 = (FT_LZWFile)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" |
||||
|
||||
|
||||
#else /* !FT_CONFIG_OPTION_USE_LZW */ |
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error ) |
||||
FT_Stream_OpenLZW( FT_Stream stream, |
||||
FT_Stream source ) |
||||
{ |
||||
FT_UNUSED( stream ); |
||||
FT_UNUSED( source ); |
||||
|
||||
return LZW_Err_Unimplemented_Feature; |
||||
} |
||||
|
||||
|
||||
#endif /* !FT_CONFIG_OPTION_USE_LZW */ |
||||
|
||||
|
||||
/* END */ |
@ -0,0 +1,70 @@ |
||||
#
|
||||
# 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_DIR)/lzw
|
||||
|
||||
|
||||
# compilation flags for the driver
|
||||
#
|
||||
LZW_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(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_DIR)/zopen.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_DIR)/ftlzw.$O
|
||||
LZW_DRV_OBJ_S := $(OBJ_DIR)/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$(subst /,$(COMPILER_SEP),$@ $(LZW_DRV_SRC_S))
|
||||
|
||||
|
||||
# LZW support - multiple objects
|
||||
#
|
||||
$(OBJ_DIR)/%.$O: $(LZW_DIR)/%.c $(FREETYPE_H) $(LZW_DRV_H) |
||||
$(LZW_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
|
||||
|
||||
|
||||
# update main driver object lists
|
||||
#
|
||||
DRV_OBJS_S += $(LZW_DRV_OBJ_S)
|
||||
DRV_OBJS_M += $(LZW_DRV_OBJ_M)
|
||||
|
||||
|
||||
# EOF
|
@ -0,0 +1,399 @@ |
||||
/* $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 <dds@doc.ic.ac.uk>. |
||||
*/ |
||||
|
||||
#include <sys/param.h> |
||||
#include <sys/stat.h> |
||||
|
||||
#include <ctype.h> |
||||
#include <signal.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <unistd.h> |
||||
|
||||
#if 0 |
||||
static char_type magic_header[] = |
||||
{ 0x1f, 0x9d }; /* 1F 9D */ |
||||
#endif |
||||
|
||||
#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. |
||||
*/ |
||||
|
||||
#if 0 |
||||
static int |
||||
zclose(s_zstate_t *zs) |
||||
{ |
||||
free(zs); |
||||
return (0); |
||||
} |
||||
#endif |
||||
|
||||
/*-
|
||||
* 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; |
||||
|
||||
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 < (unsigned int)n_bits && in_count > (long)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; |
||||
} |
@ -0,0 +1,114 @@ |
||||
/* $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 */ |
||||
|
||||
#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 enum { |
||||
S_START, S_MIDDLE, S_EOF |
||||
} zs_enum; |
||||
|
||||
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; |
||||
|
||||
zs_enum 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 *); |
||||
#if 0 |
||||
static int zclose(s_zstate_t *); |
||||
#endif |
||||
static void zinit(s_zstate_t *); |
||||
static int zread(s_zstate_t *); |
Loading…
Reference in new issue