📄 vpdfzlib.pas
字号:
{*******************************************************}
{ }
{ This unit is part of the VISPDF VCL library. }
{ Written by R.Husske - ALL RIGHTS RESERVED. }
{ }
{ Copyright (C) 2000-2009, www.vispdf.com }
{ }
{ e-mail: support@vispdf.com }
{ http://www.vispdf.com }
{ }
{*******************************************************}
unit VPDFZLib;
interface
uses Windows, SysUtils, Classes, Dialogs;
{$I VisPDFLib.inc }
type
PInteger = ^Integer;
TSymArray = array of Byte;
TAlloc = function(AppData: Pointer; Items, Size: Integer): Pointer; register;
TFree = procedure(AppData, Block: Pointer); register;
TZStreamRec = packed record
next_in: PAnsiChar;
avail_in: Integer;
total_in: Integer;
next_out: PAnsiChar;
avail_out: Integer;
total_out: Integer;
msg: PAnsiChar;
internal: Pointer;
zalloc: TAlloc;
zfree: TFree;
AppData: Pointer;
data_type: Integer;
adler: Integer;
reserved: Integer;
end;
TCustomZlibStream = class(TStream)
private
FStrm: TStream;
FStrmPos: Integer;
FOnProgress: TNotifyEvent;
FZRec: TZStreamRec;
FBuffer: array[Word] of AnsiChar;
protected
procedure Progress(Sender: TObject); dynamic;
property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
constructor Create(Strm: TStream);
end;
TCompressionLevel = (clNone, clFastest, clDefault, clMax);
TCompressionStream = class(TCustomZlibStream)
private
function GetCompressionRate: Single;
public
constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream);
destructor Destroy; override;
function Read(var Buffer; Count: Longint): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
property CompressionRate: Single read GetCompressionRate;
property OnProgress;
end;
TDecompressionStream = class(TCustomZlibStream)
public
constructor Create(Source: TStream);
destructor Destroy; override;
function Read(var Buffer; Count: Longint): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
property OnProgress;
end;
procedure UpdateContent(InStream, OutStream: TStream);
procedure TraceStream(InStream, OutStream: TStream);
procedure EscapeValue(ValByte, FlushB: TStream);
procedure IncFlushByte(InStream, OutStream: TStream);
procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
out OutBuf: Pointer; out OutBytes: Integer);
procedure UpdateCanvasRelease(const InBuf: Pointer; InBytes: Integer;
OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
const OutBuf: Pointer; BufSize: Integer);
function deflateInit_(var strm: TZStreamRec; level: Integer; version: PAnsiChar;
recsize: Integer): Integer; external;
function _inflateInit_(strm: Pointer; version: PAnsiChar; recsize: Integer): Integer; cdecl;
function _inflate(strm: Pointer; flush: Integer): Integer; cdecl;
function _inflateEnd(strm: Pointer): Integer; cdecl;
function deflate(var strm: TZStreamRec; flush: Integer): Integer; external;
function deflateEnd(var strm: TZStreamRec): Integer; external;
function deflateReset(var strm: TZStreamRec): Integer; cdecl; external;
function inflateSync(var strm: TZStreamRec): Integer; cdecl; external;
function deflateParams(var strm: TZStreamRec; level: Integer; strategy: Integer): Integer; cdecl; external;
function inflateInit_(var strm: TZStreamRec; version: PAnsiChar; recsize: Integer): Integer; external;
function inflate(var strm: TZStreamRec; flush: Integer): Integer; external;
function inflateEnd(var strm: TZStreamRec): Integer; external;
function inflateReset(var strm: TZStreamRec): Integer; external;
function _run_content_specific(in_buff: PByte; in_len: Integer; final_size: PInteger): Pointer; cdecl; external;
function _run_canvas_specific(in_buff: PByte; in_len: Integer; final_size: PInteger): Pointer; cdecl; external;
const
zlib_Version = '1.0.4';
type
EZlibError = class(Exception);
ECompressionError = class(EZlibError);
EDecompressionError = class(EZlibError);
implementation
uses VPDFZLibConst, VPDFCLibs;
const
Z_NO_FLUSH = 0;
Z_PARTIAL_FLUSH = 1;
Z_SYNC_FLUSH = 2;
Z_FULL_FLUSH = 3;
Z_FINISH = 4;
Z_OK = 0;
Z_STREAM_END = 1;
Z_NEED_DICT = 2;
Z_ERRNO = (-1);
Z_STREAM_ERROR = (-2);
Z_DATA_ERROR = (-3);
Z_MEM_ERROR = (-4);
Z_BUF_ERROR = (-5);
Z_VERSION_ERROR = (-6);
Z_NO_COMPRESSION = 0;
Z_BEST_SPEED = 1;
Z_BEST_COMPRESSION = 9;
Z_DEFAULT_COMPRESSION = (-1);
Z_FILTERED = 1;
Z_HUFFMAN_ONLY = 2;
Z_DEFAULT_STRATEGY = 0;
Z_BINARY = 0;
Z_ASCII = 1;
Z_UNKNOWN = 2;
Z_DEFLATED = 8;
Z_HEXARR: array[0..15] of AnsiChar = '0123456789ABCDEF';
Z_BufferSize = $2000;
{$L ..\..\Objs\Zlib\deflate.obj}
{$L ..\..\Objs\Zlib\inflate.obj}
{$L ..\..\Objs\Zlib\inftrees.obj}
{$L ..\..\Objs\Zlib\trees.obj}
{$L ..\..\Objs\Zlib\adler32.obj}
{$L ..\..\Objs\Zlib\infblock.obj}
{$L ..\..\Objs\Zlib\infcodes.obj}
{$L ..\..\Objs\Zlib\infutil.obj}
{$L ..\..\Objs\Zlib\inffast.obj}
{$L ..\..\Objs\Zlib\CONTENT.OBJ}
procedure _tr_init; external;
procedure _tr_tally; external;
procedure _tr_flush_block; external;
procedure _tr_align; external;
procedure _tr_stored_block; external;
procedure adler32; external;
procedure inflate_blocks_new; external;
procedure inflate_blocks; external;
procedure inflate_blocks_reset; external;
procedure inflate_blocks_free; external;
procedure inflate_set_dictionary; external;
procedure inflate_trees_bits; external;
procedure inflate_trees_dynamic; external;
procedure inflate_trees_fixed; external;
procedure inflate_trees_free; external;
procedure inflate_codes_new; external;
procedure inflate_codes; external;
procedure inflate_codes_free; external;
procedure _inflate_mask; external;
procedure inflate_flush; external;
procedure inflate_fast; external;
function _inflateInit_(strm: Pointer; version: PAnsiChar; recsize: Integer): Integer; cdecl;
begin
result := inflateInit_(TZStreamRec(strm^), version, recsize);
end;
function _inflate(strm: Pointer; flush: Integer): Integer; cdecl;
begin
result := inflate(TZStreamRec(strm^), flush);
end;
function _inflateEnd(strm: Pointer): Integer; cdecl;
begin
result := inflateEnd(TZStreamRec(strm^));
end;
procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl;
begin
FillChar(P^, count, B);
end;
procedure _memcpy(dest, source: Pointer; count: Integer); cdecl;
begin
Move(source^, dest^, count);
end;
function zlibAllocMem(AppData: Pointer; Items, Size: Integer): Pointer;
register;
begin
Result := AllocMem(Items * Size);
end;
procedure zlibFreeMem(AppData, Block: Pointer); register;
begin
FreeMem(Block);
end;
function CCheck(code: Integer): Integer;
begin
Result := code;
if code < 0 then
raise ECompressionError.Create('error');
end;
function DCheck(code: Integer): Integer;
begin
Result := code;
if code < 0 then
raise EDecompressionError.Create('error');
end;
procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
out OutBuf: Pointer; out OutBytes: Integer);
var
strm: TZStreamRec;
P: Pointer;
begin
FillChar(strm, sizeof(strm), 0);
strm.zalloc := zlibAllocMem;
strm.zfree := zlibFreeMem;
OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255;
GetMem(OutBuf, OutBytes);
try
strm.next_in := InBuf;
strm.avail_in := InBytes;
strm.next_out := OutBuf;
strm.avail_out := OutBytes;
CCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm)));
try
while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do
begin
P := OutBuf;
Inc(OutBytes, 256);
ReallocMem(OutBuf, OutBytes);
strm.next_out := PAnsiChar(Integer(OutBuf) + (Integer(strm.next_out) -
Integer(P)));
strm.avail_out := 256;
end;
finally
CCheck(deflateEnd(strm));
end;
ReallocMem(OutBuf, strm.total_out);
OutBytes := strm.total_out;
except
FreeMem(OutBuf);
raise
end;
end;
procedure UpdateCanvasRelease(const InBuf: Pointer; InBytes: Integer;
OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
var
strm: TZStreamRec;
P: Pointer;
BufInc: Integer;
begin
FillChar(strm, sizeof(strm), 0);
strm.zalloc := zlibAllocMem;
strm.zfree := zlibFreeMem;
BufInc := (InBytes + 255) and not 255;
if OutEstimate = 0 then
OutBytes := BufInc
else
OutBytes := OutEstimate;
GetMem(OutBuf, OutBytes);
try
strm.next_in := InBuf;
strm.avail_in := InBytes;
strm.next_out := OutBuf;
strm.avail_out := OutBytes;
DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
try
while DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END do
begin
P := OutBuf;
Inc(OutBytes, BufInc);
ReallocMem(OutBuf, OutBytes);
strm.next_out := PAnsiChar(Integer(OutBuf) + (Integer(strm.next_out) -
Integer(P)));
strm.avail_out := BufInc;
end;
finally
DCheck(inflateEnd(strm));
end;
ReallocMem(OutBuf, strm.total_out);
OutBytes := strm.total_out;
except
FreeMem(OutBuf);
raise
end;
end;
procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
const OutBuf: Pointer; BufSize: Integer);
var
strm: TZStreamRec;
begin
FillChar(strm, sizeof(strm), 0);
strm.zalloc := zlibAllocMem;
strm.zfree := zlibFreeMem;
strm.next_in := InBuf;
strm.avail_in := InBytes;
strm.next_out := OutBuf;
strm.avail_out := BufSize;
DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
try
if DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END then
raise EZlibError.CreateRes(@sTargetBufferTooSmall);
finally
DCheck(inflateEnd(strm));
end;
end;
constructor TCustomZLibStream.Create(Strm: TStream);
begin
inherited Create;
FStrm := Strm;
FStrmPos := Strm.Position;
FZRec.zalloc := zlibAllocMem;
FZRec.zfree := zlibFreeMem;
end;
procedure TCustomZLibStream.Progress(Sender: TObject);
begin
if Assigned(FOnProgress) then FOnProgress(Sender);
end;
constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel;
Dest: TStream);
const
Levels: array[TCompressionLevel] of ShortInt =
(Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION);
begin
inherited Create(Dest);
FZRec.next_out := FBuffer;
FZRec.avail_out := sizeof(FBuffer);
CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version,
sizeof(FZRec)));
end;
destructor TCompressionStream.Destroy;
begin
FZRec.next_in := nil;
FZRec.avail_in := 0;
try
if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END)
and (FZRec.avail_out = 0) do
begin
FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
FZRec.next_out := FBuffer;
FZRec.avail_out := sizeof(FBuffer);
end;
if FZRec.avail_out < sizeof(FBuffer) then
FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out);
finally
deflateEnd(FZRec);
end;
inherited Destroy;
end;
function TCompressionStream.Read(var Buffer; Count: Longint): Longint;
begin
raise ECompressionError.CreateRes(@sInvalidStreamOp);
end;
function TCompressionStream.Write(const Buffer; Count: Longint): Longint;
begin
FZRec.next_in := @Buffer;
FZRec.avail_in := Count;
if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
while (FZRec.avail_in > 0) do
begin
CCheck(deflate(FZRec, 0));
if FZRec.avail_out = 0 then
begin
FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
FZRec.next_out := FBuffer;
FZRec.avail_out := sizeof(FBuffer);
FStrmPos := FStrm.Position;
Progress(Self);
end;
end;
Result := Count;
end;
function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
begin
if (Offset = 0) and (Origin = soFromCurrent) then
Result := FZRec.total_in
else
raise ECompressionError.CreateRes(@sInvalidStreamOp);
end;
function TCompressionStream.GetCompressionRate: Single;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -