From 09eff40893cd55dcfced7aecb113cade28c0b533 Mon Sep 17 00:00:00 2001 From: juha Date: Tue, 19 May 2015 16:13:36 +0000 Subject: [PATCH] LazUtils, EasyLazFreetype: Drawing symbol fonts and individual glyphs with their index. Issue #28078, patch from Johann. git-svn-id: trunk@49105 - --- components/lazutils/easylazfreetype.pas | 116 +++++++++++++++++++++--- 1 file changed, 101 insertions(+), 15 deletions(-) diff --git a/components/lazutils/easylazfreetype.pas b/components/lazutils/easylazfreetype.pas index c48c2711d1..0be6a7e32f 100644 --- a/components/lazutils/easylazfreetype.pas +++ b/components/lazutils/easylazfreetype.pas @@ -191,6 +191,8 @@ type procedure DrawText(AText: string; AFont: TFreeTypeRenderableFont; x,y: single; AColor: TFPColor; AAlign: TFreeTypeAlignments); virtual; overload; procedure DrawTextWordBreak(AText: string; AFont: TFreeTypeRenderableFont; x, y, AMaxWidth: Single; AColor: TFPColor; AAlign: TFreeTypeAlignments); procedure DrawTextRect(AText: string; AFont: TFreeTypeRenderableFont; X1,Y1,X2,Y2: Single; AColor: TFPColor; AAlign: TFreeTypeAlignments); + procedure DrawGlyph(AGlyph: integer; AFont: TFreeTypeRenderableFont; x,y: single; AColor: TFPColor); virtual; abstract; overload; + procedure DrawGlyph(AGlyph: integer; AFont: TFreeTypeRenderableFont; x,y: single; AColor: TFPColor; AAlign: TFreeTypeAlignments); virtual; overload; end; {********************************* Font implementation **********************************} @@ -212,7 +214,7 @@ type FNamesArray: array of string; FCollection: TCustomFreeTypeFontCollection; function FindGlyphNode(Index: Integer): TAvgLvlTreeNode; - function GetCharIndex(AChar: integer): integer; + function GetCharIndex(AUnicodeChar: integer): integer; function GetDPI: integer; function GetFamily: string; function GetFreeTypeStyles: TFreeTypeStyles; @@ -249,7 +251,7 @@ type FInstanceCreated : boolean; FGlyphTable: TAvgLvlTree; FCharMap: TT_CharMap; - FCharmapOk: boolean; + FCharmapOk, FCharmapSymbol: boolean; FAscentValue, FDescentValue, FLineGapValue, FLargeLineGapValue, FCapHeight: single; procedure FaceChanged; function GetClearType: boolean; override; @@ -273,11 +275,13 @@ type destructor Destroy; override; procedure AccessFromStream(AStream: TStream; AStreamOwner: boolean); procedure RenderText(AText: string; x,y: single; ARect: TRect; OnRender : TDirectRenderingFunction); override; + procedure RenderGlyph(AGlyph: Integer; x,y: single; ARect: TRect; OnRender : TDirectRenderingFunction); procedure SetNameAndStyle(AName: string; AStyle: string); overload; procedure SetNameAndStyle(AName: string; AStyle: TFreeTypeStyles); overload; function TextWidth(AText: string): single; override; function TextHeight(AText: string): single; override; - function CharWidthFromUnicode(AUnicode: integer): single; override; + function CharWidthFromUnicode(AUnicodeChar: integer): single; override; + function CharWidthFromGlyph(AGlyph: integer): single; function CharsWidth(AText: string): ArrayOfSingle; function CharsPosition(AText: string): ArrayOfCharPosition; overload; function CharsPosition(AText: string; AAlign: TFreeTypeAlignments): ArrayOfCharPosition; overload; @@ -288,7 +292,7 @@ type property CapHeight: single read GetCapHeight; property Glyph[Index: integer]: TFreeTypeGlyph read GetGlyph; property GlyphCount: integer read GetGlyphCount; - property CharIndex[AChar: integer]: integer read GetCharIndex; + property CharIndex[AUnicodeChar: integer]: integer read GetCharIndex; property Hinted: boolean read FHinted write SetHinted; property WidthFactor: single read FWidthFactor write SetWidthFactor; property LineFullHeight: single read GetLineFullHeight write SetLineFullHeight; @@ -400,6 +404,14 @@ implementation uses Math; +const + TT_PLATFORM_APPLE_UNICODE = 0; + TT_PLATFORM_MACINTOSH = 1; + TT_PLATFORM_ISO = 2; // deprecated + TT_PLATFORM_MICROSOFT = 3; + TT_PLATFORM_CUSTOM = 4; + TT_PLATFORM_ADOBE = 7; // artificial + function StylesToArray(AStyles: string): ArrayOfString; var StartIndex, EndIndex: integer; @@ -667,6 +679,29 @@ begin DrawTextWordBreak(AText,AFont,X,Y,X2-X1,AColor,AAlign); end; +procedure TFreeTypeDrawer.DrawGlyph(AGlyph: integer; + AFont: TFreeTypeRenderableFont; x, y: single; AColor: TFPColor; + AAlign: TFreeTypeAlignments); +var f: TFreeTypeFont; +begin + if not (AFont is TFreeTypeFont) then exit; + f := TFreeTypeFont(Afont); + + if ftaTop in AAlign then + y += AFont.Ascent + else if ftaVerticalCenter in AALign then + y += AFont.Ascent - AFont.LineFullHeight*0.5 + else if ftaBottom in AAlign then + y += AFont.Ascent - AFont.LineFullHeight; + + if ftaCenter in AAlign then + x -= f.CharWidthFromGlyph(AGlyph)*0.5 + else if ftaRight in AAlign then + x -= f.CharWidthFromGlyph(AGlyph); + + DrawGlyph(AGlyph, AFont, x,y, AColor); +end; + { TFreeTypeGlyph } {$hints off} @@ -878,11 +913,13 @@ end; function TFreeTypeFont.GetAscent: single; begin + CheckInstance; result := FAscentValue*SizeInPixels; end; function TFreeTypeFont.GetCapHeight: single; begin + CheckInstance; result := FCapHeight*SizeInPixels; end; @@ -891,16 +928,22 @@ begin Result:= FClearType; end; -function TFreeTypeFont.GetCharIndex(AChar: integer): integer; +function TFreeTypeFont.GetCharIndex(AUnicodeChar: integer): integer; begin if FCharmapOk then - result := TT_Char_Index(FCharMap, AChar) + begin + if FCharmapSymbol then + result := TT_Char_Index(FCharMap, AUnicodeChar or $F000) + else + result := TT_Char_Index(FCharMap, AUnicodeChar); + end else - result := AChar; + result := 0; end; function TFreeTypeFont.GetDescent: single; begin + CheckInstance; result := FDescentValue*SizeInPixels; end; @@ -951,11 +994,13 @@ end; function TFreeTypeFont.GetLineFullHeight: single; begin + CheckInstance; result := (FAscentValue + FDescentValue)*SizeInPixels + GetLineSpacing; end; function TFreeTypeFont.GetLineSpacing: single; begin + CheckInstance; if not SmallLinePadding then result := FLargeLineGapValue*SizeInPixels else @@ -1030,6 +1075,7 @@ end; procedure TFreeTypeFont.SetLineFullHeight(AValue: single); var Ratio: single; begin + CheckInstance; Ratio := FAscentValue + FDescentValue; if not SmallLinePadding then Ratio += FLargeLineGapValue @@ -1205,6 +1251,7 @@ begin FAscentValue := -0.5; FDescentValue := 0.5; FLineGapValue := 0; + FLargeLineGapValue:= 0; end; end; @@ -1220,20 +1267,32 @@ begin end; n := TT_Get_CharMap_Count(FFace); - lPlatform := 0; + lPlatform := -1; encoding := 0; + FCharmapSymbol := false; //MS Unicode for i := 0 to n-1 do begin if TT_Get_CharMap_ID(FFace, i, lPlatform, encoding) = TT_Err_Ok then begin - if (lPlatform = 3) and (encoding = 1) then + if (lPlatform = TT_PLATFORM_MICROSOFT) and (encoding = 1) then + begin if TT_Get_CharMap(FFace, i, FCharMap) = TT_Err_Ok then begin FCharmapOk := true; exit; + end + end else + if (lPlatform = TT_PLATFORM_MICROSOFT) and (encoding = 0) then + begin + if TT_Get_CharMap(FFace, i, FCharMap) = TT_Err_Ok then + begin + FCharmapOk := true; + FCharmapSymbol:= true; + exit; end; + end; end; end; @@ -1242,7 +1301,7 @@ begin begin if TT_Get_CharMap_ID(FFace, i, lPlatform, encoding) = TT_Err_Ok then begin - if (lPlatform = 0) then + if (lPlatform = TT_PLATFORM_APPLE_UNICODE) then if TT_Get_CharMap(FFace, i, FCharMap) = TT_Err_Ok then begin FCharmapOk := true; @@ -1256,7 +1315,7 @@ begin begin if TT_Get_CharMap_ID(FFace, i, lPlatform, encoding) = TT_Err_Ok then begin - if (lPlatform = 2) and (encoding = 1) then + if (lPlatform = TT_PLATFORM_ISO) and (encoding = 1) then if TT_Get_CharMap(FFace, i, FCharMap) = TT_Err_Ok then begin FCharmapOk := true; @@ -1415,6 +1474,23 @@ begin end; end; +procedure TFreeTypeFont.RenderGlyph(AGlyph: Integer; x, y: single; + ARect: TRect; OnRender: TDirectRenderingFunction); +var + g: TFreeTypeGlyph; +begin + if not CheckInstance then exit; + g := Glyph[AGlyph]; + if g <> nil then + with g do + begin + if Hinted then + RenderDirectly(x,round(y),ARect,OnRender,quality,FClearType) + else + RenderDirectly(x,y,ARect,OnRender,quality,FClearType); + end; +end; + procedure TFreeTypeFont.SetNameAndStyle(AName: string; AStyle: string); begin AStyle := Trim(AStyle); @@ -1501,10 +1577,20 @@ begin end; end; -function TFreeTypeFont.CharWidthFromUnicode(AUnicode: integer): single; +function TFreeTypeFont.CharWidthFromUnicode(AUnicodeChar: integer): single; var g: TFreeTypeGlyph; begin - g := Glyph[CharIndex[AUnicode]]; + g := Glyph[CharIndex[AUnicodeChar]]; + if g = nil then result := 0 + else + result := g.Advance; + if FClearType then result /= 3; +end; + +function TFreeTypeFont.CharWidthFromGlyph(AGlyph: integer): single; +var g: TFreeTypeGlyph; +begin + g := Glyph[AGlyph]; if g = nil then result := 0 else result := g.Advance; @@ -1714,12 +1800,12 @@ begin if (nrNameID < 0) or (nrNameID > maxNameIndex) then continue; { check for Microsoft, Unicode, English } - if ((nrPlatformID=3) and (nrEncodingID in [0,1]) and + if ((nrPlatformID=TT_PLATFORM_MICROSOFT) and (nrEncodingID in[0,1]) and ((nrLanguageID=$0409) or (nrLanguageID=$0809) or (nrLanguageID=$0c09) or (nrLanguageID=$1009) or (nrLanguageID=$1409) or (nrLanguageID=$1809))) or { or for Unicode, English } - ((nrPlatformID=0) and + ((nrPlatformID=TT_PLATFORM_APPLE_UNICODE) and (nrLanguageID=0)) then begin value := TT_Get_Name_String(FFace, i);