mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-01 23:19:39 +01:00
LazUtils: FreeType fixes and new features. Issue #28073, patch from Johann.
git-svn-id: trunk@49047 -
This commit is contained in:
parent
9bbdc4fec0
commit
ccbbb894f3
@ -50,9 +50,13 @@ type
|
|||||||
|
|
||||||
TFontCollectionItemDestroyListener = procedure() of object;
|
TFontCollectionItemDestroyListener = procedure() of object;
|
||||||
ArrayOfFontCollectionItemDestroyListener = array of TFontCollectionItemDestroyListener;
|
ArrayOfFontCollectionItemDestroyListener = array of TFontCollectionItemDestroyListener;
|
||||||
|
TCustomFamilyCollectionItem = class;
|
||||||
|
|
||||||
|
{ TCustomFontCollectionItem }
|
||||||
|
|
||||||
TCustomFontCollectionItem = class
|
TCustomFontCollectionItem = class
|
||||||
protected
|
protected
|
||||||
|
FFamily: TCustomFamilyCollectionItem;
|
||||||
function GetBold: boolean; virtual; abstract;
|
function GetBold: boolean; virtual; abstract;
|
||||||
function GetInformation(AIndex: TFreeTypeInformation): string; virtual; abstract;
|
function GetInformation(AIndex: TFreeTypeInformation): string; virtual; abstract;
|
||||||
function GetItalic: boolean; virtual; abstract;
|
function GetItalic: boolean; virtual; abstract;
|
||||||
@ -76,6 +80,7 @@ type
|
|||||||
property VersionNumber: string read GetVersionNumber;
|
property VersionNumber: string read GetVersionNumber;
|
||||||
property Style[AIndex: integer]: string read GetStyle;
|
property Style[AIndex: integer]: string read GetStyle;
|
||||||
property StyleCount: integer read GetStyleCount;
|
property StyleCount: integer read GetStyleCount;
|
||||||
|
property Family: TCustomFamilyCollectionItem read FFamily write FFamily;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
IFreeTypeFontEnumerator = interface
|
IFreeTypeFontEnumerator = interface
|
||||||
@ -127,7 +132,9 @@ type
|
|||||||
procedure Clear; virtual; abstract;
|
procedure Clear; virtual; abstract;
|
||||||
procedure BeginUpdate; virtual; abstract;
|
procedure BeginUpdate; virtual; abstract;
|
||||||
procedure AddFolder(AFolder: string); virtual; abstract;
|
procedure AddFolder(AFolder: string); virtual; abstract;
|
||||||
|
procedure RemoveFolder(AFolder: string); virtual; abstract;
|
||||||
function AddFile(AFilename: string): boolean; virtual; abstract;
|
function AddFile(AFilename: string): boolean; virtual; abstract;
|
||||||
|
function RemoveFile(AFilename: string): boolean; virtual; abstract;
|
||||||
function AddStream(AStream: TStream; AOwned: boolean): boolean; virtual; abstract;
|
function AddStream(AStream: TStream; AOwned: boolean): boolean; virtual; abstract;
|
||||||
procedure EndUpdate; virtual; abstract;
|
procedure EndUpdate; virtual; abstract;
|
||||||
function FontFileEnumerator: IFreeTypeFontEnumerator; virtual; abstract;
|
function FontFileEnumerator: IFreeTypeFontEnumerator; virtual; abstract;
|
||||||
@ -193,6 +200,8 @@ type
|
|||||||
TFreeTypeFont = class(TFreeTypeRenderableFont)
|
TFreeTypeFont = class(TFreeTypeRenderableFont)
|
||||||
private
|
private
|
||||||
FName: String;
|
FName: String;
|
||||||
|
FFaceChanged: boolean;
|
||||||
|
FDPI: integer;
|
||||||
FStream: TStream;
|
FStream: TStream;
|
||||||
FOwnedStream: boolean;
|
FOwnedStream: boolean;
|
||||||
FPointSize: single;
|
FPointSize: single;
|
||||||
@ -216,7 +225,7 @@ type
|
|||||||
procedure SetFreeTypeStyles(AValue: TFreeTypeStyles);
|
procedure SetFreeTypeStyles(AValue: TFreeTypeStyles);
|
||||||
procedure SetLineFullHeight(AValue: single);
|
procedure SetLineFullHeight(AValue: single);
|
||||||
procedure SetStyleAsString(AValue: string);
|
procedure SetStyleAsString(AValue: string);
|
||||||
procedure UpdateFace(const AName: String);
|
procedure LoadFace;
|
||||||
procedure SetName(const AValue: String);
|
procedure SetName(const AValue: String);
|
||||||
procedure DiscardFace;
|
procedure DiscardFace;
|
||||||
procedure DiscardInstance;
|
procedure DiscardInstance;
|
||||||
@ -242,6 +251,7 @@ type
|
|||||||
FCharMap: TT_CharMap;
|
FCharMap: TT_CharMap;
|
||||||
FCharmapOk: boolean;
|
FCharmapOk: boolean;
|
||||||
FAscentValue, FDescentValue, FLineGapValue, FLargeLineGapValue, FCapHeight: single;
|
FAscentValue, FDescentValue, FLineGapValue, FLargeLineGapValue, FCapHeight: single;
|
||||||
|
procedure FaceChanged;
|
||||||
function GetClearType: boolean; override;
|
function GetClearType: boolean; override;
|
||||||
procedure SetClearType(const AValue: boolean); override;
|
procedure SetClearType(const AValue: boolean); override;
|
||||||
function GetLineFullHeight: single; override;
|
function GetLineFullHeight: single; override;
|
||||||
@ -254,6 +264,8 @@ type
|
|||||||
procedure OnDestroyFontItem;
|
procedure OnDestroyFontItem;
|
||||||
procedure FetchNames;
|
procedure FetchNames;
|
||||||
function GetCollection: TCustomFreeTypeFontCollection;
|
function GetCollection: TCustomFreeTypeFontCollection;
|
||||||
|
function CheckFace: boolean;
|
||||||
|
function CheckInstance: boolean;
|
||||||
public
|
public
|
||||||
Quality : TGlyphRenderQuality;
|
Quality : TGlyphRenderQuality;
|
||||||
SmallLinePadding: boolean;
|
SmallLinePadding: boolean;
|
||||||
@ -690,7 +702,7 @@ end;
|
|||||||
|
|
||||||
constructor TFreeTypeGlyph.Create(AFont: TFreeTypeFont; AIndex: integer);
|
constructor TFreeTypeGlyph.Create(AFont: TFreeTypeFont; AIndex: integer);
|
||||||
begin
|
begin
|
||||||
if TT_New_Glyph(AFont.FFace, FGlyphData) <> TT_Err_Ok then
|
if not AFont.CheckFace or (TT_New_Glyph(AFont.FFace, FGlyphData) <> TT_Err_Ok) then
|
||||||
raise Exception.Create('Cannot create empty glyph');
|
raise Exception.Create('Cannot create empty glyph');
|
||||||
FLoaded := AFont.LoadGlyphInto(FGlyphData, AIndex);
|
FLoaded := AFont.LoadGlyphInto(FGlyphData, AIndex);
|
||||||
FIndex := AIndex;
|
FIndex := AIndex;
|
||||||
@ -772,65 +784,63 @@ end;
|
|||||||
|
|
||||||
{ TFreeTypeFont }
|
{ TFreeTypeFont }
|
||||||
|
|
||||||
procedure TFreeTypeFont.UpdateFace(const AName: String);
|
procedure TFreeTypeFont.LoadFace;
|
||||||
var errorNum: TT_Error;
|
var errorNum: TT_Error;
|
||||||
PrevDPI: integer;
|
|
||||||
familyItem: TCustomFamilyCollectionItem;
|
familyItem: TCustomFamilyCollectionItem;
|
||||||
fontItem: TCustomFontCollectionItem;
|
fontItem: TCustomFontCollectionItem;
|
||||||
begin
|
begin
|
||||||
PrevDPI := DPI;
|
|
||||||
DiscardFace;
|
DiscardFace;
|
||||||
|
|
||||||
if FStream <> nil then
|
if FStream <> nil then
|
||||||
begin
|
begin
|
||||||
errorNum := TT_Open_Face(FStream,False,FFace);
|
errorNum := TT_Open_Face(FStream,False,FFace);
|
||||||
if errorNum <> TT_Err_Ok then
|
if errorNum <> TT_Err_Ok then
|
||||||
raise exception.Create('Cannot open font (TT_Error ' + intToStr(errorNum)+') <Stream>');
|
raise exception.Create('Cannot open font (TT_Error ' + intToStr(errorNum)+') <Stream>');
|
||||||
end else
|
end else
|
||||||
if (Pos(PathDelim, AName) <> 0) or (Collection = nil) or (Collection.FontFileCount = 0) then
|
|
||||||
begin
|
begin
|
||||||
if AName = '' then exit;
|
if Pos(PathDelim, FName) <> 0 then
|
||||||
|
begin
|
||||||
errorNum := TT_Open_Face(AName,FFace);
|
errorNum := TT_Open_Face(FName,FFace);
|
||||||
if errorNum <> TT_Err_Ok then
|
if errorNum <> TT_Err_Ok then
|
||||||
raise exception.Create('Cannot open font (TT_Error ' + intToStr(errorNum)+') "'+AName+'"');
|
raise exception.Create('Cannot open font (TT_Error ' + intToStr(errorNum)+') "'+FName+'"');
|
||||||
end else
|
end else
|
||||||
begin
|
begin
|
||||||
familyItem := Collection.Family[AName];
|
familyItem := Collection.Family[FName];
|
||||||
if familyItem = nil then
|
if familyItem = nil then
|
||||||
raise exception.Create('Font family not found');
|
raise exception.Create('Font family not found ("'+FName+'")');
|
||||||
fontItem := familyItem.GetFont(FStyleStr);
|
fontItem := familyItem.GetFont(FStyleStr);
|
||||||
if fontItem = nil then
|
if fontItem = nil then
|
||||||
raise exception.Create('Font style not found');
|
raise exception.Create('Font style not found ("'+FStyleStr+'")');
|
||||||
FFace := fontItem.QueryFace(@OnDestroyFontItem);
|
FFace := fontItem.QueryFace(@OnDestroyFontItem);
|
||||||
FFaceItem := fontItem;
|
FFaceItem := fontItem;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
FFaceLoaded:= true;
|
FFaceLoaded:= true;
|
||||||
FName:=AName;
|
|
||||||
UpdateInstance;
|
UpdateInstance;
|
||||||
DPI := PrevDPI;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFreeTypeFont.SetName(const AValue: String);
|
procedure TFreeTypeFont.SetName(const AValue: String);
|
||||||
begin
|
begin
|
||||||
DiscardStream;
|
DiscardStream;
|
||||||
if FName=AValue then exit;
|
if FName=AValue then exit;
|
||||||
UpdateFace(AValue);
|
FName := AValue;
|
||||||
|
FaceChanged;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{$hints off}
|
{$hints off}
|
||||||
function TFreeTypeFont.GetDPI: integer;
|
function TFreeTypeFont.GetDPI: integer;
|
||||||
var metrics: TT_Instance_Metrics;
|
var metrics: TT_Instance_Metrics;
|
||||||
begin
|
begin
|
||||||
if not FInstanceCreated then
|
if not CheckInstance then
|
||||||
result := 96
|
begin
|
||||||
|
result := FDPI;
|
||||||
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
if TT_Get_Instance_Metrics(FInstance,metrics) = TT_Err_Ok then
|
if TT_Get_Instance_Metrics(FInstance,metrics) = TT_Err_Ok then
|
||||||
result := metrics.y_resolution
|
result := metrics.y_resolution
|
||||||
else
|
else
|
||||||
result := 96;
|
result := FDPI;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
{$hints on}
|
{$hints on}
|
||||||
@ -898,7 +908,7 @@ function TFreeTypeFont.GetGlyph(Index: integer): TFreeTypeGlyph;
|
|||||||
var node: TAvgLvlTreeNode;
|
var node: TAvgLvlTreeNode;
|
||||||
lGlyph: TFreeTypeGlyph;
|
lGlyph: TFreeTypeGlyph;
|
||||||
begin
|
begin
|
||||||
if not FInstanceCreated then
|
if not CheckInstance then
|
||||||
begin
|
begin
|
||||||
result := nil;
|
result := nil;
|
||||||
exit;
|
exit;
|
||||||
@ -917,7 +927,7 @@ end;
|
|||||||
function TFreeTypeFont.GetGlyphCount: integer;
|
function TFreeTypeFont.GetGlyphCount: integer;
|
||||||
var prop : TT_Face_Properties;
|
var prop : TT_Face_Properties;
|
||||||
begin
|
begin
|
||||||
if not FFaceLoaded then
|
if not CheckFace then
|
||||||
result := 0
|
result := 0
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
@ -955,6 +965,7 @@ end;
|
|||||||
procedure TFreeTypeFont.OnDestroyFontItem;
|
procedure TFreeTypeFont.OnDestroyFontItem;
|
||||||
begin
|
begin
|
||||||
DiscardFace;
|
DiscardFace;
|
||||||
|
FaceChanged;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFreeTypeFont.GetPixelSize: single;
|
function TFreeTypeFont.GetPixelSize: single;
|
||||||
@ -986,6 +997,8 @@ end;
|
|||||||
|
|
||||||
procedure TFreeTypeFont.SetDPI(const AValue: integer);
|
procedure TFreeTypeFont.SetDPI(const AValue: integer);
|
||||||
begin
|
begin
|
||||||
|
if FDPI = AValue then exit;
|
||||||
|
FDPI := AValue;
|
||||||
if FInstanceCreated then
|
if FInstanceCreated then
|
||||||
begin
|
begin
|
||||||
TT_Set_Instance_Resolutions(FInstance, AValue,AValue);
|
TT_Set_Instance_Resolutions(FInstance, AValue,AValue);
|
||||||
@ -1033,7 +1046,7 @@ begin
|
|||||||
AValue := Trim(AValue);
|
AValue := Trim(AValue);
|
||||||
if FStyleStr=AValue then Exit;
|
if FStyleStr=AValue then Exit;
|
||||||
FStyleStr:=AValue;
|
FStyleStr:=AValue;
|
||||||
UpdateFace(FName);
|
FaceChanged;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFreeTypeFont.DiscardFace;
|
procedure TFreeTypeFont.DiscardFace;
|
||||||
@ -1077,8 +1090,7 @@ end;
|
|||||||
|
|
||||||
procedure TFreeTypeFont.SetPixelSize(const AValue: single);
|
procedure TFreeTypeFont.SetPixelSize(const AValue: single);
|
||||||
begin
|
begin
|
||||||
if FInstanceCreated then
|
SizeInPoints := AValue*72/DPI;
|
||||||
SizeInPoints := AValue*72/DPI;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFreeTypeFont.SetPointSize(AValue: single);
|
procedure TFreeTypeFont.SetPointSize(AValue: single);
|
||||||
@ -1086,14 +1098,13 @@ begin
|
|||||||
if AValue < FreeTypeMinPointSize then AValue := FreeTypeMinPointSize;
|
if AValue < FreeTypeMinPointSize then AValue := FreeTypeMinPointSize;
|
||||||
if FPointSize=AValue then exit;
|
if FPointSize=AValue then exit;
|
||||||
FPointSize:=AValue;
|
FPointSize:=AValue;
|
||||||
if FInstanceCreated then
|
UpdateSizeInPoints;
|
||||||
UpdateSizeInPoints;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFreeTypeFont.LoadGlyphInto(_glyph: TT_Glyph; glyph_index: Word): boolean;
|
function TFreeTypeFont.LoadGlyphInto(_glyph: TT_Glyph; glyph_index: Word): boolean;
|
||||||
var flags: integer;
|
var flags: integer;
|
||||||
begin
|
begin
|
||||||
if not FInstanceCreated then
|
if not CheckInstance then
|
||||||
raise Exception.Create('No font instance');
|
raise Exception.Create('No font instance');
|
||||||
flags := TT_Load_Scale_Glyph;
|
flags := TT_Load_Scale_Glyph;
|
||||||
if FHinted then flags := flags or TT_Load_Hint_Glyph;
|
if FHinted then flags := flags or TT_Load_Hint_Glyph;
|
||||||
@ -1105,8 +1116,7 @@ begin
|
|||||||
if FWidthFactor=AValue then exit;
|
if FWidthFactor=AValue then exit;
|
||||||
FWidthFactor:=AValue;
|
FWidthFactor:=AValue;
|
||||||
FGlyphTable.FreeAndClear;
|
FGlyphTable.FreeAndClear;
|
||||||
if FInstanceCreated then
|
UpdateSizeInPoints;
|
||||||
UpdateSizeInPoints;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFreeTypeFont.UpdateInstance;
|
procedure TFreeTypeFont.UpdateInstance;
|
||||||
@ -1119,6 +1129,8 @@ begin
|
|||||||
if errorNum = TT_Err_Ok then
|
if errorNum = TT_Err_Ok then
|
||||||
begin
|
begin
|
||||||
FInstanceCreated := true;
|
FInstanceCreated := true;
|
||||||
|
TT_Set_Instance_Resolutions(FInstance, FDPI,FDPI);
|
||||||
|
UpdateSizeInPoints;
|
||||||
UpdateMetrics;
|
UpdateMetrics;
|
||||||
UpdateCharmap;
|
UpdateCharmap;
|
||||||
end else
|
end else
|
||||||
@ -1144,7 +1156,7 @@ end;
|
|||||||
procedure TFreeTypeFont.UpdateMetrics;
|
procedure TFreeTypeFont.UpdateMetrics;
|
||||||
var prop: TT_Face_Properties;
|
var prop: TT_Face_Properties;
|
||||||
begin
|
begin
|
||||||
if FFaceLoaded then
|
if CheckFace then
|
||||||
begin
|
begin
|
||||||
TT_Get_Face_Properties(FFace,prop);
|
TT_Get_Face_Properties(FFace,prop);
|
||||||
FAscentValue := prop.horizontal^.ascender;
|
FAscentValue := prop.horizontal^.ascender;
|
||||||
@ -1198,7 +1210,7 @@ end;
|
|||||||
|
|
||||||
procedure TFreeTypeFont.UpdateCharmap;
|
procedure TFreeTypeFont.UpdateCharmap;
|
||||||
var i,n: integer;
|
var i,n: integer;
|
||||||
platform,encoding: integer;
|
lPlatform,encoding: integer;
|
||||||
begin
|
begin
|
||||||
if FCharmapOk then exit;
|
if FCharmapOk then exit;
|
||||||
if not FFaceLoaded then
|
if not FFaceLoaded then
|
||||||
@ -1208,15 +1220,15 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
n := TT_Get_CharMap_Count(FFace);
|
n := TT_Get_CharMap_Count(FFace);
|
||||||
platform := 0;
|
lPlatform := 0;
|
||||||
encoding := 0;
|
encoding := 0;
|
||||||
|
|
||||||
//MS Unicode
|
//MS Unicode
|
||||||
for i := 0 to n-1 do
|
for i := 0 to n-1 do
|
||||||
begin
|
begin
|
||||||
if TT_Get_CharMap_ID(FFace, i, platform, encoding) = TT_Err_Ok then
|
if TT_Get_CharMap_ID(FFace, i, lPlatform, encoding) = TT_Err_Ok then
|
||||||
begin
|
begin
|
||||||
if (platform = 3) and (encoding = 1) then
|
if (lPlatform = 3) and (encoding = 1) then
|
||||||
if TT_Get_CharMap(FFace, i, FCharMap) = TT_Err_Ok then
|
if TT_Get_CharMap(FFace, i, FCharMap) = TT_Err_Ok then
|
||||||
begin
|
begin
|
||||||
FCharmapOk := true;
|
FCharmapOk := true;
|
||||||
@ -1228,9 +1240,9 @@ begin
|
|||||||
//Apple Unicode
|
//Apple Unicode
|
||||||
for i := 0 to n-1 do
|
for i := 0 to n-1 do
|
||||||
begin
|
begin
|
||||||
if TT_Get_CharMap_ID(FFace, i, platform, encoding) = TT_Err_Ok then
|
if TT_Get_CharMap_ID(FFace, i, lPlatform, encoding) = TT_Err_Ok then
|
||||||
begin
|
begin
|
||||||
if (platform = 0) then
|
if (lPlatform = 0) then
|
||||||
if TT_Get_CharMap(FFace, i, FCharMap) = TT_Err_Ok then
|
if TT_Get_CharMap(FFace, i, FCharMap) = TT_Err_Ok then
|
||||||
begin
|
begin
|
||||||
FCharmapOk := true;
|
FCharmapOk := true;
|
||||||
@ -1242,9 +1254,9 @@ begin
|
|||||||
//ISO Unicode
|
//ISO Unicode
|
||||||
for i := 0 to n-1 do
|
for i := 0 to n-1 do
|
||||||
begin
|
begin
|
||||||
if TT_Get_CharMap_ID(FFace, i, platform, encoding) = TT_Err_Ok then
|
if TT_Get_CharMap_ID(FFace, i, lPlatform, encoding) = TT_Err_Ok then
|
||||||
begin
|
begin
|
||||||
if (platform = 2) and (encoding = 1) then
|
if (lPlatform = 2) and (encoding = 1) then
|
||||||
if TT_Get_CharMap(FFace, i, FCharMap) = TT_Err_Ok then
|
if TT_Get_CharMap(FFace, i, FCharMap) = TT_Err_Ok then
|
||||||
begin
|
begin
|
||||||
FCharmapOk := true;
|
FCharmapOk := true;
|
||||||
@ -1314,6 +1326,15 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TFreeTypeFont.FaceChanged;
|
||||||
|
begin
|
||||||
|
if not FFaceChanged then
|
||||||
|
begin
|
||||||
|
FFaceChanged := true;
|
||||||
|
DiscardFace;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TFreeTypeFont.Create;
|
constructor TFreeTypeFont.Create;
|
||||||
begin
|
begin
|
||||||
EnsureFreeTypeInitialized;
|
EnsureFreeTypeInitialized;
|
||||||
@ -1322,6 +1343,7 @@ begin
|
|||||||
FInstanceCreated := false;
|
FInstanceCreated := false;
|
||||||
FCharmapOk := false;
|
FCharmapOk := false;
|
||||||
FPointSize := 10;
|
FPointSize := 10;
|
||||||
|
FDPI := 96;
|
||||||
FGlyphTable := TAvgLvlTree.Create;
|
FGlyphTable := TAvgLvlTree.Create;
|
||||||
FHinted := true;
|
FHinted := true;
|
||||||
FWidthFactor := 1;
|
FWidthFactor := 1;
|
||||||
@ -1329,8 +1351,7 @@ begin
|
|||||||
FStyleStr:= 'Regular';
|
FStyleStr:= 'Regular';
|
||||||
SmallLinePadding:= true;
|
SmallLinePadding:= true;
|
||||||
Quality := grqHighQuality;
|
Quality := grqHighQuality;
|
||||||
|
FFaceChanged := true;
|
||||||
UpdateFace('');
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TFreeTypeFont.Destroy;
|
destructor TFreeTypeFont.Destroy;
|
||||||
@ -1347,7 +1368,7 @@ begin
|
|||||||
DiscardStream;
|
DiscardStream;
|
||||||
FStream := AStream;
|
FStream := AStream;
|
||||||
FOwnedStream:= AStreamOwner;
|
FOwnedStream:= AStreamOwner;
|
||||||
UpdateFace('');
|
FaceChanged;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFreeTypeFont.RenderText(AText: string; x, y: single; ARect: TRect;
|
procedure TFreeTypeFont.RenderText(AText: string; x, y: single; ARect: TRect;
|
||||||
@ -1358,7 +1379,7 @@ var
|
|||||||
idx: integer;
|
idx: integer;
|
||||||
g: TFreeTypeGlyph;
|
g: TFreeTypeGlyph;
|
||||||
begin
|
begin
|
||||||
if not FInstanceCreated then exit;
|
if not CheckInstance then exit;
|
||||||
if AText = '' then exit;
|
if AText = '' then exit;
|
||||||
idx := pos(LineEnding,AText);
|
idx := pos(LineEnding,AText);
|
||||||
while idx <> 0 do
|
while idx <> 0 do
|
||||||
@ -1394,13 +1415,13 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFreeTypeFont.SetNameAndStyle(AName: String; AStyle: string);
|
procedure TFreeTypeFont.SetNameAndStyle(AName: string; AStyle: string);
|
||||||
begin
|
begin
|
||||||
AStyle := Trim(AStyle);
|
AStyle := Trim(AStyle);
|
||||||
if (AName = FName) and (AStyle = FStyleStr) then exit;
|
if (AName = FName) and (AStyle = FStyleStr) then exit;
|
||||||
FName := AName;
|
FName := AName;
|
||||||
FStyleStr := AStyle;
|
FStyleStr := AStyle;
|
||||||
UpdateFace(FName);
|
FaceChanged;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFreeTypeFont.SetNameAndStyle(AName: string; AStyle: TFreeTypeStyles);
|
procedure TFreeTypeFont.SetNameAndStyle(AName: string; AStyle: TFreeTypeStyles);
|
||||||
@ -1421,7 +1442,7 @@ var
|
|||||||
g: TFreeTypeGlyph;
|
g: TFreeTypeGlyph;
|
||||||
begin
|
begin
|
||||||
result := 0;
|
result := 0;
|
||||||
if not FInstanceCreated then exit;
|
if not CheckInstance then exit;
|
||||||
if AText = '' then exit;
|
if AText = '' then exit;
|
||||||
|
|
||||||
maxWidth := 0;
|
maxWidth := 0;
|
||||||
@ -1560,7 +1581,7 @@ var
|
|||||||
g: TFreeTypeGlyph;
|
g: TFreeTypeGlyph;
|
||||||
begin
|
begin
|
||||||
result := nil;
|
result := nil;
|
||||||
if not FInstanceCreated then exit;
|
if not CheckInstance then exit;
|
||||||
if AText = '' then exit;
|
if AText = '' then exit;
|
||||||
StrLineEnding := LineEnding;
|
StrLineEnding := LineEnding;
|
||||||
pstr := @AText[1];
|
pstr := @AText[1];
|
||||||
@ -1683,7 +1704,7 @@ var i,j: integer;
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
setlength(FNamesArray, maxNameIndex+1);
|
setlength(FNamesArray, maxNameIndex+1);
|
||||||
if FFaceLoaded then
|
if CheckFace then
|
||||||
begin
|
begin
|
||||||
for i := 0 to TT_Get_Name_Count(FFace)-1 do
|
for i := 0 to TT_Get_Name_Count(FFace)-1 do
|
||||||
begin
|
begin
|
||||||
@ -1725,6 +1746,21 @@ begin
|
|||||||
result := FCollection;
|
result := FCollection;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TFreeTypeFont.CheckFace: boolean;
|
||||||
|
begin
|
||||||
|
if FFaceChanged then
|
||||||
|
begin
|
||||||
|
FFaceChanged:= false;
|
||||||
|
LoadFace;
|
||||||
|
end;
|
||||||
|
result := FFaceLoaded;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFreeTypeFont.CheckInstance: boolean;
|
||||||
|
begin
|
||||||
|
result := CheckFace and FInstanceCreated;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TFreeTypeGrayscaleMap }
|
{ TFreeTypeGrayscaleMap }
|
||||||
|
|
||||||
procedure TFreeTypeGrayscaleMap.Init(AWidth, AHeight: integer);
|
procedure TFreeTypeGrayscaleMap.Init(AWidth, AHeight: integer);
|
||||||
|
|||||||
@ -65,13 +65,16 @@ type
|
|||||||
function GetFontIndexByStyles(AStyles: string): integer;
|
function GetFontIndexByStyles(AStyles: string): integer;
|
||||||
function GetStyle(AIndex: integer): string; override;
|
function GetStyle(AIndex: integer): string; override;
|
||||||
procedure AddStyle(AName: string);
|
procedure AddStyle(AName: string);
|
||||||
|
function RemoveStyle(AName: string): boolean;
|
||||||
function GetStyles: string; override;
|
function GetStyles: string; override;
|
||||||
function GetFamilyName: string; override;
|
function GetFamilyName: string; override;
|
||||||
function GetFontCount: integer; override;
|
function GetFontCount: integer; override;
|
||||||
function GetStyleCount: integer; override;
|
function GetStyleCount: integer; override;
|
||||||
|
procedure RebuildStyleList(out ADuplicates: boolean);
|
||||||
public
|
public
|
||||||
constructor Create(AName: string);
|
constructor Create(AName: string);
|
||||||
procedure AddFont(AFontItem: TFontCollectionItem);
|
procedure AddFont(AFontItem: TFontCollectionItem);
|
||||||
|
function RemoveFont(AFontItem: TCustomFontCollectionItem): boolean;
|
||||||
function GetFont(const AStyles: array of string; NeedAllStyles: boolean = false; NoMoreStyle: boolean = false): TCustomFontCollectionItem; override;
|
function GetFont(const AStyles: array of string; NeedAllStyles: boolean = false; NoMoreStyle: boolean = false): TCustomFontCollectionItem; override;
|
||||||
function GetFont(AStyle: string; NeedAllStyles: boolean = false; NoMoreStyle: boolean = false): TCustomFontCollectionItem; override;
|
function GetFont(AStyle: string; NeedAllStyles: boolean = false; NoMoreStyle: boolean = false): TCustomFontCollectionItem; override;
|
||||||
function GetFontIndex(const AStyles: array of string; NeedAllStyles: boolean = false; NoMoreStyle: boolean = false): integer; override;
|
function GetFontIndex(const AStyles: array of string; NeedAllStyles: boolean = false; NoMoreStyle: boolean = false): integer; override;
|
||||||
@ -101,13 +104,15 @@ type
|
|||||||
function GetFamily(AName: string): TCustomFamilyCollectionItem; override;
|
function GetFamily(AName: string): TCustomFamilyCollectionItem; override;
|
||||||
function GetFamilyCount: integer; override;
|
function GetFamilyCount: integer; override;
|
||||||
function GetFontCount: integer; override;
|
function GetFontCount: integer; override;
|
||||||
|
function RemoveAndFreeFamily(AFamily: TCustomFamilyCollectionItem): boolean;
|
||||||
public
|
public
|
||||||
constructor Create; override;
|
constructor Create; override;
|
||||||
procedure Clear; override;
|
procedure Clear; override;
|
||||||
procedure BeginUpdate; override;
|
procedure BeginUpdate; override;
|
||||||
procedure AddFolder(AFolder: string); override;
|
procedure AddFolder(AFolder: string); override;
|
||||||
|
procedure RemoveFolder(AFolder: string); override;
|
||||||
function AddFile(AFilename: string): boolean; override;
|
function AddFile(AFilename: string): boolean; override;
|
||||||
|
function RemoveFile(AFilename: string): boolean; override;
|
||||||
function AddStream(AStream: TStream; AOwned: boolean): boolean; override;
|
function AddStream(AStream: TStream; AOwned: boolean): boolean; override;
|
||||||
procedure EndUpdate; override;
|
procedure EndUpdate; override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -457,6 +462,21 @@ begin
|
|||||||
inc(FStyleCount);
|
inc(FStyleCount);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TFamilyCollectionItem.RemoveStyle(AName: string): boolean;
|
||||||
|
var i,j: integer;
|
||||||
|
begin
|
||||||
|
for i := 0 to FStyleCount-1 do
|
||||||
|
if CompareText(FStyles[i],AName)=0 then
|
||||||
|
begin
|
||||||
|
for j := i to FStyleCount-2 do
|
||||||
|
FStyles[j] := FStyles[j+1];
|
||||||
|
dec(FStyleCount);
|
||||||
|
result := true;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
result := false;
|
||||||
|
end;
|
||||||
|
|
||||||
function TFamilyCollectionItem.GetStyles: string;
|
function TFamilyCollectionItem.GetStyles: string;
|
||||||
var i: integer;
|
var i: integer;
|
||||||
begin
|
begin
|
||||||
@ -483,6 +503,31 @@ begin
|
|||||||
result := FStyleCount;
|
result := FStyleCount;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TFamilyCollectionItem.RebuildStyleList(out ADuplicates: boolean);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
j: Integer;
|
||||||
|
begin
|
||||||
|
FStyleCount := 0;
|
||||||
|
ADuplicates := false;
|
||||||
|
for i := 0 to FFontCount-1 do
|
||||||
|
begin
|
||||||
|
FFonts[i].UsePostscriptStyle := true;
|
||||||
|
for j := 0 to FFonts[i].StyleCount -1 do
|
||||||
|
AddStyle(FFonts[i].Style[j]);
|
||||||
|
|
||||||
|
//add regular style if no other style
|
||||||
|
if FFonts[i].StyleCount = 0 then AddStyle('Regular');
|
||||||
|
|
||||||
|
for j := 0 to i-1 do
|
||||||
|
if FFonts[j].Styles = FFonts[i].Styles then
|
||||||
|
begin
|
||||||
|
ADuplicates:= true;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TFamilyCollectionItem.Create(AName: string);
|
constructor TFamilyCollectionItem.Create(AName: string);
|
||||||
begin
|
begin
|
||||||
FFamilyName:= AName;
|
FFamilyName:= AName;
|
||||||
@ -494,15 +539,24 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFamilyCollectionItem.AddFont(AFontItem: TFontCollectionItem);
|
procedure TFamilyCollectionItem.AddFont(AFontItem: TFontCollectionItem);
|
||||||
var i,j: integer;
|
var i: integer;
|
||||||
DuplicateStyle: boolean;
|
DuplicateStyle: boolean;
|
||||||
StyleNumber: integer;
|
StyleNumber: integer;
|
||||||
TempStyles,BaseStyle: string;
|
TempStyles,BaseStyle: string;
|
||||||
begin
|
begin
|
||||||
|
if AFontItem = nil then exit;
|
||||||
|
|
||||||
|
for i := 0 to FFontCount-1 do
|
||||||
|
if FFonts[i] = AFontItem then exit;
|
||||||
|
|
||||||
|
if AFontItem.Family <> nil then
|
||||||
|
raise exception.Create('This font already belongs to another family');
|
||||||
|
|
||||||
if FFontCount = length(FFonts) then
|
if FFontCount = length(FFonts) then
|
||||||
setlength(FFonts, length(FFonts)+4);
|
setlength(FFonts, length(FFonts)+4);
|
||||||
|
|
||||||
FFonts[FFontCount] := AFontItem;
|
FFonts[FFontCount] := AFontItem;
|
||||||
|
AFontItem.Family := self;
|
||||||
inc(FFontCount);
|
inc(FFontCount);
|
||||||
|
|
||||||
if FUsePostscriptStyle then AFontItem.UsePostscriptStyle := true;
|
if FUsePostscriptStyle then AFontItem.UsePostscriptStyle := true;
|
||||||
@ -510,6 +564,9 @@ begin
|
|||||||
for i := 0 to AFontItem.StyleCount -1 do
|
for i := 0 to AFontItem.StyleCount -1 do
|
||||||
AddStyle(AFontItem.Style[i]);
|
AddStyle(AFontItem.Style[i]);
|
||||||
|
|
||||||
|
//add regular style if no other style
|
||||||
|
if AFontItem.StyleCount = 0 then AddStyle('Regular');
|
||||||
|
|
||||||
DuplicateStyle := false;
|
DuplicateStyle := false;
|
||||||
for i := 0 to FFontCount-2 do
|
for i := 0 to FFontCount-2 do
|
||||||
if FFonts[i].Styles = AFontItem.Styles then
|
if FFonts[i].Styles = AFontItem.Styles then
|
||||||
@ -521,21 +578,7 @@ begin
|
|||||||
if DuplicateStyle and not FUsePostscriptStyle then
|
if DuplicateStyle and not FUsePostscriptStyle then
|
||||||
begin //try with postscript styles instead
|
begin //try with postscript styles instead
|
||||||
FUsePostscriptStyle:= true;
|
FUsePostscriptStyle:= true;
|
||||||
FStyleCount := 0;
|
RebuildStyleList(DuplicateStyle);
|
||||||
DuplicateStyle := false;
|
|
||||||
for i := 0 to FFontCount-1 do
|
|
||||||
begin
|
|
||||||
FFonts[i].UsePostscriptStyle := true;
|
|
||||||
for j := 0 to FFonts[i].StyleCount -1 do
|
|
||||||
AddStyle(FFonts[i].Style[j]);
|
|
||||||
|
|
||||||
for j := 0 to i-1 do
|
|
||||||
if FFonts[j].Styles = FFonts[i].Styles then
|
|
||||||
begin
|
|
||||||
DuplicateStyle:= true;
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if DuplicateStyle then
|
if DuplicateStyle then
|
||||||
@ -558,8 +601,6 @@ begin
|
|||||||
until not DuplicateStyle;
|
until not DuplicateStyle;
|
||||||
AFontItem.Information[ftiStyle] := TempStyles;
|
AFontItem.Information[ftiStyle] := TempStyles;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if AFontItem.StyleCount = 0 then AddStyle('Regular');
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFamilyCollectionItem.GetFont(const AStyles: array of string;
|
function TFamilyCollectionItem.GetFont(const AStyles: array of string;
|
||||||
@ -627,6 +668,25 @@ begin
|
|||||||
result := GetFontIndex(StylesToArray(AStyle),NeedAllStyles,NoMoreStyle);
|
result := GetFontIndex(StylesToArray(AStyle),NeedAllStyles,NoMoreStyle);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TFamilyCollectionItem.RemoveFont(AFontItem: TCustomFontCollectionItem
|
||||||
|
): boolean;
|
||||||
|
var i,j: integer;
|
||||||
|
dummy: boolean;
|
||||||
|
begin
|
||||||
|
for i := 0 to FFontCount-1 do
|
||||||
|
if FFonts[i] = AFontItem then
|
||||||
|
begin
|
||||||
|
for j := i to FFontCount-2 do
|
||||||
|
FFonts[j] := FFonts[j+1];
|
||||||
|
dec(FFontCount);
|
||||||
|
AFontItem.Family := nil;
|
||||||
|
RebuildStyleList(dummy);
|
||||||
|
result := true;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
result := false;
|
||||||
|
end;
|
||||||
|
|
||||||
function TFamilyCollectionItem.GetFont(AStyle: string; NeedAllStyles: boolean; NoMoreStyle: boolean): TCustomFontCollectionItem;
|
function TFamilyCollectionItem.GetFont(AStyle: string; NeedAllStyles: boolean; NoMoreStyle: boolean): TCustomFontCollectionItem;
|
||||||
begin
|
begin
|
||||||
result := GetFontByStyles(AStyle); //exact match
|
result := GetFontByStyles(AStyle); //exact match
|
||||||
@ -653,6 +713,17 @@ begin
|
|||||||
result := FFontList.Count;
|
result := FFontList.Count;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TFreeTypeFontCollection.RemoveAndFreeFamily(
|
||||||
|
AFamily: TCustomFamilyCollectionItem): boolean;
|
||||||
|
begin
|
||||||
|
if FFamilyList.Remove(Pointer(AFamily)) then
|
||||||
|
begin
|
||||||
|
result := true;
|
||||||
|
AFamily.Free;
|
||||||
|
end else
|
||||||
|
result := false;
|
||||||
|
end;
|
||||||
|
|
||||||
function TFreeTypeFontCollection.GetFamilyCount: integer;
|
function TFreeTypeFontCollection.GetFamilyCount: integer;
|
||||||
begin
|
begin
|
||||||
result := FFamilyList.Count;
|
result := FFamilyList.Count;
|
||||||
@ -751,6 +822,7 @@ end;
|
|||||||
function TFreeTypeFontCollection.GetFont(AFileName: string
|
function TFreeTypeFontCollection.GetFont(AFileName: string
|
||||||
): TCustomFontCollectionItem;
|
): TCustomFontCollectionItem;
|
||||||
begin
|
begin
|
||||||
|
AFilename:= ExpandFileName(AFilename);
|
||||||
result := FindFont(AFilename);
|
result := FindFont(AFilename);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -780,6 +852,7 @@ var sr: TSearchRec;
|
|||||||
files: TStringList;
|
files: TStringList;
|
||||||
i: integer;
|
i: integer;
|
||||||
begin
|
begin
|
||||||
|
AFolder := ExpandFileName(AFolder);
|
||||||
if (length(AFolder) <> 0) and (AFolder[length(AFolder)] <> PathDelim) then
|
if (length(AFolder) <> 0) and (AFolder[length(AFolder)] <> PathDelim) then
|
||||||
AFolder += PathDelim;
|
AFolder += PathDelim;
|
||||||
|
|
||||||
@ -801,12 +874,39 @@ begin
|
|||||||
files.Free;
|
files.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TFreeTypeFontCollection.RemoveFolder(AFolder: string);
|
||||||
|
var toBeDeleted: TStringList;
|
||||||
|
enumerator: TAvgLvlTreeNodeEnumerator;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
AFolder := ExpandFileName(AFolder);
|
||||||
|
if (length(AFolder) <> 0) and (AFolder[length(AFolder)] <> PathDelim) then
|
||||||
|
AFolder += PathDelim;
|
||||||
|
|
||||||
|
toBeDeleted := TStringList.Create;
|
||||||
|
enumerator := FFontList.GetEnumerator;
|
||||||
|
while enumerator.MoveNext do
|
||||||
|
begin
|
||||||
|
with TCustomFontCollectionItem(enumerator.Current.Data) do
|
||||||
|
begin
|
||||||
|
if copy(Filename, 1, length(AFolder)) = AFolder then
|
||||||
|
toBeDeleted.Add(Filename);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
enumerator.Free;
|
||||||
|
|
||||||
|
for i := 0 to toBeDeleted.Count-1 do
|
||||||
|
RemoveFile(toBeDeleted[i]);
|
||||||
|
toBeDeleted.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
function TFreeTypeFontCollection.AddFile(AFilename: string): boolean;
|
function TFreeTypeFontCollection.AddFile(AFilename: string): boolean;
|
||||||
var info: TFreeTypeInformation;
|
var info: TFreeTypeInformation;
|
||||||
fName: string;
|
fName: string;
|
||||||
item: TFontCollectionItem;
|
item: TFontCollectionItem;
|
||||||
f: TFamilyCollectionItem;
|
f: TFamilyCollectionItem;
|
||||||
begin
|
begin
|
||||||
|
AFilename:= ExpandFileName(AFilename);
|
||||||
result := false;
|
result := false;
|
||||||
BeginUpdate;
|
BeginUpdate;
|
||||||
try
|
try
|
||||||
@ -831,6 +931,27 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TFreeTypeFontCollection.RemoveFile(AFilename: string): boolean;
|
||||||
|
var fontItem : TCustomFontCollectionItem;
|
||||||
|
f: TFamilyCollectionItem;
|
||||||
|
begin
|
||||||
|
AFilename:= ExpandFileName(AFilename);
|
||||||
|
fontItem := GetFont(AFilename);
|
||||||
|
if (fontItem = nil) or not (fontItem.Family is TFamilyCollectionItem) then
|
||||||
|
begin
|
||||||
|
result := false;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
FFontList.Remove(Pointer(fontItem));
|
||||||
|
f := fontItem.Family as TFamilyCollectionItem;
|
||||||
|
result := f.RemoveFont(fontItem);
|
||||||
|
if result then
|
||||||
|
begin
|
||||||
|
if f.FontCount = 0 then
|
||||||
|
RemoveAndFreeFamily(f);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TFreeTypeFontCollection.AddStream(AStream: TStream; AOwned: boolean): boolean;
|
function TFreeTypeFontCollection.AddStream(AStream: TStream; AOwned: boolean): boolean;
|
||||||
var info: TFreeTypeInformation;
|
var info: TFreeTypeInformation;
|
||||||
fName: string;
|
fName: string;
|
||||||
|
|||||||
@ -246,7 +246,7 @@ const
|
|||||||
try
|
try
|
||||||
ftstream := TFreeTypeStream.Create(name);
|
ftstream := TFreeTypeStream.Create(name);
|
||||||
if ftstream.Activate then
|
if ftstream.Activate then
|
||||||
raise exception.Create('Cannot activate');
|
raise exception.Create('Cannot activate stream, file may not exist');
|
||||||
except
|
except
|
||||||
on ex: Exception do
|
on ex: Exception do
|
||||||
begin
|
begin
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user