📄 ftgzip.c
字号:
/***************************************************************************/
/* */
/* ftgzip.c */
/* */
/* FreeType support for .gz compressed files. */
/* */
/* This optional component relies on zlib. It should mainly be used to */
/* parse compressed PCF fonts, as found with many X11 server */
/* distributions. */
/* */
/* Copyright 2002, 2003, 2004, 2005, 2006 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 FT_GZIP_H
#include <string.h>
#include FT_MODULE_ERRORS_H
#undef __FTERRORS_H__
#define FT_ERR_PREFIX Gzip_Err_
#define FT_ERR_BASE FT_Mod_Err_Gzip
#include FT_ERRORS_H
#ifdef FT_CONFIG_OPTION_USE_ZLIB
#ifdef FT_CONFIG_OPTION_SYSTEM_ZLIB
#include <zlib.h>
#else /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */
/* In this case, we include our own modified sources of the ZLib */
/* within the "ftgzip" component. The modifications were necessary */
/* to #include all files without conflicts, as well as preventing */
/* the definition of "extern" functions that may cause linking */
/* conflicts when a program is linked with both FreeType and the */
/* original ZLib. */
#define NO_DUMMY_DECL
#define MY_ZCALLOC
#include "zlib.h"
#undef SLOW
#define SLOW 1 /* we can't use asm-optimized sources here! */
/* Urgh. `inflate_mask' must not be declared twice -- C++ doesn't like
this. We temporarily disable it and load all necessary header files. */
#define NO_INFLATE_MASK
#include "zutil.h"
#include "inftrees.h"
#include "infblock.h"
#include "infcodes.h"
#include "infutil.h"
#undef NO_INFLATE_MASK
/* infutil.c must be included before infcodes.c */
#include "zutil.c"
#include "inftrees.c"
#include "infutil.c"
#include "infcodes.c"
#include "infblock.c"
#include "inflate.c"
#include "adler32.c"
#endif /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */
/***************************************************************************/
/***************************************************************************/
/***** *****/
/***** Z L I B M E M O R Y M A N A G E M E N T *****/
/***** *****/
/***************************************************************************/
/***************************************************************************/
/* it is better to use FreeType memory routines instead of raw
'malloc/free' */
static voidpf
ft_gzip_alloc( FT_Memory memory,
uInt items,
uInt size )
{
FT_ULong sz = (FT_ULong)size * items;
FT_Error error;
FT_Pointer p;
(void)FT_ALLOC( p, sz );
return p;
}
static void
ft_gzip_free( FT_Memory memory,
voidpf address )
{
FT_MEM_FREE( address );
}
#ifndef FT_CONFIG_OPTION_SYSTEM_ZLIB
local voidpf
zcalloc ( voidpf opaque,
unsigned items,
unsigned size )
{
return ft_gzip_alloc( (FT_Memory)opaque, items, size );
}
local void
zcfree( voidpf opaque,
voidpf ptr )
{
ft_gzip_free( (FT_Memory)opaque, ptr );
}
#endif /* !SYSTEM_ZLIB */
/***************************************************************************/
/***************************************************************************/
/***** *****/
/***** Z L I B F I L E D E S C R I P T O R *****/
/***** *****/
/***************************************************************************/
/***************************************************************************/
#define FT_GZIP_BUFFER_SIZE 4096
typedef struct FT_GZipFileRec_
{
FT_Stream source; /* parent/source stream */
FT_Stream stream; /* embedding stream */
FT_Memory memory; /* memory allocator */
z_stream zstream; /* zlib input stream */
FT_ULong start; /* starting position, after .gz header */
FT_Byte input[FT_GZIP_BUFFER_SIZE]; /* input read buffer */
FT_Byte buffer[FT_GZIP_BUFFER_SIZE]; /* output buffer */
FT_ULong pos; /* position in output */
FT_Byte* cursor;
FT_Byte* limit;
} FT_GZipFileRec, *FT_GZipFile;
/* gzip flag byte */
#define FT_GZIP_ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
#define FT_GZIP_HEAD_CRC 0x02 /* bit 1 set: header CRC present */
#define FT_GZIP_EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define FT_GZIP_ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define FT_GZIP_COMMENT 0x10 /* bit 4 set: file comment present */
#define FT_GZIP_RESERVED 0xE0 /* bits 5..7: reserved */
/* check and skip .gz header - we don't support `transparent' compression */
static FT_Error
ft_gzip_check_header( FT_Stream stream )
{
FT_Error error;
FT_Byte head[4];
if ( FT_STREAM_SEEK( 0 ) ||
FT_STREAM_READ( head, 4 ) )
goto Exit;
/* head[0] && head[1] are the magic numbers; */
/* head[2] is the method, and head[3] the flags */
if ( head[0] != 0x1f ||
head[1] != 0x8b ||
head[2] != Z_DEFLATED ||
(head[3] & FT_GZIP_RESERVED) )
{
error = Gzip_Err_Invalid_File_Format;
goto Exit;
}
/* skip time, xflags and os code */
(void)FT_STREAM_SKIP( 6 );
/* skip the extra field */
if ( head[3] & FT_GZIP_EXTRA_FIELD )
{
FT_UInt len;
if ( FT_READ_USHORT_LE( len ) ||
FT_STREAM_SKIP( len ) )
goto Exit;
}
/* skip original file name */
if ( head[3] & FT_GZIP_ORIG_NAME )
for (;;)
{
FT_UInt c;
if ( FT_READ_BYTE( c ) )
goto Exit;
if ( c == 0 )
break;
}
/* skip .gz comment */
if ( head[3] & FT_GZIP_COMMENT )
for (;;)
{
FT_UInt c;
if ( FT_READ_BYTE( c ) )
goto Exit;
if ( c == 0 )
break;
}
/* skip CRC */
if ( head[3] & FT_GZIP_HEAD_CRC )
if ( FT_STREAM_SKIP( 2 ) )
goto Exit;
Exit:
return error;
}
static FT_Error
ft_gzip_file_init( FT_GZipFile zip,
FT_Stream stream,
FT_Stream source )
{
z_stream* zstream = &zip->zstream;
FT_Error error = Gzip_Err_Ok;
zip->stream = stream;
zip->source = source;
zip->memory = stream->memory;
zip->limit = zip->buffer + FT_GZIP_BUFFER_SIZE;
zip->cursor = zip->limit;
zip->pos = 0;
/* check and skip .gz header */
{
stream = source;
error = ft_gzip_check_header( stream );
if ( error )
goto Exit;
zip->start = FT_STREAM_POS();
}
/* initialize zlib -- there is no zlib header in the compressed stream */
zstream->zalloc = (alloc_func)ft_gzip_alloc;
zstream->zfree = (free_func) ft_gzip_free;
zstream->opaque = stream->memory;
zstream->avail_in = 0;
zstream->next_in = zip->buffer;
if ( inflateInit2( zstream, -MAX_WBITS ) != Z_OK ||
zstream->next_in == NULL )
error = Gzip_Err_Invalid_File_Format;
Exit:
return error;
}
static void
ft_gzip_file_done( FT_GZipFile zip )
{
z_stream* zstream = &zip->zstream;
inflateEnd( zstream );
/* clear the rest */
zstream->zalloc = NULL;
zstream->zfree = NULL;
zstream->opaque = NULL;
zstream->next_in = NULL;
zstream->next_out = NULL;
zstream->avail_in = 0;
zstream->avail_out = 0;
zip->memory = NULL;
zip->source = NULL;
zip->stream = NULL;
}
static FT_Error
ft_gzip_file_reset( FT_GZipFile zip )
{
FT_Stream stream = zip->source;
FT_Error error;
if ( !FT_STREAM_SEEK( zip->start ) )
{
z_stream* zstream = &zip->zstream;
inflateReset( zstream );
zstream->avail_in = 0;
zstream->next_in = zip->input;
zstream->avail_out = 0;
zstream->next_out = zip->buffer;
zip->limit = zip->buffer + FT_GZIP_BUFFER_SIZE;
zip->cursor = zip->limit;
zip->pos = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -