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