Changeset 472 for GraphicTest/Packages/bgrabitmap/bgravectorize.pas
- Timestamp:
- Apr 9, 2015, 9:58:36 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
GraphicTest/Packages/bgrabitmap/bgravectorize.pas
r452 r472 5 5 interface 6 6 7 { 8 Font rendering units : BGRAText, BGRATextFX, BGRAVectorize, BGRAFreeType 9 10 This unit provides vectorizers : 11 - VectorizeMonochrome function vectorizes a back'n'white image 12 - TBGRAVectorizedFont allows to vectorize and to load vectorized font and draw them 13 14 TBGRAVectorizedFontRenderer class works like other font renderers, i.e., it can 15 be assigned to the FontRenderer property. You can use it in two different modes : 16 - if you supply a directory, it will look for *.glyphs files in it to load fonts 17 - if you don't supply a directory, fonts will be vectorized from LCL 18 19 Note that unless you want to supply your own glyphs files, you don't need 20 to use explicitely this renderer, because TBGRATextEffectFontRenderer will 21 make use of it if necessary, according to effects parameters used. 22 } 23 7 24 uses 8 Classes, SysUtils, Graphics, BGRABitmapTypes, BGRATypewriter, BGRATransform, BGRACanvas2D; 9 25 Types, Classes, SysUtils, Graphics, BGRABitmapTypes, BGRATypewriter, BGRATransform, BGRACanvas2D, BGRAText; 26 27 //vectorize a monochrome bitmap 10 28 function VectorizeMonochrome(ASource: TBGRACustomBitmap; zoom: single; PixelCenteredCoordinates: boolean): ArrayOfTPointF; 11 29 12 30 type 31 TBGRAVectorizedFont = class; 32 33 //this is the class to assign to FontRenderer property of TBGRABitmap 34 { TBGRAVectorizedFontRenderer } 35 36 TBGRAVectorizedFontRenderer = class(TBGRACustomFontRenderer) 37 protected 38 FVectorizedFontArray: array of record 39 FontName: string; 40 FontStyle: TFontStyles; 41 VectorizedFont: TBGRAVectorizedFont; 42 end; 43 FVectorizedFont: TBGRAVectorizedFont; 44 FCanvas2D: TBGRACanvas2D; 45 FDirectoryUTF8: string; 46 function OutlineActuallyVisible: boolean; 47 procedure UpdateFont; 48 function GetCanvas2D(ASurface: TBGRACustomBitmap): TBGRACanvas2D; 49 procedure InternalTextRect(ADest: TBGRACustomBitmap; ARect: TRect; x, y: integer; sUTF8: string; style: TTextStyle; c: TBGRAPixel; texture: IBGRAScanner); 50 procedure Init; 51 public 52 MaxFontResolution: integer; 53 54 OutlineVisible: boolean; 55 OutlineWidth: single; 56 OutlineColor: TBGRAPixel; 57 OutlineTexture: IBGRAScanner; 58 OuterOutlineOnly: boolean; 59 60 ShadowVisible: boolean; 61 ShadowColor: TBGRAPixel; 62 ShadowRadius: integer; 63 ShadowOffset: TPoint; 64 65 constructor Create; 66 constructor Create(ADirectoryUTF8: string); 67 function GetFontPixelMetric: TFontPixelMetric; override; 68 procedure TextOutAngle(ADest: TBGRACustomBitmap; x, y: single; orientation: integer; s: string; c: TBGRAPixel; align: TAlignment); override; 69 procedure TextOutAngle(ADest: TBGRACustomBitmap; x, y: single; orientation: integer; s: string; texture: IBGRAScanner; align: TAlignment); override; 70 procedure TextOut(ADest: TBGRACustomBitmap; x, y: single; s: string; texture: IBGRAScanner; align: TAlignment); override; 71 procedure TextOut(ADest: TBGRACustomBitmap; x, y: single; s: string; c: TBGRAPixel; align: TAlignment); override; 72 procedure TextRect(ADest: TBGRACustomBitmap; ARect: TRect; x, y: integer; s: string; style: TTextStyle; c: TBGRAPixel); override; 73 procedure TextRect(ADest: TBGRACustomBitmap; ARect: TRect; x, y: integer; s: string; style: TTextStyle; texture: IBGRAScanner); override; 74 procedure CopyTextPathTo(ADest: IBGRAPath; x, y: single; s: string; align: TAlignment); override; 75 function TextSize(s: string): TSize; override; 76 destructor Destroy; override; 77 end; 78 13 79 TGlyphSizes = array of record 14 80 Glyph: String; … … 16 82 end; 17 83 18 TWordBreakHandler = procedure(var ABefore, AAfter: string) of object; 84 TBGRAVectorizedFontHeader = record 85 Name: string; 86 Style: TFontStyles; 87 EmHeightRatio: single; 88 Resolution: integer; 89 PixelMetric: TFontPixelMetric; 90 end; 91 TBGRAGlyphsInfo = record 92 Name: string; 93 Style: TFontStyles; 94 NbGlyphs: integer; 95 end; 19 96 20 97 { TBGRAVectorizedFont } … … 33 110 FItalicSlope: single; 34 111 FWordBreakHandler: TWordBreakHandler; 112 FDirectory: string; 113 FDirectoryContent: array of record 114 Filename: string; 115 FontName: string; 116 FontStyle: TFontStyles; 117 end; 118 FFontEmHeightRatioComputed: boolean; 119 FFontEmHeightRatio: single; 120 FFontPixelMetric: TFontPixelMetric; 121 FFontPixelMetricComputed: boolean; 122 FFontFound: boolean; 123 function GetEmHeight: single; 124 function GetFontPixelMetric: TFontPixelMetric; 125 function GetLCLHeight: single; 126 function GetVectorizeLCL: boolean; 127 procedure SetEmHeight(AValue: single); 35 128 procedure SetItalicSlope(AValue: single); 129 procedure SetLCLHeight(AValue: single); 36 130 procedure SetOrientation(AValue: single); 37 131 procedure SetQuadraticCurves(AValue: boolean); … … 41 135 procedure SetName(AValue: string); 42 136 procedure SetStyle(AValue: TFontStyles); 137 function GetFontEmHeightRatio: single; 138 procedure SetVectorizeLCL(AValue: boolean); 43 139 protected 44 140 procedure UpdateFont; … … 46 142 function GetGlyph(AIdentifier: string): TBGRAGlyph; override; 47 143 procedure DefaultWordBreakHandler(var ABefore, AAfter: string); 144 procedure Init(AVectorize: boolean); 145 function CustomHeaderSize: integer; override; 146 procedure WriteCustomHeader(AStream: TStream); override; 147 procedure ReadAdditionalHeader(AStream: TStream); override; 148 function ReadVectorizedFontHeader(AStream: TStream): TBGRAVectorizedFontHeader; 149 function HeaderName: string; override; 150 procedure SetDirectory(const AValue: string); 48 151 public 152 UnderlineDecoration,StrikeOutDecoration: boolean; 49 153 constructor Create; 154 constructor Create(AVectorizeLCL: boolean); 50 155 destructor Destroy; override; 51 156 function GetGlyphSize(AIdentifier:string): TPointF; 52 157 function GetTextGlyphSizes(AText:string): TGlyphSizes; 53 158 function GetTextSize(AText:string): TPointF; 54 procedure SplitText(var AText: string; AMaxWidth: single; out ARemains: string); 55 procedure DrawTextWordBreak(ADest: TBGRACanvas2D; AText: string; X, Y, MaxWidth: Single; AAlign: TBGRATypeWriterAlignment=twaTopLeft); 56 procedure DrawTextRect(ADest: TBGRACanvas2D; AText: string; X1,Y1,X2,Y2: Single; AAlign: TBGRATypeWriterAlignment=twaTopLeft); 57 procedure DrawTextRect(ADest: TBGRACanvas2D; AText: string; ATopLeft,ABottomRight: TPointF; AAlign: TBGRATypeWriterAlignment=twaTopLeft); 58 function GetTextWordBreakGlyphBoxes(AText: string; X,Y, MaxWidth: Single; AAlign: TBGRATypeWriterAlignment = twaTopLeft): TGlyphBoxes; 59 function GetTextRectGlyphBoxes(AText: string; X1,Y1,X2,Y2: Single; AAlign: TBGRATypeWriterAlignment=twaTopLeft): TGlyphBoxes; 60 function GetTextRectGlyphBoxes(AText: string; ATopLeft,ABottomRight: TPointF; AAlign: TBGRATypeWriterAlignment=twaTopLeft): TGlyphBoxes; 159 procedure SplitText(var ATextUTF8: string; AMaxWidth: single; out ARemainsUTF8: string); 160 procedure DrawText(ADest: TBGRACanvas2D; ATextUTF8: string; X, Y: Single; AAlign: TBGRATypeWriterAlignment=twaTopLeft); override; 161 procedure CopyTextPathTo(ADest: IBGRAPath; ATextUTF8: string; X, Y: Single; 162 AAlign: TBGRATypeWriterAlignment=twaTopLeft); override; 163 procedure DrawTextWordBreak(ADest: TBGRACanvas2D; ATextUTF8: string; X, Y, MaxWidth: Single; AAlign: TBGRATypeWriterAlignment=twaTopLeft); 164 procedure DrawTextRect(ADest: TBGRACanvas2D; ATextUTF8: string; X1,Y1,X2,Y2: Single; AAlign: TBGRATypeWriterAlignment=twaTopLeft); 165 procedure DrawTextRect(ADest: TBGRACanvas2D; ATextUTF8: string; ATopLeft,ABottomRight: TPointF; AAlign: TBGRATypeWriterAlignment=twaTopLeft); 166 function GetTextWordBreakGlyphBoxes(ATextUTF8: string; X,Y, MaxWidth: Single; AAlign: TBGRATypeWriterAlignment = twaTopLeft): TGlyphBoxes; 167 function GetTextRectGlyphBoxes(ATextUTF8: string; X1,Y1,X2,Y2: Single; AAlign: TBGRATypeWriterAlignment=twaTopLeft): TGlyphBoxes; 168 function GetTextRectGlyphBoxes(ATextUTF8: string; ATopLeft,ABottomRight: TPointF; AAlign: TBGRATypeWriterAlignment=twaTopLeft): TGlyphBoxes; 169 procedure UpdateDirectory; 170 function LoadGlyphsInfo(AFilenameUTF8: string): TBGRAGlyphsInfo; 61 171 62 172 property Resolution: integer read FResolution write SetResolution; 63 173 property Style: TFontStyles read FStyle write SetStyle; 64 174 property Name: string read FName write SetName; 175 property LCLHeight: single read GetLCLHeight write SetLCLHeight; 176 property EmHeight: single read GetEmHeight write SetEmHeight; 65 177 property FullHeight: single read FFullHeight write SetFullHeight; 66 178 property FontMatrix: TAffineMatrix read FFontMatrix write SetFontMatrix; … … 69 181 property ItalicSlope: single read FItalicSlope write SetItalicSlope; 70 182 property OnWordBreak: TWordBreakHandler read FWordBreakHandler write FWordBreakHandler; 183 property Directory: string read FDirectory write SetDirectory; 184 property FontEmHeightRatio: single read GetFontEmHeightRatio; 185 property FontPixelMetric: TFontPixelMetric read GetFontPixelMetric; 186 property FontFound: boolean read FFontFound; 187 property VectorizeLCL: boolean read GetVectorizeLCL write SetVectorizeLCL; 71 188 end; 72 189 73 190 implementation 74 191 75 uses BGRAText, LCLProc, Types; 76 192 uses LCLProc, FileUtil, lazutf8classes; 193 194 {$i winstream.inc} 77 195 function VectorizeMonochrome(ASource: TBGRACustomBitmap; zoom: single; PixelCenteredCoordinates: boolean): ArrayOfTPointF; 78 196 const unitShift = 6; … … 516 634 (ord(cur[1])+ord(cur[3])+ord(cur[7])+ord(cur[9]) = 3)) then 517 635 begin 518 if (not cur[6] and not cur[9] and not cur[8] and ((ASource.getPixel( integer(x-1),integer(y-2)).green <= 128) or (ASource.getPixel(integer(x+2),integer(y+1)).green <= 128)) ) or519 (not cur[8] and not cur[7] and not cur[4] and ((ASource.getPixel( integer(x-2),integer(y+1)).green <= 128) or (ASource.getPixel(integer(x+1),integer(y-2)).green <= 128)) ) or520 (not cur[4] and not cur[1] and not cur[2] and ((ASource.getPixel( integer(x+1),integer(y+2)).green <= 128) or (ASource.getPixel(integer(x-2),integer(y-1)).green <= 128)) ) or521 (not cur[2] and not cur[3] and not cur[6] and ((ASource.getPixel( integer(x-1),integer(y+2)).green <= 128) or (ASource.getPixel(integer(x+2),integer(y-1)).green <= 128)) ) then636 if (not cur[6] and not cur[9] and not cur[8] and ((ASource.getPixel(x-1,y-2).green <= 128) or (ASource.getPixel(x+2,y+1).green <= 128)) ) or 637 (not cur[8] and not cur[7] and not cur[4] and ((ASource.getPixel(x-2,y+1).green <= 128) or (ASource.getPixel(x+1,y-2).green <= 128)) ) or 638 (not cur[4] and not cur[1] and not cur[2] and ((ASource.getPixel(x+1,y+2).green <= 128) or (ASource.getPixel(x-2,y-1).green <= 128)) ) or 639 (not cur[2] and not cur[3] and not cur[6] and ((ASource.getPixel(x-1,y+2).green <= 128) or (ASource.getPixel(x+2,y-1).green <= 128)) ) then 522 640 ortho[y,x] := true; 523 641 end; … … 839 957 end; 840 958 959 { TBGRAVectorizedFontRenderer } 960 961 function TBGRAVectorizedFontRenderer.OutlineActuallyVisible: boolean; 962 begin 963 result := OutlineVisible and (abs(OutlineWidth) > 0) and (OutlineColor.Alpha <> 0) or (OutlineTexture <> nil); 964 end; 965 966 procedure TBGRAVectorizedFontRenderer.UpdateFont; 967 var i,neededResolution: integer; 968 begin 969 FVectorizedFont := nil; 970 FontName := Trim(FontName); 971 for i := 0 to high(FVectorizedFontArray) do 972 if (CompareText(FVectorizedFontArray[i].FontName,FontName)=0) and 973 (FVectorizedFontArray[i].FontStyle = FontStyle) then 974 begin 975 FVectorizedFont := FVectorizedFontArray[i].VectorizedFont; 976 break; 977 end; 978 979 if FVectorizedFont = nil then 980 begin 981 FVectorizedFont:= TBGRAVectorizedFont.Create(False); 982 FVectorizedFont.Name := FontName; 983 FVectorizedFont.Style := FontStyle; 984 FVectorizedFont.Directory := FDirectoryUTF8; 985 if not FVectorizedFont.FontFound and LCLFontAvailable then 986 FVectorizedFont.VectorizeLCL := True; 987 Setlength(FVectorizedFontArray,length(FVectorizedFontArray)+1); 988 FVectorizedFontArray[high(FVectorizedFontArray)].FontName := FontName; 989 FVectorizedFontArray[high(FVectorizedFontArray)].FontStyle := FontStyle; 990 FVectorizedFontArray[high(FVectorizedFontArray)].VectorizedFont := FVectorizedFont; 991 end; 992 if FontEmHeight > 0 then 993 FVectorizedFont.EmHeight := FontEmHeight 994 else 995 FVectorizedFont.FullHeight:= -FontEmHeight; 996 if OutlineActuallyVisible then 997 begin 998 if OuterOutlineOnly then 999 FVectorizedFont.OutlineMode := twoFillOverStroke 1000 else 1001 FVectorizedFont.OutlineMode := twoStrokeOverFill; 1002 FVectorizedFont.QuadraticCurves := False; 1003 end 1004 else 1005 begin 1006 FVectorizedFont.OutlineMode := twoFill; 1007 FVectorizedFont.QuadraticCurves := FVectorizedFont.FullHeight > FVectorizedFont.Resolution*0.8; 1008 end; 1009 if FVectorizedFont.VectorizeLCL then 1010 begin 1011 neededResolution := trunc((FVectorizedFont.FullHeight+80)/50)*50; 1012 if neededResolution > MaxFontResolution then neededResolution := MaxFontResolution; 1013 if FVectorizedFont.Resolution < neededResolution then FVectorizedFont.Resolution:= neededResolution; 1014 end; 1015 end; 1016 1017 function TBGRAVectorizedFontRenderer.GetCanvas2D(ASurface: TBGRACustomBitmap 1018 ): TBGRACanvas2D; 1019 begin 1020 if (FCanvas2D = nil) or (FCanvas2D.surface <> ASurface) then 1021 begin 1022 FCanvas2D.Free; 1023 FCanvas2D := TBGRACanvas2D.Create(ASurface); 1024 end; 1025 result := FCanvas2D; 1026 FCanvas2D.antialiasing:= FontQuality in[fqFineAntialiasing,fqFineClearTypeBGR,fqFineClearTypeRGB]; 1027 if OutlineTexture <> nil then 1028 FCanvas2D.strokeStyle(OutlineTexture) 1029 else 1030 FCanvas2D.strokeStyle(OutlineColor); 1031 FCanvas2D.lineWidth := abs(OutlineWidth); 1032 if not ShadowVisible then 1033 FCanvas2D.shadowColor(BGRAPixelTransparent) 1034 else 1035 begin 1036 FCanvas2D.shadowColor(ShadowColor); 1037 FCanvas2D.shadowBlur:= ShadowRadius; 1038 FCanvas2D.shadowOffset := PointF(ShadowOffset.X,ShadowOffset.Y); 1039 end; 1040 end; 1041 1042 procedure TBGRAVectorizedFontRenderer.InternalTextRect( 1043 ADest: TBGRACustomBitmap; ARect: TRect; x, y: integer; sUTF8: string; 1044 style: TTextStyle; c: TBGRAPixel; texture: IBGRAScanner); 1045 var 1046 twAlign : TBGRATypeWriterAlignment; 1047 c2D: TBGRACanvas2D; 1048 intersectedClip,previousClip: TRect; 1049 begin 1050 previousClip := ADest.ClipRect; 1051 if style.Clipping then 1052 begin 1053 intersectedClip := rect(0,0,0,0); 1054 if not IntersectRect(intersectedClip, previousClip, ARect) then exit; 1055 ADest.ClipRect := intersectedClip; 1056 end; 1057 UpdateFont; 1058 FVectorizedFont.Orientation := 0; 1059 case style.Alignment of 1060 taCenter: case style.Layout of 1061 tlCenter: twAlign := twaMiddle; 1062 tlBottom: twAlign := twaBottom; 1063 else twAlign:= twaTop; 1064 end; 1065 taRightJustify: 1066 case style.Layout of 1067 tlCenter: twAlign := twaRight; 1068 tlBottom: twAlign := twaBottomRight; 1069 else twAlign := twaTopRight; 1070 end; 1071 else 1072 case style.Layout of 1073 tlCenter: twAlign := twaLeft; 1074 tlBottom: twAlign := twaBottomLeft; 1075 else twAlign:= twaTopLeft; 1076 end; 1077 end; 1078 c2D := GetCanvas2D(ADest); 1079 if texture = nil then 1080 c2D.fillStyle(c) 1081 else 1082 c2D.fillStyle(texture); 1083 if style.Wordbreak then 1084 FVectorizedFont.DrawTextRect(c2D, sUTF8, x-0.5,y-0.5,ARect.Right-0.5,ARect.Bottom-0.5, twAlign) 1085 else 1086 begin 1087 case style.Layout of 1088 tlCenter: y := (ARect.Top+ARect.Bottom) div 2; 1089 tlBottom: y := ARect.Bottom; 1090 end; 1091 case style.Alignment of 1092 taCenter: FVectorizedFont.DrawText(c2D, sUTF8, (ARect.Left+ARect.Right-1)/2,y-0.5, twAlign); 1093 taRightJustify: FVectorizedFont.DrawText(c2D, sUTF8, ARect.Right-0.5,y-0.5, twAlign); 1094 else 1095 FVectorizedFont.DrawText(c2D, sUTF8, x-0.5,y-0.5, twAlign); 1096 end; 1097 end; 1098 if style.Clipping then 1099 ADest.ClipRect := previousClip; 1100 end; 1101 1102 procedure TBGRAVectorizedFontRenderer.Init; 1103 begin 1104 FVectorizedFontArray := nil; 1105 FDirectoryUTF8 := ''; 1106 1107 OutlineVisible:= True; 1108 OutlineColor := BGRAPixelTransparent; 1109 OuterOutlineOnly := false; 1110 1111 ShadowColor := BGRABlack; 1112 ShadowVisible := false; 1113 ShadowOffset := Point(5,5); 1114 ShadowRadius := 5; 1115 1116 MaxFontResolution := 300; 1117 end; 1118 1119 constructor TBGRAVectorizedFontRenderer.Create; 1120 begin 1121 Init; 1122 end; 1123 1124 constructor TBGRAVectorizedFontRenderer.Create(ADirectoryUTF8: string); 1125 begin 1126 Init; 1127 FDirectoryUTF8 := ADirectoryUTF8; 1128 end; 1129 1130 function TBGRAVectorizedFontRenderer.GetFontPixelMetric: TFontPixelMetric; 1131 var factor: single; 1132 begin 1133 UpdateFont; 1134 result := FVectorizedFont.FontPixelMetric; 1135 if FVectorizedFont.Resolution > 0 then 1136 begin 1137 factor := FVectorizedFont.FullHeight/FVectorizedFont.Resolution; 1138 result.Baseline := round(result.Baseline*factor); 1139 result.CapLine := round(result.CapLine*factor); 1140 result.Lineheight := round(result.Lineheight*factor); 1141 result.DescentLine := round(result.DescentLine*factor); 1142 result.xLine := round(result.xLine*factor); 1143 end; 1144 end; 1145 1146 procedure TBGRAVectorizedFontRenderer.TextOutAngle(ADest: TBGRACustomBitmap; x, 1147 y: single; orientation: integer; s: string; c: TBGRAPixel; align: TAlignment); 1148 var 1149 twAlign : TBGRATypeWriterAlignment; 1150 c2D: TBGRACanvas2D; 1151 ofs: TPointF; 1152 begin 1153 UpdateFont; 1154 FVectorizedFont.Orientation := orientation; 1155 case align of 1156 taCenter: twAlign:= twaMiddle; 1157 taRightJustify: twAlign := twaRight; 1158 else twAlign:= twaLeft; 1159 end; 1160 c2D := GetCanvas2D(ADest); 1161 c2D.fillStyle(c); 1162 ofs := PointF(x,y); 1163 ofs += AffineMatrixRotationDeg(-orientation*0.1)*PointF(0,FVectorizedFont.FullHeight*0.5); 1164 FVectorizedFont.DrawText(c2D, s, ofs.x,ofs.y, twAlign); 1165 end; 1166 1167 procedure TBGRAVectorizedFontRenderer.TextOutAngle(ADest: TBGRACustomBitmap; x, 1168 y: single; orientation: integer; s: string; texture: IBGRAScanner; 1169 align: TAlignment); 1170 var 1171 twAlign : TBGRATypeWriterAlignment; 1172 c2D: TBGRACanvas2D; 1173 begin 1174 UpdateFont; 1175 FVectorizedFont.Orientation := orientation; 1176 case align of 1177 taCenter: twAlign:= twaTop; 1178 taRightJustify: twAlign := twaTopRight; 1179 else twAlign:= twaTopLeft; 1180 end; 1181 c2D := GetCanvas2D(ADest); 1182 c2D.fillStyle(texture); 1183 FVectorizedFont.DrawText(c2D, s, x,y, twAlign); 1184 end; 1185 1186 procedure TBGRAVectorizedFontRenderer.TextOut(ADest: TBGRACustomBitmap; x, 1187 y: single; s: string; texture: IBGRAScanner; align: TAlignment); 1188 begin 1189 TextOutAngle(ADest,x,y,FontOrientation,s,texture,align); 1190 end; 1191 1192 procedure TBGRAVectorizedFontRenderer.TextOut(ADest: TBGRACustomBitmap; x, 1193 y: single; s: string; c: TBGRAPixel; align: TAlignment); 1194 begin 1195 TextOutAngle(ADest,x,y,FontOrientation,s,c,align); 1196 end; 1197 1198 procedure TBGRAVectorizedFontRenderer.TextRect(ADest: TBGRACustomBitmap; 1199 ARect: TRect; x, y: integer; s: string; style: TTextStyle; c: TBGRAPixel); 1200 begin 1201 InternalTextRect(ADest,ARect,x,y,s,style,c,nil); 1202 end; 1203 1204 procedure TBGRAVectorizedFontRenderer.TextRect(ADest: TBGRACustomBitmap; 1205 ARect: TRect; x, y: integer; s: string; style: TTextStyle; 1206 texture: IBGRAScanner); 1207 begin 1208 InternalTextRect(ADest,ARect,x,y,s,style,BGRAPixelTransparent,texture); 1209 end; 1210 1211 procedure TBGRAVectorizedFontRenderer.CopyTextPathTo(ADest: IBGRAPath; x, y: single; s: string; align: TAlignment); 1212 var 1213 twAlign : TBGRATypeWriterAlignment; 1214 ofs: TPointF; 1215 begin 1216 UpdateFont; 1217 FVectorizedFont.Orientation := 0; 1218 case align of 1219 taCenter: twAlign:= twaMiddle; 1220 taRightJustify: twAlign := twaRight; 1221 else twAlign:= twaLeft; 1222 end; 1223 ofs := PointF(x,y); 1224 ofs += PointF(0,FVectorizedFont.FullHeight*0.5); 1225 FVectorizedFont.CopyTextPathTo(ADest, s, ofs.x,ofs.y, twAlign); 1226 end; 1227 1228 function TBGRAVectorizedFontRenderer.TextSize(s: string): TSize; 1229 var sizeF: TPointF; 1230 begin 1231 UpdateFont; 1232 sizeF := FVectorizedFont.GetTextSize(s); 1233 result.cx := round(sizeF.x); 1234 result.cy := round(sizeF.y); 1235 end; 1236 1237 destructor TBGRAVectorizedFontRenderer.Destroy; 1238 var i: integer; 1239 begin 1240 FCanvas2D.Free; 1241 for i := 0 to high(FVectorizedFontArray) do 1242 FVectorizedFontArray[i].VectorizedFont.Free; 1243 FVectorizedFontArray := nil; 1244 inherited Destroy; 1245 end; 1246 841 1247 { TBGRAVectorizedFont } 842 1248 … … 862 1268 end; 863 1269 1270 procedure TBGRAVectorizedFont.SetLCLHeight(AValue: single); 1271 begin 1272 if (AValue > 0) xor (FontEmHeightSign < 0) then 1273 EmHeight := abs(AValue) 1274 else 1275 FullHeight := abs(AValue); 1276 end; 1277 1278 function TBGRAVectorizedFont.GetEmHeight: single; 1279 begin 1280 result := FullHeight * FontEmHeightRatio; 1281 end; 1282 1283 function TBGRAVectorizedFont.GetFontPixelMetric: TFontPixelMetric; 1284 begin 1285 if not FFontPixelMetricComputed and (FFont <> nil) then 1286 begin 1287 FFontPixelMetric := BGRAText.GetFontPixelMetric(FFont); 1288 FFontPixelMetricComputed := true; 1289 end; 1290 result := FFontPixelMetric; 1291 end; 1292 1293 function TBGRAVectorizedFont.GetLCLHeight: single; 1294 begin 1295 result := FullHeight * FontFullHeightSign; 1296 end; 1297 1298 function TBGRAVectorizedFont.GetVectorizeLCL: boolean; 1299 begin 1300 result := FFont <> nil; 1301 end; 1302 1303 procedure TBGRAVectorizedFont.SetEmHeight(AValue: single); 1304 begin 1305 if FontEmHeightRatio > 0 then 1306 FullHeight := AValue / FontEmHeightRatio; 1307 end; 1308 864 1309 procedure TBGRAVectorizedFont.SetQuadraticCurves(AValue: boolean); 865 1310 begin … … 895 1340 end; 896 1341 1342 function TBGRAVectorizedFont.GetFontEmHeightRatio: single; 1343 var 1344 lEmHeight, lFullHeight: single; 1345 OldHeight: integer; 1346 begin 1347 if not FFontEmHeightRatioComputed then 1348 begin 1349 if FFont <> nil then 1350 begin 1351 OldHeight := FFont.Height; 1352 FFont.Height := FontEmHeightSign * 100; 1353 lEmHeight := BGRATextSize(FFont, fqSystem, 'Hg', 1).cy; 1354 FFont.Height := FontFullHeightSign * 100; 1355 lFullHeight := BGRATextSize(FFont, fqSystem, 'Hg', 1).cy; 1356 if lEmHeight = 0 then 1357 FFontEmHeightRatio := 1 1358 else 1359 FFontEmHeightRatio := lFullHeight/lEmHeight; 1360 FFontEmHeightRatioComputed := true; 1361 FFont.Height := OldHeight; 1362 end else 1363 begin 1364 result := 1; 1365 exit; 1366 end; 1367 end; 1368 result := FFontEmHeightRatio; 1369 end; 1370 1371 procedure TBGRAVectorizedFont.SetVectorizeLCL(AValue: boolean); 1372 begin 1373 if AValue then 1374 begin 1375 if FFont = nil then 1376 FFont := TFont.Create; 1377 end else 1378 begin 1379 if FFont <> nil then 1380 FreeAndNil(FFont); 1381 end; 1382 UpdateFont; 1383 end; 1384 897 1385 procedure TBGRAVectorizedFont.UpdateFont; 898 begin 899 ClearGlyphs; 900 FFont.Name := FName; 901 FFont.Style := FStyle; 902 FFont.Height := FontFullHeightSign * FResolution; 1386 var i: integer; 1387 bestIndex, bestDistance: integer; 1388 distance: integer; 1389 begin 1390 if FFont <> nil then 1391 begin 1392 ClearGlyphs; 1393 FFont.Name := FName; 1394 FFont.Style := FStyle; 1395 FFont.Height := FontFullHeightSign * FResolution; 1396 FFontEmHeightRatio := 1; 1397 FFontEmHeightRatioComputed := false; 1398 fillchar(FFontPixelMetric,sizeof(FFontPixelMetric),0); 1399 FFontPixelMetricComputed := false; 1400 FFontFound := True; 1401 end else 1402 begin 1403 bestIndex := -1; 1404 bestDistance := 1000; 1405 for i := 0 to high(FDirectoryContent) do 1406 begin 1407 if CompareText(FDirectoryContent[i].FontName,FName) = 0 then 1408 begin 1409 distance := 0; 1410 if (fsBold in FDirectoryContent[i].FontStyle) xor (fsBold in FStyle) then distance += 10; 1411 if (fsItalic in FDirectoryContent[i].FontStyle) xor (fsItalic in FStyle) then distance += 5; 1412 if (fsStrikeOut in FDirectoryContent[i].FontStyle) xor (fsStrikeOut in FStyle) then distance += 1; 1413 if (fsUnderline in FDirectoryContent[i].FontStyle) xor (fsUnderline in FStyle) then distance += 1; 1414 if (bestIndex = -1) or (distance < bestDistance) then 1415 begin 1416 bestIndex := i; 1417 bestDistance := distance; 1418 if FDirectoryContent[i].FontStyle = FStyle then break; 1419 end; 1420 end; 1421 end; 1422 if bestIndex <> -1 then 1423 begin 1424 if not (fsItalic in FDirectoryContent[bestIndex].FontStyle) and (fsItalic in FStyle) then 1425 ItalicSlope := 0.25 1426 else if (fsItalic in FDirectoryContent[bestIndex].FontStyle) and not (fsItalic in FStyle) then 1427 ItalicSlope := -0.25 1428 else 1429 ItalicSlope := 0; 1430 1431 UnderlineDecoration := not (fsUnderline in FDirectoryContent[bestIndex].FontStyle) and (fsUnderline in FStyle); 1432 StrikeOutDecoration := not (fsStrikeOut in FDirectoryContent[bestIndex].FontStyle) and (fsStrikeOut in FStyle); 1433 1434 ClearGlyphs; 1435 LoadGlyphsFromFile(FDirectoryContent[bestIndex].Filename); 1436 FFontFound := True; 1437 end else 1438 FFontFound := false; 1439 end; 903 1440 end; 904 1441 … … 911 1448 begin 912 1449 inherited Create; 913 FName := 'Arial'; 914 FStyle := []; 915 FFontMatrix := AffineMatrixIdentity; 916 FOrientation := 0; 917 FResolution := 100; 918 FFont := TFont.Create; 919 FBuffer := BGRABitmapFactory.Create; 920 FFullHeight := 20; 921 FItalicSlope := 0; 922 UpdateFont; 923 UpdateMatrix; 924 FWordBreakHandler:= nil; 1450 Init(True); 1451 end; 1452 1453 constructor TBGRAVectorizedFont.Create(AVectorizeLCL: boolean); 1454 begin 1455 inherited Create; 1456 Init(AVectorizeLCL); 925 1457 end; 926 1458 … … 1012 1544 end; 1013 1545 1014 procedure TBGRAVectorizedFont.SplitText(var AText : string; AMaxWidth: single;1015 out ARemains : string);1546 procedure TBGRAVectorizedFont.SplitText(var ATextUTF8: string; AMaxWidth: single; 1547 out ARemainsUTF8: string); 1016 1548 var 1017 1549 pstr: pchar; 1018 left,charlen: integer; 1550 p,left,charlen: integer; 1551 totalWidth: single; 1552 firstChar: boolean; 1019 1553 nextchar: string; 1020 1554 g: TBGRAGlyph; 1021 totalWidth: single;1022 firstChar: boolean;1023 1555 begin 1024 1556 totalWidth := 0; 1025 if AText = '' then1026 begin 1027 ARemains := '';1557 if ATextUTF8 = '' then 1558 begin 1559 ARemainsUTF8 := ''; 1028 1560 exit; 1029 1561 end else 1030 1562 begin 1031 pstr := @AText[1]; 1032 left := length(AText); 1563 p := 1; 1564 pstr := @ATextUTF8[1]; 1565 left := length(ATextUTF8); 1033 1566 firstChar := true; 1034 1567 while left > 0 do 1035 1568 begin 1569 if RemoveLineEnding(ATextUTF8,p) then 1570 begin 1571 ARemainsUTF8 := copy(ATextUTF8,p,length(ATextUTF8)-p+1); 1572 ATextUTF8 := copy(ATextUTF8,1,p-1); 1573 exit; 1574 end; 1575 1036 1576 charlen := UTF8CharacterLength(pstr); 1037 1577 setlength(nextchar, charlen); … … 1043 1583 begin 1044 1584 totalWidth += g.Width*FullHeight; 1045 if (totalWidth > AMaxWidth) and not firstCharthen1585 if not firstChar and (totalWidth > AMaxWidth) then 1046 1586 begin 1047 ARemains := copy(AText,length(AText)-left+1,left);1048 AText := copy(AText, 1, length(AText)-left);1587 ARemainsUTF8:= copy(ATextUTF8,p,length(ATextUTF8)-p+1); 1588 ATextUTF8 := copy(ATextUTF8,1,p-1); 1049 1589 if Assigned(FWordBreakHandler) then 1050 FWordBreakHandler(AText ,ARemains) else1051 DefaultWordBreakHandler(AText ,ARemains);1590 FWordBreakHandler(ATextUTF8,ARemainsUTF8) else 1591 DefaultWordBreakHandler(ATextUTF8,ARemainsUTF8); 1052 1592 exit; 1053 1593 end; … … 1055 1595 1056 1596 dec(left,charlen); 1597 inc(p,charlen); 1057 1598 firstChar := false; 1058 1599 end; 1059 1600 end; 1060 ARemains := ''; //no split 1601 ARemainsUTF8 := ''; //no split 1602 end; 1603 1604 procedure TBGRAVectorizedFont.DrawText(ADest: TBGRACanvas2D; ATextUTF8: string; X, 1605 Y: Single; AAlign: TBGRATypeWriterAlignment); 1606 var underlinePoly: ArrayOfTPointF; 1607 m: TAffineMatrix; 1608 i: integer; 1609 deltaY: single; 1610 begin 1611 inherited DrawText(ADest, ATextUTF8, X, Y, AAlign); 1612 if AAlign in [twaBottom,twaBottomLeft,twaBottomRight] then deltaY := -1 else 1613 if AAlign in [twaLeft,twaMiddle,twaRight] then deltaY := -0.5 else 1614 deltaY := 0; 1615 if UnderlineDecoration and (Resolution > 0) then 1616 begin 1617 underlinePoly := BGRATextUnderline(PointF(0,deltaY), GetTextSize(ATextUTF8).x/FullHeight, FontPixelMetric.Baseline/Resolution, 1618 (FontPixelMetric.Baseline-FontPixelMetric.CapLine)/Resolution); 1619 if underlinePoly <> nil then 1620 begin 1621 m := GetTextMatrix(ATextUTF8, X,Y,AAlign); 1622 for i := 0 to high(underlinePoly) do 1623 underlinePoly[i] := m*underlinePoly[i]; 1624 if OutlineMode <> twoPath then ADest.beginPath; 1625 ADest.polylineTo(underlinePoly); 1626 DrawLastPath(ADest); 1627 end; 1628 end; 1629 if StrikeOutDecoration and (Resolution > 0) then 1630 begin 1631 underlinePoly := BGRATextStrikeOut(PointF(0,deltaY), GetTextSize(ATextUTF8).x/FullHeight, FontPixelMetric.Baseline/Resolution, 1632 (FontPixelMetric.Baseline-FontPixelMetric.CapLine)/Resolution, (FontPixelMetric.Baseline-FontPixelMetric.xLine)/Resolution); 1633 if underlinePoly <> nil then 1634 begin 1635 m := GetTextMatrix(ATextUTF8, X,Y,AAlign); 1636 for i := 0 to high(underlinePoly) do 1637 underlinePoly[i] := m*underlinePoly[i]; 1638 if OutlineMode <> twoPath then ADest.beginPath; 1639 ADest.polylineTo(underlinePoly); 1640 DrawLastPath(ADest); 1641 end; 1642 end; 1643 end; 1644 1645 procedure TBGRAVectorizedFont.CopyTextPathTo(ADest: IBGRAPath; 1646 ATextUTF8: string; X, Y: Single; AAlign: TBGRATypeWriterAlignment); 1647 var underlinePoly: ArrayOfTPointF; 1648 m: TAffineMatrix; 1649 i: integer; 1650 deltaY: single; 1651 begin 1652 inherited CopyTextPathTo(ADest,ATextUTF8, X, Y, AAlign); 1653 if AAlign in [twaBottom,twaBottomLeft,twaBottomRight] then deltaY := -1 else 1654 if AAlign in [twaLeft,twaMiddle,twaRight] then deltaY := -0.5 else 1655 deltaY := 0; 1656 if UnderlineDecoration and (Resolution > 0) then 1657 begin 1658 underlinePoly := BGRATextUnderline(PointF(0,deltaY), GetTextSize(ATextUTF8).x/FullHeight, FontPixelMetric.Baseline/Resolution, 1659 (FontPixelMetric.Baseline-FontPixelMetric.CapLine)/Resolution); 1660 if underlinePoly <> nil then 1661 begin 1662 m := GetTextMatrix(ATextUTF8, X,Y,AAlign); 1663 ADest.moveTo(m*underlinePoly[0]); 1664 for i := 1 to high(underlinePoly) do 1665 ADest.lineTo(m*underlinePoly[i]); 1666 ADest.closePath; 1667 end; 1668 end; 1669 if StrikeOutDecoration and (Resolution > 0) then 1670 begin 1671 underlinePoly := BGRATextStrikeOut(PointF(0,deltaY), GetTextSize(ATextUTF8).x/FullHeight, FontPixelMetric.Baseline/Resolution, 1672 (FontPixelMetric.Baseline-FontPixelMetric.CapLine)/Resolution, (FontPixelMetric.Baseline-FontPixelMetric.xLine)/Resolution); 1673 if underlinePoly <> nil then 1674 begin 1675 m := GetTextMatrix(ATextUTF8, X,Y,AAlign); 1676 ADest.moveTo(m*underlinePoly[0]); 1677 for i := 1 to high(underlinePoly) do 1678 ADest.lineTo(m*underlinePoly[i]); 1679 ADest.closePath; 1680 end; 1681 end; 1061 1682 end; 1062 1683 1063 1684 procedure TBGRAVectorizedFont.DrawTextWordBreak(ADest: TBGRACanvas2D; 1064 AText : string; X, Y, MaxWidth: Single; AAlign: TBGRATypeWriterAlignment);1685 ATextUTF8: string; X, Y, MaxWidth: Single; AAlign: TBGRATypeWriterAlignment); 1065 1686 var ARemains: string; 1066 1687 step: TPointF; … … 1071 1692 lineAlignment: TBGRATypeWriterAlignment; 1072 1693 begin 1073 if (AText = '') or (MaxWidth <= 0) then exit;1694 if (ATextUTF8 = '') or (MaxWidth <= 0) then exit; 1074 1695 1075 1696 oldItalicSlope:= ItalicSlope; … … 1104 1725 Y += step.Y*lineShift; 1105 1726 repeat 1106 SplitText(AText , MaxWidth, ARemains);1107 DrawText(ADest,AText ,X,Y,lineAlignment);1108 AText := ARemains;1727 SplitText(ATextUTF8, MaxWidth, ARemains); 1728 DrawText(ADest,ATextUTF8,X,Y,lineAlignment); 1729 ATextUTF8 := ARemains; 1109 1730 X+= step.X; 1110 1731 Y+= step.Y; … … 1114 1735 lines := TStringList.Create; 1115 1736 repeat 1116 SplitText(AText , MaxWidth, ARemains);1117 lines.Add(AText );1118 AText := ARemains;1737 SplitText(ATextUTF8, MaxWidth, ARemains); 1738 lines.Add(ATextUTF8); 1739 ATextUTF8 := ARemains; 1119 1740 until ARemains = ''; 1120 1741 if AAlign in[twaLeft,twaMiddle,twaRight] then lineShift := lines.Count/2-0.5 … … 1140 1761 end; 1141 1762 1142 procedure TBGRAVectorizedFont.DrawTextRect(ADest: TBGRACanvas2D; AText : string;1763 procedure TBGRAVectorizedFont.DrawTextRect(ADest: TBGRACanvas2D; ATextUTF8: string; 1143 1764 X1, Y1, X2, Y2: Single; AAlign: TBGRATypeWriterAlignment); 1144 1765 var X,Y: single; … … 1154 1775 oldOrientation:= Orientation; 1155 1776 Orientation:= 0; 1156 DrawTextWordBreak(ADest,AText ,X,Y,X2-X1,AAlign);1777 DrawTextWordBreak(ADest,ATextUTF8,X,Y,X2-X1,AAlign); 1157 1778 Orientation:= oldOrientation; 1158 1779 end; 1159 1780 1160 procedure TBGRAVectorizedFont.DrawTextRect(ADest: TBGRACanvas2D; AText : string;1781 procedure TBGRAVectorizedFont.DrawTextRect(ADest: TBGRACanvas2D; ATextUTF8: string; 1161 1782 ATopLeft, ABottomRight: TPointF; AAlign: TBGRATypeWriterAlignment); 1162 1783 begin 1163 DrawTextRect(ADest,AText ,ATopLeft.X,ATopLeft.Y,ABottomRight.X,ABottomRight.Y,AAlign);1164 end; 1165 1166 function TBGRAVectorizedFont.GetTextWordBreakGlyphBoxes(AText : string; X, Y,1784 DrawTextRect(ADest,ATextUTF8,ATopLeft.X,ATopLeft.Y,ABottomRight.X,ABottomRight.Y,AAlign); 1785 end; 1786 1787 function TBGRAVectorizedFont.GetTextWordBreakGlyphBoxes(ATextUTF8: string; X, Y, 1167 1788 MaxWidth: Single; AAlign: TBGRATypeWriterAlignment): TGlyphBoxes; 1168 1789 var ARemains: string; … … 1177 1798 begin 1178 1799 result := nil; 1179 if AText = '' then exit;1800 if ATextUTF8 = '' then exit; 1180 1801 1181 1802 oldItalicSlope:= ItalicSlope; … … 1202 1823 lines := TStringList.Create; 1203 1824 repeat 1204 SplitText(AText , MaxWidth, ARemains);1205 lines.Add(AText );1206 AText := ARemains;1825 SplitText(ATextUTF8, MaxWidth, ARemains); 1826 lines.Add(ATextUTF8); 1827 ATextUTF8 := ARemains; 1207 1828 until ARemains = ''; 1208 1829 … … 1239 1860 end; 1240 1861 1241 function TBGRAVectorizedFont.GetTextRectGlyphBoxes(AText : string; X1, Y1, X2,1862 function TBGRAVectorizedFont.GetTextRectGlyphBoxes(ATextUTF8: string; X1, Y1, X2, 1242 1863 Y2: Single; AAlign: TBGRATypeWriterAlignment): TGlyphBoxes; 1243 1864 var X,Y,oldOrientation: single; … … 1256 1877 oldOrientation:= Orientation; 1257 1878 Orientation:= 0; 1258 result := GetTextWordBreakGlyphBoxes(AText ,X,Y,X2-X1,AAlign);1879 result := GetTextWordBreakGlyphBoxes(ATextUTF8,X,Y,X2-X1,AAlign); 1259 1880 Orientation:= oldOrientation; 1260 1881 end; 1261 1882 1262 function TBGRAVectorizedFont.GetTextRectGlyphBoxes(AText : string; ATopLeft,1883 function TBGRAVectorizedFont.GetTextRectGlyphBoxes(ATextUTF8: string; ATopLeft, 1263 1884 ABottomRight: TPointF; AAlign: TBGRATypeWriterAlignment): TGlyphBoxes; 1264 1885 begin 1265 result := GetTextRectGlyphBoxes(AText,ATopLeft.X,ATopLeft.Y,ABottomRight.X,ABottomRight.Y,AAlign); 1886 result := GetTextRectGlyphBoxes(ATextUTF8,ATopLeft.X,ATopLeft.Y,ABottomRight.X,ABottomRight.Y,AAlign); 1887 end; 1888 1889 procedure TBGRAVectorizedFont.UpdateDirectory; 1890 var 1891 NbFiles: integer; 1892 SearchRec: TSearchRec; 1893 Info: TBGRAGlyphsInfo; 1894 Fullname: string; 1895 begin 1896 NbFiles := 0; 1897 FDirectoryContent := nil; 1898 if FDirectory = '' then exit; 1899 if (length(FDirectory) > 0) and not (FDirectory[length(FDirectory)] in AllowDirectorySeparators) then 1900 FDirectory += DirectorySeparator; 1901 if FindFirstUTF8(FDirectory +'*.glyphs', faAnyFile, SearchRec) = 0 then 1902 repeat 1903 if (faDirectory or faVolumeId or faSysFile) and SearchRec.Attr = 0 then 1904 begin 1905 Fullname := FDirectory+SearchRec.Name; 1906 Info := LoadGlyphsInfo(Fullname); 1907 if (info.Name <> '') and (info.NbGlyphs > 0) then 1908 begin 1909 if NbFiles = length(FDirectoryContent) then 1910 setlength(FDirectoryContent,2*NbFiles+1); 1911 FDirectoryContent[NbFiles].Filename:= Fullname; 1912 FDirectoryContent[NbFiles].FontName:= info.Name; 1913 FDirectoryContent[NbFiles].FontStyle:= info.Style; 1914 inc(NbFiles); 1915 end; 1916 end; 1917 until FindNext(SearchRec) <> 0; 1918 SetLength(FDirectoryContent,NbFiles); 1919 end; 1920 1921 function TBGRAVectorizedFont.LoadGlyphsInfo(AFilenameUTF8: string): TBGRAGlyphsInfo; 1922 var Stream: TFileStreamUTF8; 1923 twHeader: TBGRACustomTypeWriterHeader; 1924 vfHeader: TBGRAVectorizedFontHeader; 1925 begin 1926 result.Name := ''; 1927 result.NbGlyphs := 0; 1928 result.Style := []; 1929 Stream := nil; 1930 try 1931 Stream := TFileStreamUTF8.Create(AFilenameUTF8,fmOpenRead); 1932 Stream.Position := 4; 1933 twHeader := ReadCustomTypeWriterHeader(Stream); 1934 result.NbGlyphs := twHeader.NbGlyphs; 1935 if twHeader.HeaderName = HeaderName then 1936 begin 1937 vfHeader := ReadVectorizedFontHeader(Stream); 1938 result.Name := vfHeader.Name; 1939 result.Style:= vfHeader.Style; 1940 end; 1941 except 1942 on ex:exception do 1943 begin 1944 1945 end; 1946 end; 1947 Stream.Free; 1266 1948 end; 1267 1949 … … 1271 1953 begin 1272 1954 Result:=inherited GetGlyph(AIdentifier); 1273 if (result = nil) and (FResolution > 0) then1955 if (result = nil) and (FResolution > 0) and (FFont <> nil) then 1274 1956 begin 1275 1957 g := TBGRAPolygonalGlyph.Create(AIdentifier); … … 1294 1976 1295 1977 procedure TBGRAVectorizedFont.DefaultWordBreakHandler(var ABefore,AAfter: string); 1296 var p: integer; 1297 begin 1298 if (AAfter <> '') and (ABefore <> '') and (AAfter[1]<> ' ') and (ABefore[length(ABefore)] <> ' ') then 1299 begin 1300 p := length(ABefore); 1301 while (p > 1) and (ABefore[p-1] <> ' ') do dec(p); 1302 if p > 1 then //can put the word after 1303 begin 1304 AAfter := copy(ABefore,p,length(ABefore)-p+1)+AAfter; 1305 ABefore := copy(ABefore,1,p-1); 1306 end else 1307 begin //cannot put the word after, so before 1308 1309 end; 1310 end; 1311 while (ABefore <> '') and (ABefore[length(ABefore)] =' ') do delete(ABefore,length(ABefore),1); 1312 while (AAfter <> '') and (AAfter[1] =' ') do delete(AAfter,1,1); 1978 begin 1979 BGRADefaultWordBreakHandler(ABefore,AAfter); 1980 end; 1981 1982 procedure TBGRAVectorizedFont.Init(AVectorize: boolean); 1983 begin 1984 FName := 'Arial'; 1985 FStyle := []; 1986 FFontMatrix := AffineMatrixIdentity; 1987 FOrientation := 0; 1988 FResolution := 100; 1989 FFontEmHeightRatio := 1; 1990 FFontEmHeightRatioComputed := false; 1991 if AVectorize then 1992 FFont := TFont.Create 1993 else 1994 FFont := nil; 1995 FBuffer := BGRABitmapFactory.Create; 1996 FFullHeight := 20; 1997 FItalicSlope := 0; 1998 UpdateFont; 1999 UpdateMatrix; 2000 FWordBreakHandler:= nil; 2001 end; 2002 2003 function TBGRAVectorizedFont.CustomHeaderSize: integer; 2004 begin 2005 Result:= (inherited CustomHeaderSize) + 4+length(FName)+4 + sizeof(single) + 4 + 5*4; 2006 end; 2007 2008 procedure TBGRAVectorizedFont.WriteCustomHeader(AStream: TStream); 2009 var metric: TFontPixelMetric; 2010 begin 2011 inherited WriteCustomHeader(AStream); 2012 WinWriteLongint(AStream, length(FName)); 2013 AStream.Write(FName[1],length(FName)); 2014 WinWriteLongint(AStream, integer(FStyle)); 2015 WinWriteSingle(AStream, FontEmHeightRatio); 2016 WinWriteLongint(AStream, Resolution); 2017 metric := FontPixelMetric; 2018 WinWriteLongint(AStream, metric.Baseline); 2019 WinWriteLongint(AStream, metric.xLine); 2020 WinWriteLongint(AStream, metric.CapLine); 2021 WinWriteLongint(AStream, metric.DescentLine); 2022 WinWriteLongint(AStream, metric.Lineheight); 2023 end; 2024 2025 procedure TBGRAVectorizedFont.ReadAdditionalHeader(AStream: TStream); 2026 var Header: TBGRAVectorizedFontHeader; 2027 begin 2028 inherited ReadAdditionalHeader(AStream); 2029 Header := ReadVectorizedFontHeader(AStream); 2030 FName := Header.Name; 2031 FStyle := Header.Style; 2032 if header.EmHeightRatio <> 0 then 2033 begin 2034 FFontEmHeightRatio := Header.EmHeightRatio; 2035 FFontEmHeightRatioComputed := true; 2036 end else 2037 begin 2038 FFontEmHeightRatio := 1; 2039 FFontEmHeightRatioComputed := false; 2040 end; 2041 FFontPixelMetric := Header.PixelMetric; 2042 FFontPixelMetricComputed := True; 2043 if FFont = nil then 2044 FResolution := Header.Resolution; 2045 end; 2046 2047 function TBGRAVectorizedFont.ReadVectorizedFontHeader(AStream: TStream): TBGRAVectorizedFontHeader; 2048 var lNameLength: integer; 2049 begin 2050 lNameLength := WinReadLongint(AStream); 2051 setlength(result.Name, lNameLength); 2052 AStream.Read(result.Name[1],length(result.Name)); 2053 result.Style := TFontStyles(WinReadLongint(AStream)); 2054 result.EmHeightRatio:= WinReadSingle(AStream); 2055 result.Resolution := WinReadLongint(AStream); 2056 result.PixelMetric.Baseline := WinReadLongint(AStream); 2057 result.PixelMetric.xLine := WinReadLongint(AStream); 2058 result.PixelMetric.CapLine := WinReadLongint(AStream); 2059 result.PixelMetric.DescentLine := WinReadLongint(AStream); 2060 result.PixelMetric.Lineheight := WinReadLongint(AStream); 2061 result.PixelMetric.Defined := result.PixelMetric.Lineheight > 0; 2062 end; 2063 2064 function TBGRAVectorizedFont.HeaderName: string; 2065 begin 2066 Result:= 'TBGRAVectorizedFont'; 2067 end; 2068 2069 procedure TBGRAVectorizedFont.SetDirectory(const AValue: string); 2070 begin 2071 if Trim(AValue) = Trim(FDirectory) then exit; 2072 FDirectory := Trim(AValue); 2073 UpdateDirectory; 2074 UpdateFont; 1313 2075 end; 1314 2076
Note:
See TracChangeset
for help on using the changeset viewer.