LazFreeType: Add TFreeTypeStream class, allow fonts to be loaded from streams. Patch by "circular"

git-svn-id: trunk@40207 -
This commit is contained in:
ask 2013-02-08 12:35:14 +00:00
parent 247bb4784b
commit 7aff56c144
7 changed files with 709 additions and 774 deletions

View File

@ -192,6 +192,8 @@ type
TFreeTypeFont = class(TFreeTypeRenderableFont)
private
FName: String;
FStream: TStream;
FOwnedStream: boolean;
FPointSize: single;
FHinted: boolean;
FStyleStr: string;
@ -217,6 +219,7 @@ type
procedure SetName(const AValue: String);
procedure DiscardFace;
procedure DiscardInstance;
procedure DiscardStream;
procedure SetPixelSize(const AValue: single);
procedure SetPointSize(const AValue: single);
function LoadGlyphInto(_glyph : TT_Glyph;
@ -254,6 +257,7 @@ type
SmallLinePadding: boolean;
constructor Create;
destructor Destroy; override;
procedure AccessFromStream(AStream: TStream; AStreamOwner: boolean);
procedure RenderText(AText: string; x,y: single; ARect: TRect; OnRender : TDirectRenderingFunction); override;
procedure SetNameAndStyle(AName: string; AStyle: string); overload;
procedure SetNameAndStyle(AName: string; AStyle: TFreeTypeStyles); overload;
@ -772,6 +776,12 @@ begin
PrevDPI := DPI;
DiscardFace;
if FStream <> nil then
begin
errorNum := TT_Open_Face(FStream,False,FFace);
if errorNum <> TT_Err_Ok then
raise exception.Create('Cannot open font (TT_Error ' + intToStr(errorNum)+') <Stream>');
end else
if (Pos(PathDelim, AName) <> 0) or (Collection = nil) or (Collection.FontFileCount = 0) then
begin
if AName = '' then exit;
@ -799,6 +809,7 @@ end;
procedure TFreeTypeFont.SetName(const AValue: String);
begin
DiscardStream;
if FName=AValue then exit;
UpdateFace(AValue);
end;
@ -1043,6 +1054,17 @@ begin
end;
end;
procedure TFreeTypeFont.DiscardStream;
begin
if FStream <> nil then
begin
DiscardFace;
if FOwnedStream then FStream.Free;
FStream := nil;
FOwnedStream:= false;
end;
end;
procedure TFreeTypeFont.SetPixelSize(const AValue: single);
begin
if FInstanceCreated then
@ -1298,10 +1320,19 @@ destructor TFreeTypeFont.Destroy;
begin
DiscardInstance;
DiscardFace;
DiscardStream;
FGlyphTable.Free;
inherited Destroy;
end;
procedure TFreeTypeFont.AccessFromStream(AStream: TStream; AStreamOwner: boolean);
begin
DiscardStream;
FStream := AStream;
FOwnedStream:= AStreamOwner;
UpdateFace('');
end;
procedure TFreeTypeFont.RenderText(AText: string; x, y: single; ARect: TRect;
OnRender: TDirectRenderingFunction);
var

View File

@ -37,7 +37,7 @@ unit LazFreeType;
interface
{$R-}
uses TTTypes;
uses TTTypes, Classes;
(***********************************************************************)
(* *)
@ -83,6 +83,9 @@ uses TTTypes;
function TT_Open_Face( fontname : string;
var _face : TT_Face ) : TT_Error;
function TT_Open_Face( AStream : TStream; AStreamOwner: boolean;
var _face : TT_Face ) : TT_Error;
(*****************************************************************)
(* Open a font file embedded in a collection. *)
(* *)
@ -527,6 +530,23 @@ uses
TT_Open_Face := error;
end;
function TT_Open_Face(AStream: TStream; AStreamOwner: boolean;
var _face: TT_Face): TT_Error;
var
input : TFont_Input;
begin
input.fontIndex := 0;
if TT_Open_Stream( AStream, AStreamOwner, input.stream ) then
begin
TT_Open_Face := error;
exit;
end;
Cache_New( face_cache, Pointer(_face), @input );
TT_Open_Face := error;
end;
(*****************************************************************)
(* *)

View File

@ -138,7 +138,7 @@ uses
num_SH, u : UShort;
i : Int;
num_segs : Int;
stream: TT_Stream;
ftstream: TFreeTypeStream;
label
Fail, SimpleExit;
begin
@ -150,124 +150,124 @@ uses
exit;
end;
TT_Use_Stream(cmap.StreamPtr^, stream);
if TT_Use_Stream(cmap.StreamPtr^, ftstream) then exit;
if TT_Seek_File( cmap.offset ) then goto SimpleExit;
if ftstream.SeekFile( cmap.offset ) then goto SimpleExit;
case cmap.format of
0: with cmap.cmap0 do
if Alloc( glyphIdArray, 256 ) or
TT_Read_File( glyphIdArray^, 256 ) then goto Fail;
ftstream.ReadFile( glyphIdArray^, 256 ) then goto Fail;
2: begin
num_SH := 0;
with cmap.cmap2 do
begin
if Alloc( subHeaderKeys, 256*sizeof(UShort) ) or
TT_Access_Frame( 512 ) then goto Fail;
ftstream.AccessFrame( 512 ) then goto Fail;
for i := 0 to 255 do
begin
u := GET_UShort shr 3;
u := ftstream.GET_UShort shr 3;
subHeaderKeys^[i] := u;
if num_SH < u then num_SH := u;
end;
TT_Forget_Frame;
ftstream.ForgetFrame;
(* now load sub headers *)
numGlyphId := ((cmap.length - 2*(256+3) - num_SH*8) and $FFFF)
div 2;
if Alloc( subHeaders, (num_SH+1)*sizeof(TCMap2SubHeader) ) or
TT_Access_Frame( (num_SH+1)*8 ) then goto Fail;
ftstream.AccessFrame( (num_SH+1)*8 ) then goto Fail;
for i := 0 to num_SH do with subHeaders^[i] do
begin
firstCode := GET_UShort;
entryCount := GET_UShort;
idDelta := GET_UShort;
firstCode := ftstream.GET_UShort;
entryCount := ftstream.GET_UShort;
idDelta := ftstream.GET_UShort;
(* we apply the location offset immediately *)
idRangeOffset := GET_UShort - (num_SH-i)*8 - 2;
idRangeOffset := ftstream.GET_UShort - (num_SH-i)*8 - 2;
end;
TT_Forget_Frame;
ftstream.ForgetFrame;
(* load glyph ids *)
if Alloc( glyphIdArray, numGlyphId*sizeof(UShort) ) or
TT_Access_Frame( numGlyphId*2 ) then goto Fail;
ftstream.AccessFrame( numGlyphId*2 ) then goto Fail;
for i := 0 to numGlyphId-1 do
glyphIdArray^[i] := GET_UShort;
glyphIdArray^[i] := ftstream.GET_UShort;
TT_Forget_Frame;
ftstream.ForgetFrame;
end;
end;
4: with cmap.cmap4 do
begin
if TT_Access_Frame(8) then goto Fail;
if ftstream.AccessFrame(8) then goto Fail;
segCountX2 := Get_UShort;
searchRange := Get_UShort;
entrySelector := Get_UShort;
rangeShift := Get_UShort;
segCountX2 := ftstream.Get_UShort;
searchRange := ftstream.Get_UShort;
entrySelector := ftstream.Get_UShort;
rangeShift := ftstream.Get_UShort;
num_segs := segCountX2 shr 1;
TT_Forget_Frame;
ftstream.ForgetFrame;
(* load segments *)
if Alloc( segments, num_segs*sizeof(TCMap4Segment) ) or
TT_Access_Frame( (num_segs*4+1)*2 ) then goto Fail;
ftstream.AccessFrame( (num_segs*4+1)*2 ) then goto Fail;
for i := 0 to num_segs-1 do
segments^[i].endCount := Get_UShort;
segments^[i].endCount := ftstream.Get_UShort;
Get_UShort;
ftstream.Get_UShort;
for i := 0 to num_segs-1 do
segments^[i].startCount := Get_UShort;
segments^[i].startCount := ftstream.Get_UShort;
for i := 0 to num_segs-1 do
segments^[i].idDelta := GET_Short;
segments^[i].idDelta := ftstream.GET_Short;
for i := 0 to num_segs-1 do
segments^[i].idRangeOffset := GET_UShort;
segments^[i].idRangeOffset := ftstream.GET_UShort;
TT_Forget_Frame;
ftstream.ForgetFrame;
numGlyphId := (( cmap.length - (16+8*num_segs) ) and $FFFF)
div 2;
(* load glyph ids *)
if Alloc( glyphIdArray, numGlyphId*sizeof(UShort) ) or
TT_Access_Frame( numGlyphId*2 ) then goto Fail;
ftstream.AccessFrame( numGlyphId*2 ) then goto Fail;
for i := 0 to numGlyphId-1 do
glyphIdArray^[i] := Get_UShort;
glyphIdArray^[i] := ftstream.Get_UShort;
TT_Forget_Frame;
ftstream.ForgetFrame;
end;
6: with cmap.cmap6 do
begin
if TT_Access_Frame(4) then goto Fail;
if ftstream.AccessFrame(4) then goto Fail;
firstCode := GET_UShort;
entryCount := GET_UShort;
firstCode := ftstream.GET_UShort;
entryCount := ftstream.GET_UShort;
TT_Forget_Frame;
ftstream.ForgetFrame;
if Alloc( glyphIdArray, entryCount*sizeof(Short) ) or
TT_Access_Frame( entryCount*2 ) then goto Fail;
ftstream.AccessFrame( entryCount*2 ) then goto Fail;
for i := 0 to entryCount-1 do
glyphIdArray^[i] := GET_UShort;
glyphIdArray^[i] := ftstream.GET_UShort;
TT_Forget_Frame;
ftstream.ForgetFrame;
end;
else

File diff suppressed because it is too large Load Diff

View File

@ -222,8 +222,8 @@ const
******************************************************************)
function Load_Simple_Glyph( exec : PExec_Context;
{%H-}stream : TT_Stream;
function Load_Simple_Glyph( AStream : TFreeTypeStream;
exec : PExec_Context;
n_contours : Int;
left_contours : Int;
left_points : Int;
@ -264,7 +264,7 @@ const
(* Reading the contours endpoints *)
if TT_Access_Frame( (n_contours+1)*2 ) then
if AStream.AccessFrame( (n_contours+1)*2 ) then
goto Fail_File;
n_points := 0;
@ -272,7 +272,7 @@ const
for k := 0 to n_contours-1 do
begin
{$IFDEF FREETYPE_DEBUG} Write( n_points,' '); {$ENDIF}
n_points := GET_Short;
n_points := AStream.GET_Short;
exec^.pts.conEnds^[k] := n_points;
inc( n_points );
end;
@ -286,9 +286,9 @@ const
(* Loading instructions *)
n_ins := GET_Short;
n_ins := AStream.GET_Short;
TT_Forget_Frame;
AStream.ForgetFrame;
{
if not subg^.is_hinted then
@ -312,7 +312,7 @@ const
with exec^ do
begin
if TT_Read_File( glyphIns^, n_ins ) then
if AStream.ReadFile( glyphIns^, n_ins ) then
goto Fail_File;
glyphSize := n_ins;
@ -327,7 +327,7 @@ const
(* read the flags *)
if TT_Check_And_Access_Frame( n_points*5 )
if AStream.CheckAndAccessFrame( n_points*5 )
then goto Fail;
k := 0;
@ -335,13 +335,13 @@ const
while ( k < n_points ) do
begin
c := GET_Byte;
c := AStream.GET_Byte;
flag^[k] := c;
inc(k);
if c and 8 <> 0 then
begin
cnt := GET_Byte;
cnt := AStream.GET_Byte;
while ( cnt > 0 ) do
begin
@ -361,10 +361,10 @@ const
begin
if flag^[k] and 2 <> 0 then
if flag^[k] and 16 <> 0 then inc( x, GET_Byte )
else inc( x, -GET_Byte )
if flag^[k] and 16 <> 0 then inc( x, AStream.GET_Byte )
else inc( x, -AStream.GET_Byte )
else
if flag^[k] and 16 = 0 then inc( x, GET_Short );
if flag^[k] and 16 = 0 then inc( x, AStream.GET_Short );
coords^[k].x := x;
end;
@ -377,15 +377,15 @@ const
begin
if flag^[k] and 4 <> 0 then
if flag^[k] and 32 <> 0 then inc( y, GET_Byte )
else inc( y, -GET_Byte )
if flag^[k] and 32 <> 0 then inc( y, AStream.GET_Byte )
else inc( y, -AStream.GET_Byte )
else
if flag^[k] and 32 = 0 then inc( y, GET_Short );
if flag^[k] and 32 = 0 then inc( y, AStream.GET_Short );
coords^[k].y := y;
end;
TT_Forget_Frame;
AStream.ForgetFrame;
(* Now adds the two shadow points at n and n+1 *)
(* We need the left side bearing and advance width *)
@ -490,7 +490,8 @@ const
*
******************************************************************)
function Load_Composite_End( n_points : Int;
function Load_Composite_End( AStream: TFreeTypeStream;
n_points : Int;
{%H-}n_contours : Int;
exec : PExec_Context;
subg : PSubglyph_Record;
@ -509,9 +510,9 @@ const
if subg^.is_hinted and
(subg^.element_flag and WE_HAVE_INSTR <> 0) then
begin
if TT_Access_Frame(2) then goto Fail_File;
n_ins := Get_UShort;
TT_Forget_Frame;
if AStream.AccessFrame(2) then goto Fail_File;
n_ins := AStream.Get_UShort;
AStream.ForgetFrame;
(* load the instructions *)
{$IFDEF FREETYPE_DEBUG} Writeln('Instructions size : ', n_ins); {$ENDIF}
@ -528,7 +529,7 @@ const
if n_ins > 0 then with exec^ do
begin
if TT_Read_File( glyphIns^, n_ins ) then
if AStream.ReadFile( glyphIns^, n_ins ) then
goto Fail_File;
glyphSize := n_ins;
@ -680,7 +681,7 @@ const
xx, xy, yx, yy : TT_Fixed;
exec : PExec_Context;
stream : TT_Stream;
ftstream : TFreeTypeStream;
subglyph, subglyph2 : PSubGlyph_Record;
@ -779,7 +780,7 @@ const
(* now access stream *)
if TT_Use_Stream( face^.stream, stream {%H-}) then
if TT_Use_Stream( face^.stream, ftstream {%H-}) then
goto Fin;
(* Main Loading Loop *)
@ -848,17 +849,17 @@ const
(* read first glyph header *)
if TT_Seek_File( offset ) or
TT_Access_Frame( 5*sizeof(Short) ) then
if ftstream.SeekFile( offset ) or
ftstream.AccessFrame( 5*sizeof(Short) ) then
goto Fail_File;
num_contours := GET_Short;
subglyph^.bbox.xMin := GET_Short;
subglyph^.bbox.yMin := GET_Short;
subglyph^.bbox.xMax := GET_Short;
subglyph^.bbox.yMax := GET_Short;
num_contours := ftstream.GET_Short;
subglyph^.bbox.xMin := ftstream.GET_Short;
subglyph^.bbox.yMin := ftstream.GET_Short;
subglyph^.bbox.xMax := ftstream.GET_Short;
subglyph^.bbox.yMax := ftstream.GET_Short;
TT_Forget_Frame;
ftstream.ForgetFrame;
{$IFDEF FREETYPE_DEBUG}
Writeln('Glyph ', i );
@ -925,8 +926,8 @@ const
new_flags := new_flags and not TT_Load_Debug;
if Load_Simple_Glyph(
ftstream,
exec,
stream,
num_contours,
left_contours,
left_points,
@ -973,15 +974,15 @@ const
(* now read composite header *)
if TT_Access_Frame( 4 ) then
if ftstream.AccessFrame( 4 ) then
goto Fail_File;
new_flags := Get_UShort;
new_flags := ftstream.Get_UShort;
subglyph^.element_flag := new_flags;
subglyph2^.index := Get_UShort;
subglyph2^.index := ftstream.Get_UShort;
TT_Forget_Frame;
ftstream.ForgetFrame;
k := 2;
@ -997,18 +998,18 @@ const
if new_flags and WE_HAVE_A_2X2 <> 0 then
inc( k, 8 );
if TT_Access_Frame( k ) then
if ftstream.AccessFrame( k ) then
goto Fail_File;
if new_flags and ARGS_ARE_WORDS <> 0 then
begin
k := Get_Short;
l := Get_Short;
k := ftstream.Get_Short;
l := ftstream.Get_Short;
end
else
begin
k := Get_Byte;
l := Get_Byte;
k := ftstream.Get_Byte;
l := ftstream.Get_Byte;
end;
subglyph^.arg1 := k;
@ -1027,24 +1028,24 @@ const
if new_flags and WE_HAVE_A_SCALE <> 0 then
begin
xx := Long(Get_Short) shl 2;
xx := Long(ftstream.Get_Short) shl 2;
yy := xx;
subglyph2^.is_scaled := true;
end
else if new_flags and WE_HAVE_AN_XY_SCALE <> 0 then
begin
xx := Long(Get_Short) shl 2;
yy := Long(Get_Short) shl 2;
xx := Long(ftstream.Get_Short) shl 2;
yy := Long(ftstream.Get_Short) shl 2;
subglyph2^.is_scaled := true;
end
else if new_flags and WE_HAVE_A_2X2 <> 0 then
begin
xx := Long(Get_Short) shl 2;
xy := Long(Get_Short) shl 2;
yx := Long(Get_Short) shl 2;
yy := Long(Get_Short) shl 2;
xx := Long(ftstream.Get_Short) shl 2;
xy := Long(ftstream.Get_Short) shl 2;
yx := Long(ftstream.Get_Short) shl 2;
yy := Long(ftstream.Get_Short) shl 2;
subglyph2^.is_scaled := true;
end;
@ -1060,9 +1061,9 @@ const
if abs(delta) <> 1 shl 16 then
subglyph2^.is_hinted := false;
TT_Forget_Frame;
ftstream.ForgetFrame;
subglyph^.file_offset := TT_File_Pos;
subglyph^.file_offset := ftstream.Position;
phase := Load_Glyph;
end;
@ -1186,7 +1187,7 @@ const
(* check for last component *)
if TT_Seek_File( subglyph^.file_offset ) then
if ftstream.SeekFile( subglyph^.file_offset ) then
goto Fail_File;
if subglyph^.element_flag and MORE_COMPONENTS <> 0 then
@ -1196,7 +1197,8 @@ const
debug := ( load_top = 0 ) and
( load_flags and TT_Load_Debug <> 0 );
if Load_Composite_End( num_points,
if Load_Composite_End( ftstream,
num_points,
num_contours,
exec,
subglyph,
@ -1344,7 +1346,7 @@ const
Load_TrueType_Glyph := Success;
Fail:
TT_Done_Stream( stream );
TT_Done_Stream( face^.stream );
Fin:

View File

@ -26,27 +26,27 @@ Unit TTLoad;
interface
{$R-}
uses TTTypes, TTTables, TTCMap, TTObjs;
uses TTTypes, TTTables, TTCMap, TTObjs, TTFile;
function LookUp_TrueType_Table( face : PFace;
aTag : string ) : int;
function Load_TrueType_Directory( face : PFace;
function Load_TrueType_Directory( AStream: TFreeTypeStream; face : PFace;
faceIndex : Int ) : TError;
function Load_TrueType_MaxProfile( face : PFace ) : TError;
function Load_TrueType_Header ( face : PFace ) : TError;
function Load_TrueType_Locations ( face : PFace ) : TError;
function Load_TrueType_CVT ( face : PFace ) : TError;
function Load_TrueType_CMap ( face : PFace ) : TError;
function Load_TrueType_Gasp ( face : PFace ) : TError;
function Load_TrueType_Names ( face : PFace ) : TError;
function Load_TrueType_Programs ( face : PFace ) : TError;
function Load_trueType_Postscript( face : PFace ) : TError;
function Load_TrueType_OS2 ( face : PFace ) : TError;
function Load_TrueType_HDMX ( face : PFace ) : TError;
function Load_TrueType_MaxProfile( AStream: TFreeTypeStream; face : PFace ) : TError;
function Load_TrueType_Header ( AStream: TFreeTypeStream; face : PFace ) : TError;
function Load_TrueType_Locations ( AStream: TFreeTypeStream; face : PFace ) : TError;
function Load_TrueType_CVT ( AStream: TFreeTypeStream; face : PFace ) : TError;
function Load_TrueType_CMap ( AStream: TFreeTypeStream; face : PFace ) : TError;
function Load_TrueType_Gasp ( AStream: TFreeTypeStream; face : PFace ) : TError;
function Load_TrueType_Names ( AStream: TFreeTypeStream; face : PFace ) : TError;
function Load_TrueType_Programs ( AStream: TFreeTypeStream; face : PFace ) : TError;
function Load_trueType_Postscript( AStream: TFreeTypeStream; face : PFace ) : TError;
function Load_TrueType_OS2 ( AStream: TFreeTypeStream; face : PFace ) : TError;
function Load_TrueType_HDMX ( AStream: TFreeTypeStream; face : PFace ) : TError;
function Load_TrueType_Metrics_Header( face : PFace;
function Load_TrueType_Metrics_Header( AStream: TFreeTypeStream; face : PFace;
vertical : Boolean ) : TError;
function Load_TrueType_Any( face : PFace;
@ -57,7 +57,7 @@ uses TTTypes, TTTables, TTCMap, TTObjs;
implementation
uses TTError, TTMemory, TTFile;
uses TTError, TTMemory;
(* Composite glyph decoding flags *)
@ -125,7 +125,7 @@ uses TTError, TTMemory, TTFile;
*
******************************************************************)
function Load_TrueType_Collection( face : PFace ) : TError;
function Load_TrueType_Collection( AStream: TFreeTypeStream; face : PFace ) : TError;
var
n : Int;
const
@ -139,14 +139,14 @@ uses TTError, TTMemory, TTFile;
with face^.ttcHeader do
begin
if TT_Seek_File( 0 ) or
TT_Access_Frame( 12 ) then exit;
if AStream.SeekFile( 0 ) or
AStream.AccessFrame(12 ) then exit;
Tag := Get_ULong;
version := Get_Long;
dirCount := Get_Long;
Tag := AStream.Get_ULong;
version := AStream.Get_Long;
dirCount := AStream.Get_Long;
TT_Forget_Frame;
AStream.ForgetFrame;
if Tag <> TTC_Tag then
begin
@ -160,12 +160,12 @@ uses TTError, TTMemory, TTFile;
end;
if Alloc( tableDirectory, dirCount * sizeof(ULong) ) or
TT_Access_Frame( dirCount*4 ) then exit;
AStream.AccessFrame( dirCount*4 ) then exit;
for n := 0 to dirCount-1 do
tableDirectory^[n] := Get_ULong;
tableDirectory^[n] := AStream.Get_ULong;
TT_Forget_Frame;
AStream.ForgetFrame;
end;
Load_TrueType_Collection := Success;
@ -186,7 +186,7 @@ uses TTError, TTMemory, TTFile;
*
******************************************************************)
function Load_TrueType_Directory( face : PFace;
function Load_TrueType_Directory( AStream: TFreeTypeStream; face : PFace;
faceIndex : Int ) : TError;
var
n : Int;
@ -196,7 +196,7 @@ uses TTError, TTMemory, TTFile;
{$IFDEF FREETYPE_DEBUG} Write('Directory '); {$ENDIF}
if Load_TrueType_Collection(face) then
if Load_TrueType_Collection(AStream, face) then
begin
if error <> TT_Err_File_Is_Not_Collection then
exit;
@ -208,7 +208,7 @@ uses TTError, TTMemory, TTFile;
error := TT_Err_Ok;
(* Now skip to the beginning of the file *)
if TT_Seek_File(0) then
if AStream.SeekFile(0) then
exit;
end
else
@ -222,23 +222,23 @@ uses TTError, TTMemory, TTFile;
end;
(* select a TT Font within the ttc file *)
if TT_Seek_File( face^.ttcHeader.tableDirectory^[faceIndex] ) then
if AStream.SeekFile( face^.ttcHeader.tableDirectory^[faceIndex] ) then
exit;
end;
if TT_Access_Frame( 12 ) then
if AStream.AccessFrame( 12 ) then
exit;
tableDir.version := GET_Long;
tableDir.numTables := GET_UShort;
tableDir.version := AStream.GET_Long;
tableDir.numTables := AStream.GET_UShort;
tableDir.searchRange := GET_UShort;
tableDir.entrySelector := GET_UShort;
tableDir.rangeShift := GET_UShort;
tableDir.searchRange := AStream.GET_UShort;
tableDir.entrySelector := AStream.GET_UShort;
tableDir.rangeShift := AStream.GET_UShort;
{$IFDEF FREETYPE_DEBUG} Writeln('Tables number : ', tableDir.numTables ); {$ENDIF}
TT_Forget_Frame();
AStream.ForgetFrame;
(* Check that we have a 'sfnt' format there *)
if (tableDir.version <> $10000 ) and (* MS fonts *)
@ -249,20 +249,25 @@ uses TTError, TTMemory, TTFile;
exit;
end;
face^.numTables := tableDir.numTables;
if Alloc( face^.dirTables, face^.numTables * sizeof( TTableDirEntry ) ) or
TT_Access_Frame( 16 * face^.numTables ) then exit;
for n := 0 to face^.numTables-1 do
with face^ do
begin
face^.dirTables^[n].Tag := GET_ULong;
face^.dirTables^[n].Checksum := GET_ULong;
face^.dirTables^[n].Offset := GET_Long;
face^.dirTables^[n].Length := Get_Long;
end;
TT_Forget_Frame();
numTables := tableDir.numTables;
if Alloc( dirTables, numTables * sizeof( TTableDirEntry ) ) or
AStream.AccessFrame( 16 * numTables ) then exit;
for n := 0 to numTables-1 do with dirTables^[n] do
begin
Tag := AStream.GET_ULong;
Checksum := AStream.GET_ULong;
Offset := AStream.GET_Long;
Length := AStream.Get_Long;
end;
AStream.ForgetFrame;
end;
{$IFDEF FREETYPE_DEBUG} Writeln('loaded'); {$ENDIF}
@ -284,7 +289,7 @@ uses TTError, TTMemory, TTFile;
*
******************************************************************)
function Load_TrueType_MaxProfile( face : PFace ) : TError;
function Load_TrueType_MaxProfile( AStream: TFreeTypeStream; face : PFace ) : TError;
var
table : int;
begin
@ -299,10 +304,10 @@ uses TTError, TTMemory, TTFile;
with face^ do
begin
if TT_Seek_File( dirTables^[table].Offset ) or
TT_Access_Frame( 32 ) then exit;
if astream.SeekFile( dirTables^[table].Offset ) or
AStream.AccessFrame( 32 ) then exit;
with MaxProfile do
with AStream, MaxProfile do
begin
ULong(Version) := GET_ULong;
@ -325,7 +330,7 @@ uses TTError, TTMemory, TTFile;
maxComponentDepth := GET_UShort;
end;
TT_Forget_Frame;
AStream.ForgetFrame;
(* XXX : an adjustement that is necessary to load certain */
/* broken fonts like "Keystrokes MT" :-( */
@ -381,7 +386,7 @@ uses TTError, TTMemory, TTFile;
*
******************************************************************)
function Load_TrueType_Gasp( face : PFace ) : TError;
function Load_TrueType_Gasp( AStream: TFreeTypeStream; face : PFace ) : TError;
var
gRanges : PGaspRanges;
table, i : Int;
@ -404,33 +409,33 @@ uses TTError, TTMemory, TTFile;
exit;
end;
if TT_Seek_File( face^.dirTables^[table].Offset ) or
TT_Access_Frame( 4 ) then exit;
if astream.SeekFile( face^.dirTables^[table].Offset ) or
AStream.AccessFrame( 4 ) then exit;
with face^.gasp do
with AStream, face^.gasp do
begin
version := Get_UShort;
numRanges := Get_UShort;
gaspRanges := nil;
end;
TT_Forget_Frame;
AStream.ForgetFrame;
gRanges:=nil;
if Alloc( gRanges, face^.gasp.numRanges * sizeof(TGaspRange) ) or
TT_Access_Frame( face^.gasp.numRanges * 4 ) then
AStream.AccessFrame( face^.gasp.numRanges * 4 ) then
goto Fail;
face^.gasp.gaspRanges := gRanges;
for i := 0 to face^.gasp.numRanges-1 do
with gRanges^[i] do
with AStream, gRanges^[i] do
begin
maxPPEM := Get_UShort;
gaspFlag := Get_UShort;
end;
TT_Forget_Frame;
AStream.ForgetFrame;
Load_TrueType_Gasp := Success;
exit;
@ -457,7 +462,7 @@ uses TTError, TTMemory, TTFile;
*
******************************************************************)
function Load_TrueType_Header( face : PFace ) : TError;
function Load_TrueType_Header( AStream: TFreeTypeStream; face : PFace ) : TError;
var
i : int;
begin
@ -471,10 +476,10 @@ uses TTError, TTMemory, TTFile;
with face^ do
begin
if TT_Seek_File( dirTables^[i].offset ) or
TT_Access_Frame( 54 ) then exit;
if AStream.SeekFile( dirTables^[i].offset ) or
AStream.AccessFrame(54 ) then exit;
with FontHeader do
with AStream, FontHeader do
begin
ULong(Table_Version) := GET_ULong;
@ -505,7 +510,7 @@ uses TTError, TTMemory, TTFile;
end;
TT_Forget_Frame;
AStream.ForgetFrame;
end;
@ -529,7 +534,7 @@ uses TTError, TTMemory, TTFile;
*
******************************************************************)
function Load_TrueType_Metrics( face : PFace;
function Load_TrueType_Metrics( AStream: TFreeTypeStream; face : PFace;
vertical : Boolean ) : TError;
var
table, n : int;
@ -599,20 +604,20 @@ uses TTError, TTMemory, TTFile;
if Alloc( longs^, sizeof(TLongMetrics) * num_longs ) or
Alloc( shorts^, sizeof(TShortMetrics)* num_shorts ) or
TT_Seek_File( face^.dirTables^[table].Offset ) or
TT_Access_Frame( face^.dirTables^[table].Length ) then exit;
AStream.SeekFile( face^.dirTables^[table].Offset ) or
AStream.AccessFrame( face^.dirTables^[table].Length ) then exit;
for n := 0 to num_longs-1 do with longs^^[n] do
begin
advance := GET_UShort;
bearing := GET_Short;
advance := AStream.GET_UShort;
bearing := AStream.GET_Short;
end;
(* do we have an inconsistent number of metric values ? *)
if num_shorts > num_shorts_checked then
begin
for n := 0 to num_shorts_checked-1 do
shorts^^[n] := GET_Short;
shorts^^[n] := AStream.GET_Short;
(* we fill up the missing left side bearings with the *)
(* last valid value. Since this will occur for buggy CJK *)
@ -625,9 +630,9 @@ uses TTError, TTMemory, TTFile;
end
else
for n := 0 to num_shorts-1 do
shorts^^[n] := GET_Short;
shorts^^[n] := AStream.GET_Short;
TT_Forget_Frame;
AStream.ForgetFrame;
{$IFDEF FREETYPE_DEBUG} Writeln('loaded'); {$ENDIF}
@ -649,7 +654,7 @@ uses TTError, TTMemory, TTFile;
*
******************************************************************)
function Load_TrueType_Metrics_Header( face : PFace;
function Load_TrueType_Metrics_Header( AStream: TFreeTypeStream; face : PFace;
vertical : Boolean ) : TError;
var
table : int;
@ -691,11 +696,11 @@ uses TTError, TTMemory, TTFile;
with face^ do
begin
if TT_Seek_File( dirTables^[table].Offset ) or
TT_Access_Frame( 36 ) then
if AStream.SeekFile( dirTables^[table].Offset ) or
AStream.AccessFrame( 36 ) then
exit;
with header^ do
with AStream, header^ do
begin
Long(Version) := GET_ULong;
@ -726,13 +731,13 @@ uses TTError, TTMemory, TTFile;
end;
TT_Forget_Frame;
AStream.ForgetFrame;
end;
{$IFDEF FREETYPE_DEBUG} Writeln('loaded'); {$ENDIF}
Load_TrueType_Metrics_Header := Load_TrueType_Metrics( face, vertical );
Load_TrueType_Metrics_Header := Load_TrueType_Metrics( AStream, face, vertical );
end;
(*******************************************************************
@ -754,7 +759,7 @@ uses TTError, TTMemory, TTFile;
*
******************************************************************)
function Load_TrueType_Locations( face : PFace ): TError;
function Load_TrueType_Locations( AStream: TFreeTypeStream; face : PFace ): TError;
var
t, n : int;
LongOffsets : int;
@ -772,7 +777,7 @@ uses TTError, TTMemory, TTFile;
t := LookUp_Mandatory_Table( face, 'loca' );
if t < 0 then exit;
if TT_Seek_File( dirTables^[T].Offset ) then exit;
if AStream.SeekFile( dirTables^[T].Offset ) then exit;
if LongOffsets <> 0 then
begin
@ -784,12 +789,12 @@ uses TTError, TTMemory, TTFile;
{$ENDIF}
if Alloc( glyphLocations, sizeof(Long)*numLocations ) or
TT_Access_Frame( numLocations*4 ) then exit;
AStream.AccessFrame( numLocations*4 ) then exit;
for n := 0 to numLocations-1 do
glyphLocations^[n] := GET_Long;
glyphLocations^[n] := AStream.GET_Long;
TT_Forget_Frame;
AStream.ForgetFrame;
end
else
@ -801,12 +806,12 @@ uses TTError, TTMemory, TTFile;
{$ENDIF}
if Alloc( glyphLocations, sizeof(Long)*numLocations ) or
TT_Access_Frame( numLocations*2 ) then exit;
AStream.AccessFrame( numLocations*2 ) then exit;
for n := 0 to numLocations-1 do
glyphLocations^[n] := Long(GET_UShort) * 2;
glyphLocations^[n] := Long(AStream.GET_UShort) * 2;
TT_Forget_Frame;
AStream.ForgetFrame;
end;
end;
@ -832,7 +837,7 @@ uses TTError, TTMemory, TTFile;
*
******************************************************************)
function Load_TrueType_Names( face : PFace ) : TError;
function Load_TrueType_Names( AStream: TFreeTypeStream; face : PFace ) : TError;
var
table, i : Int;
bytes : Long;
@ -845,17 +850,17 @@ uses TTError, TTMemory, TTFile;
with face^.nameTable do
begin
(* Seek to the beginning of the table and check the frame access. *)
if TT_Seek_File( face^.dirTables^[table].Offset ) or
TT_Access_Frame( 6 ) then exit;
if AStream.SeekFile( face^.dirTables^[table].Offset ) or
AStream.AccessFrame(6 ) then exit;
format := GET_UShort;
numNameRecords := GET_UShort;
storageOffset := GET_UShort;
format := AStream.GET_UShort;
numNameRecords := AStream.GET_UShort;
storageOffset := AStream.GET_UShort;
TT_Forget_Frame;
AStream.ForgetFrame;
if Alloc( names, numNameRecords*sizeof(TName_Record) ) or
TT_Access_Frame( numNameRecords*12 ) then
AStream.AccessFrame( numNameRecords*12 ) then
begin
numNameRecords := 0;
exit;
@ -865,7 +870,7 @@ uses TTError, TTMemory, TTFile;
(* to hold the strings themselves *)
bytes := 0;
for i := 0 to numNameRecords-1 do with names^[i] do
for i := 0 to numNameRecords-1 do with AStream, names^[i] do
begin
platformID := GET_UShort;
encodingID := GET_UShort;
@ -880,14 +885,14 @@ uses TTError, TTMemory, TTFile;
bytes := Offset + Length;
end;
TT_Forget_Frame;
AStream.ForgetFrame;
storage := nil;
if bytes > 0 then
begin
if Alloc( storage, bytes ) then exit;
if TT_Read_At_File( face^.dirTables^[table].Offset + storageOffset,
if AStream.ReadAtFile( face^.dirTables^[table].Offset + storageOffset,
storage^, bytes ) then
begin
Free(storage);
@ -916,7 +921,7 @@ uses TTError, TTMemory, TTFile;
*
******************************************************************)
function Load_TrueType_CVT( face : PFace ): TError;
function Load_TrueType_CVT( AStream: TFreeTypeStream; face : PFace ): TError;
var
t, n : Int;
begin
@ -943,14 +948,14 @@ uses TTError, TTMemory, TTFile;
if Alloc( cvt, sizeof(Short)*cvtSize ) or
TT_Seek_File( dirTables^[t].Offset ) or
AStream.SeekFile( dirTables^[t].Offset ) or
TT_Access_Frame( 2*cvtSize ) then exit;
AStream.AccessFrame(2*cvtSize ) then exit;
for n := 0 to cvtSize-1 do
cvt^[n] := GET_Short;
cvt^[n] := AStream.GET_Short;
TT_Forget_Frame;
AStream.ForgetFrame;
end;
{$IFDEF FREETYPE_DEBUG} Writeln('loaded'); {$ENDIF}
@ -974,7 +979,7 @@ uses TTError, TTMemory, TTFile;
*
******************************************************************)
function Load_TrueType_CMap( face : PFace ) : TError;
function Load_TrueType_CMap( AStream: TFreeTypeStream; face : PFace ) : TError;
var
off, table_start : Longint;
n, t : Int;
@ -998,15 +1003,15 @@ uses TTError, TTMemory, TTFile;
table_start := dirTables^[t].offset;
if TT_Seek_File( dirTables^[t].Offset ) or
TT_Access_Frame( 4 ) then exit;
if AStream.SeekFile( dirTables^[t].Offset ) or
AStream.AccessFrame( 4 ) then exit;
cmap_dir.tableVersionNumber := GET_UShort;
cmap_dir.numCMaps := GET_UShort;
cmap_dir.tableVersionNumber := AStream.GET_UShort;
cmap_dir.numCMaps := AStream.GET_UShort;
TT_Forget_Frame;
AStream.ForgetFrame;
off := TT_File_Pos;
off := AStream.Position;
(* save space in face data for cmap tables *)
numCMaps := cmap_dir.numCMaps;
@ -1015,34 +1020,34 @@ uses TTError, TTMemory, TTFile;
for n := 0 to numCMaps-1 do
begin
if TT_Seek_File ( off ) or
TT_Access_Frame( 8 ) then exit;
if AStream.SeekFile ( off ) or
AStream.AccessFrame( 8 ) then exit;
cmap := @cMaps^[n];
entry.platformID := GET_UShort;
entry.platformEncodingID := GET_UShort;
entry.offset := GET_Long;
entry.platformID := AStream.GET_UShort;
entry.platformEncodingID := AStream.GET_UShort;
entry.offset := AStream.GET_Long;
cmap^.loaded := False;
cmap^.platformID := entry.platformID;
cmap^.platformEncodingID := entry.platformEncodingID;
TT_Forget_Frame;
AStream.ForgetFrame;
off := TT_File_Pos;
off := AStream.Position;
if TT_Seek_File ( table_start + entry.offset ) or
TT_Access_Frame( 6 ) then exit;
if AStream.SeekFile ( table_start + entry.offset ) or
AStream.AccessFrame( 6 ) then exit;
cmap^.format := Get_UShort;
cmap^.length := Get_UShort;
cmap^.version := Get_UShort;
cmap^.format := AStream.Get_UShort;
cmap^.length := AStream.Get_UShort;
cmap^.version := AStream.Get_UShort;
TT_Forget_Frame;
AStream.ForgetFrame;
cmap^.StreamPtr := @face^.stream;
cmap^.offset := TT_File_Pos;
cmap^.offset := AStream.Position;
end; (* for n *)
@ -1108,7 +1113,7 @@ uses TTError, TTMemory, TTFile;
*
******************************************************************)
function Load_TrueType_Programs( face : PFace ) : TError;
function Load_TrueType_Programs( AStream: TFreeTypeStream; face : PFace ) : TError;
var
t : Int;
begin
@ -1139,7 +1144,7 @@ uses TTError, TTMemory, TTFile;
fontPgmSize := dirTables^[t].Length;
if Alloc( fontProgram, fontPgmSize ) or
TT_Read_At_File( dirTables^[t].offset,
AStream.ReadAtFile( dirTables^[t].offset,
fontProgram^,
fontPgmSize ) then exit;
@ -1170,7 +1175,7 @@ uses TTError, TTMemory, TTFile;
cvtPgmSize := dirTables^[t].Length;
if Alloc( cvtProgram, cvtPgmSize ) or
TT_Read_At_File( dirTables^[t].offset,
AStream.ReadAtFile( dirTables^[t].offset,
cvtProgram^,
cvtPgmSize ) then exit;
@ -1192,7 +1197,7 @@ uses TTError, TTMemory, TTFile;
*
******************************************************************)
function Load_TrueType_OS2( face : PFace ) : TError;
function Load_TrueType_OS2( AStream: TFreeTypeStream; face : PFace ) : TError;
var
table : Int;
i : Int;
@ -1210,10 +1215,10 @@ uses TTError, TTMemory, TTFile;
exit;
end;
if TT_Seek_File( face^.dirTables^[table].offset ) or
TT_Access_Frame( 78 ) then exit;
if AStream.SeekFile( face^.dirTables^[table].offset ) or
AStream.AccessFrame( 78 ) then exit;
with face^.os2 do
with AStream, face^.os2 do
begin
version := Get_UShort;
xAvgCharWidth := Get_Short;
@ -1250,16 +1255,16 @@ uses TTError, TTMemory, TTFile;
usWinAscent := Get_UShort;
usWinDescent := Get_UShort;
TT_Forget_Frame;
AStream.ForgetFrame;
if version >= $0001 then
begin
if TT_Access_Frame(8) then exit;
if AStream.AccessFrame(8) then exit;
ulCodePageRange1 := Get_ULong;
ulCodePageRange2 := Get_ULong;
ulCodePageRange1 := AStream.Get_ULong;
ulCodePageRange2 := AStream.Get_ULong;
TT_Forget_Frame;
AStream.ForgetFrame;
end
else
begin
@ -1286,7 +1291,7 @@ uses TTError, TTMemory, TTFile;
*
******************************************************************)
function Load_TrueType_Postscript( face : PFace ) : TError;
function Load_TrueType_Postscript( AStream: TFreeTypeStream; face : PFace ) : TError;
var
table : Int;
begin
@ -1297,10 +1302,10 @@ uses TTError, TTMemory, TTFile;
table := LookUp_TrueType_Table( face, 'post' );
if table < 0 then exit;
if TT_Seek_File( face^.dirTables^[table].offset ) or
TT_Access_Frame(32) then exit;
if AStream.SeekFile( face^.dirTables^[table].offset ) or
AStream.AccessFrame(32) then exit;
with face^.postscript do
with AStream, face^.postscript do
begin
formatType := Get_ULong;
italicAngle := Get_ULong;
@ -1313,7 +1318,7 @@ uses TTError, TTMemory, TTFile;
maxMemType1 := Get_ULong;
end;
TT_Forget_Frame;
AStream.ForgetFrame;
{$IFDEF FREETYPE_DEBUG} Writeln('loaded'); {$ENDIF}
@ -1332,7 +1337,7 @@ uses TTError, TTMemory, TTFile;
*
******************************************************************)
function Load_TrueType_Hdmx( face : PFace ) : TError;
function Load_TrueType_Hdmx( AStream: TFreeTypeStream; face : PFace ) : TError;
var
table, n : Int;
num_glyphs : Int;
@ -1362,14 +1367,14 @@ uses TTError, TTMemory, TTFile;
exit;
end;
if TT_Seek_File( face^.dirTables^[table].offset ) or
TT_Access_Frame( 8 ) then exit;
if AStream.SeekFile( face^.dirTables^[table].offset ) or
AStream.AccessFrame(8 ) then exit;
version := Get_UShort;
num_rec := Get_Short;
rec_size := Get_Long;
version := AStream.Get_UShort;
num_rec := AStream.Get_Short;
rec_size := AStream.Get_Long;
TT_Forget_Frame;
AStream.ForgetFrame;
(* right now, we only recognize format 0 *)
@ -1390,22 +1395,22 @@ uses TTError, TTMemory, TTFile;
(* read record *)
if TT_Access_Frame(2) then
if AStream.AccessFrame(2) then
goto Fail;
rec^.ppem := Get_Byte;
rec^.max_width := Get_Byte;
rec^.ppem := AStream.Get_Byte;
rec^.max_width := AStream.Get_Byte;
TT_Forget_Frame;
AStream.ForgetFrame;
if Alloc( rec^.widths, num_glyphs ) or
TT_Read_File( rec^.widths^, num_glyphs ) then
AStream.ReadFile( rec^.widths^, num_glyphs ) then
goto Fail;
(* skip padding bytes *)
if rec_size > 0 then
if TT_Skip_File( rec_size ) then
if AStream.SkipFile( rec_size ) then
goto Fail;
end;
@ -1440,7 +1445,7 @@ uses TTError, TTMemory, TTFile;
var buffer;
var length : longint ) : TError;
var
stream : TT_Stream;
ftstream : TFreeTypeStream;
found, i : integer;
begin
if tag <> 0 then
@ -1483,8 +1488,8 @@ uses TTError, TTMemory, TTFile;
exit;
end;
TT_Use_Stream( face^.stream, stream {%H-});
Load_TrueType_Any := TT_Read_At_File( offset, buffer, length );
TT_Use_Stream( face^.stream, ftstream {%H-});
Load_TrueType_Any := ftstream.ReadAtFile( offset, buffer, length );
TT_Done_Stream( face^.stream );
end;

View File

@ -682,7 +682,7 @@ type
PFont_Input = ^TFont_Input;
TFont_Input = record
stream : TT_Stream; (* inpute stream *)
stream : TT_Stream; (* input stream *)
fontIndex : Int; (* index of font in collection *)
end;
@ -1834,8 +1834,8 @@ const
var
input : PFont_Input;
face : PFace;
label
Fail;
ftstream: TFreeTypeStream;
label Fail;
begin
Face_Create := Failure;
@ -1843,34 +1843,38 @@ const
input := PFont_Input(_input);
face^.stream := input^.stream;
if TT_Use_Stream(face^.stream, ftstream) then exit;
if Cache_Create( objs_instance_class, face^.instances ) or
Cache_Create( objs_glyph_class, face^.glyphs ) then exit;
Cache_Create( objs_glyph_class, face^.glyphs ) then goto Fail;
(* Load collection directory if present *)
if Load_TrueType_Directory( face, input^.fontIndex ) then
exit;
if Load_TrueType_Directory( ftstream, face, input^.fontIndex ) then
goto Fail;
if Load_TrueType_Header ( face ) or
Load_TrueType_MaxProfile ( face ) or
Load_TrueType_Locations ( face ) or
Load_TrueType_CMap ( face ) or
Load_TrueType_CVT ( face ) or
Load_TrueType_Metrics_Header ( face, false ) or
Load_TrueType_Programs ( face ) or
Load_TrueType_Gasp ( face ) or
Load_TrueType_Names ( face ) or
Load_TrueType_OS2 ( face ) or
Load_TrueType_Hdmx ( face ) or
Load_TrueType_Postscript ( face ) or
Load_TrueType_Metrics_Header ( face, true ) then
if Load_TrueType_Header ( ftstream, face ) or
Load_TrueType_MaxProfile ( ftstream, face ) or
Load_TrueType_Locations ( ftstream, face ) or
Load_TrueType_CMap ( ftstream, face ) or
Load_TrueType_CVT ( ftstream, face ) or
Load_TrueType_Metrics_Header ( ftstream, face, false ) or
Load_TrueType_Programs ( ftstream, face ) or
Load_TrueType_Gasp ( ftstream, face ) or
Load_TrueType_Names ( ftstream, face ) or
Load_TrueType_OS2 ( ftstream, face ) or
Load_TrueType_Hdmx ( ftstream, face ) or
Load_TrueType_Postscript ( ftstream, face ) or
Load_TrueType_Metrics_Header ( ftstream, face, true ) then
goto Fail;
Face_Create := Success;
TT_Done_Stream(face^.stream);
exit;
Fail:
TT_Done_Stream(face^.stream);
Face_Destroy( face );
exit;
end;