Changeset 472 for GraphicTest/Packages/bgrabitmap/bgrafreetype.pas
- Timestamp:
- Apr 9, 2015, 9:58:36 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
GraphicTest/Packages/bgrabitmap/bgrafreetype.pas
r452 r472 3 3 {$mode objfpc}{$H+} 4 4 5 { 6 Font rendering units : BGRAText, BGRATextFX, BGRAVectorize, BGRAFreeType 7 8 This units provide a font renderer with FreeType fonts, using the integrated FreeType font engine in Lazarus. 9 The simplest way to render effects is to use TBGRAFreeTypeFontRenderer class. 10 To do this, create an instance of this class and assign it to a TBGRABitmap.FontRenderer property. Now functions 11 to draw text like TBGRABitmap.TextOut will use the chosen renderer. 12 13 >> Note that you need to defined the default FreeType font collection 14 >> using LazFreeTypeFontCollection unit. 15 16 To set the effects, keep a variable containing 17 the TBGRAFreeTypeFontRenderer class and modify ShadowVisible and other effects parameters. The FontHinted property 18 allows you to choose if the font is snapped to pixels to make it more readable. 19 20 TBGRAFreeTypeDrawer class is the class that provides basic FreeType drawing 21 by deriving the TFreeTypeDrawer type. You can use it directly, but it is not 22 recommended, because there are less text layout parameters. However, it is 23 necessary if you want to create TBGRATextEffect objects using FreeType fonts. 24 } 25 5 26 interface 6 27 7 28 uses 8 Classes, SysUtils, Graphics, BGRABitmapTypes, EasyLazFreeType, FPimage;29 Types, Classes, SysUtils, Graphics, BGRABitmapTypes, EasyLazFreeType, FPimage, BGRAText, BGRATextFX, BGRAPhongTypes, LCLVersion; 9 30 10 31 type 32 TBGRAFreeTypeDrawer = class; 33 34 //this is the class to assign to FontRenderer property of TBGRABitmap 35 { TBGRAFreeTypeFontRenderer } 36 37 TBGRAFreeTypeFontRenderer = class(TBGRACustomFontRenderer) 38 private 39 FDrawer: TBGRAFreeTypeDrawer; 40 FFont: TFreeTypeFont; 41 function GetCollection: TCustomFreeTypeFontCollection; 42 function GetDrawer(ASurface: TBGRACustomBitmap): TBGRAFreeTypeDrawer; 43 function GetShaderLightPosition: TPoint; 44 procedure SetShaderLightPosition(AValue: TPoint); 45 protected 46 FShaderOwner: boolean; 47 FShader: TCustomPhongShading; 48 procedure UpdateFont; 49 procedure Init; 50 public 51 FontHinted: boolean; 52 53 ShaderActive: boolean; 54 55 ShadowVisible: boolean; 56 ShadowColor: TBGRAPixel; 57 ShadowRadius: integer; 58 ShadowOffset: TPoint; 59 60 OutlineColor: TBGRAPixel; 61 OutlineVisible,OuterOutlineOnly: boolean; 62 OutlineTexture: IBGRAScanner; 63 64 constructor Create; 65 constructor Create(AShader: TCustomPhongShading; AShaderOwner: boolean); 66 function GetFontPixelMetric: TFontPixelMetric; override; 67 procedure TextOutAngle({%H-}ADest: TBGRACustomBitmap; {%H-}x, {%H-}y: single; {%H-}orientation: integer; {%H-}s: string; {%H-}c: TBGRAPixel; {%H-}align: TAlignment); override; 68 procedure TextOutAngle({%H-}ADest: TBGRACustomBitmap; {%H-}x, {%H-}y: single; {%H-}orientation: integer; {%H-}s: string; {%H-}texture: IBGRAScanner; {%H-}align: TAlignment); override; 69 procedure TextOut(ADest: TBGRACustomBitmap; x, y: single; s: string; texture: IBGRAScanner; align: TAlignment); override; 70 procedure TextOut(ADest: TBGRACustomBitmap; x, y: single; s: string; c: TBGRAPixel; align: TAlignment); override; 71 procedure TextRect(ADest: TBGRACustomBitmap; ARect: TRect; x, y: integer; s: string; style: TTextStyle; c: TBGRAPixel); override; 72 procedure TextRect(ADest: TBGRACustomBitmap; ARect: TRect; x, y: integer; s: string; style: TTextStyle; texture: IBGRAScanner); override; 73 function TextSize(s: string): TSize; override; 74 destructor Destroy; override; 75 property Collection: TCustomFreeTypeFontCollection read GetCollection; 76 property ShaderLightPosition: TPoint read GetShaderLightPosition write SetShaderLightPosition; 77 end; 11 78 12 79 { TBGRAFreeTypeDrawer } … … 16 83 FMask: TBGRACustomBitmap; 17 84 FColor: TBGRAPixel; 85 FInCreateTextEffect: boolean; 18 86 procedure RenderDirectly(x, y, tx: integer; data: pointer); 19 87 procedure RenderDirectlyClearType(x, y, tx: integer; data: pointer); 88 function ShadowActuallyVisible :boolean; 89 function OutlineActuallyVisible: boolean; 90 function ShaderActuallyActive : boolean; 20 91 public 21 92 Destination: TBGRACustomBitmap; 22 93 ClearTypeRGBOrder: boolean; 94 Texture: IBGRAScanner; 95 96 Shader: TCustomPhongShading; 97 ShaderActive: boolean; 98 99 ShadowVisible: boolean; 100 ShadowColor: TBGRAPixel; 101 ShadowRadius: integer; 102 ShadowOffset: TPoint; 103 104 OutlineColor: TBGRAPixel; 105 OutlineVisible,OuterOutlineOnly: boolean; 106 OutlineTexture: IBGRAScanner; 107 23 108 constructor Create(ADestination: TBGRACustomBitmap); 24 109 procedure DrawText(AText: string; AFont: TFreeTypeRenderableFont; x,y: single; AColor: TFPColor); override; overload; 25 110 procedure DrawText(AText: string; AFont: TFreeTypeRenderableFont; x,y: single; AColor: TBGRAPixel); overload; 26 111 procedure DrawText(AText: string; AFont: TFreeTypeRenderableFont; x,y: single; AColor: TBGRAPixel; AAlign: TFreeTypeAlignments); overload; 112 function CreateTextEffect(AText: string; AFont: TFreeTypeRenderableFont): TBGRATextEffect; 27 113 destructor Destroy; override; 28 114 end; 29 115 116 30 117 implementation 31 118 32 uses LCLType, BGRABlend, BGRAText; 119 uses LCLType, BGRABlend, Math; 120 121 { TBGRAFreeTypeFontRenderer } 122 123 function TBGRAFreeTypeFontRenderer.GetCollection: TCustomFreeTypeFontCollection; 124 begin 125 result := EasyLazFreeType.FontCollection; 126 end; 127 128 function TBGRAFreeTypeFontRenderer.GetDrawer(ASurface: TBGRACustomBitmap): TBGRAFreeTypeDrawer; 129 begin 130 result := FDrawer; 131 result.ShadowColor := ShadowColor; 132 result.ShadowOffset := ShadowOffset; 133 result.ShadowRadius := ShadowRadius; 134 result.ShadowVisible := ShadowVisible; 135 result.ClearTypeRGBOrder := FontQuality <> fqFineClearTypeBGR; 136 result.Destination := ASurface; 137 result.OutlineColor := OutlineColor; 138 result.OutlineVisible := OutlineVisible; 139 result.OuterOutlineOnly := OuterOutlineOnly; 140 result.OutlineTexture := OutlineTexture; 141 if ShaderActive then result.Shader := FShader 142 else result.Shader := nil; 143 end; 144 145 function TBGRAFreeTypeFontRenderer.GetShaderLightPosition: TPoint; 146 begin 147 if FShader = nil then 148 result := point(0,0) 149 else 150 result := FShader.LightPosition; 151 end; 152 153 procedure TBGRAFreeTypeFontRenderer.SetShaderLightPosition(AValue: TPoint); 154 begin 155 if FShader <> nil then 156 FShader.LightPosition := AValue; 157 end; 158 159 procedure TBGRAFreeTypeFontRenderer.UpdateFont; 160 var fts: TFreeTypeStyles; 161 begin 162 fts := []; 163 if fsBold in FontStyle then fts += [ftsBold]; 164 if fsItalic in FontStyle then fts += [ftsItalic]; 165 try 166 {$IF (lcl_fullversion>=1010000)} 167 FFont.SetNameAndStyle(FontName,fts); 168 {$ELSE} 169 FFont.Name := FontName; 170 FFont.Style := fts; 171 {$ENDIF} 172 except 173 on ex: exception do 174 begin 175 end; 176 end; 177 if FontEmHeight >= 0 then 178 FFont.SizeInPixels := FontEmHeight 179 else 180 FFont.LineFullHeight := -FontEmHeight; 181 case FontQuality of 182 fqSystem: 183 begin 184 FFont.Quality := grqMonochrome; 185 FFont.ClearType := false; 186 end; 187 fqSystemClearType: 188 begin 189 FFont.Quality:= grqLowQuality; 190 FFont.ClearType:= true; 191 end; 192 fqFineAntialiasing: 193 begin 194 FFont.Quality:= grqHighQuality; 195 FFont.ClearType:= false; 196 end; 197 fqFineClearTypeRGB,fqFineClearTypeBGR: 198 begin 199 FFont.Quality:= grqHighQuality; 200 FFont.ClearType:= true; 201 end; 202 end; 203 FFont.Hinted := FontHinted; 204 {$IF (lcl_fullversion>=1010000)} 205 FFont.StrikeOutDecoration := fsStrikeOut in FontStyle; 206 FFont.UnderlineDecoration := fsUnderline in FontStyle; 207 {$ENDIF} 208 end; 209 210 procedure TBGRAFreeTypeFontRenderer.Init; 211 begin 212 ShaderActive := true; 213 214 FDrawer := TBGRAFreeTypeDrawer.Create(nil); 215 FFont := TFreeTypeFont.Create; 216 FontHinted:= True; 217 218 ShadowColor := BGRABlack; 219 ShadowVisible := false; 220 ShadowOffset := Point(5,5); 221 ShadowRadius := 5; 222 end; 223 224 constructor TBGRAFreeTypeFontRenderer.Create; 225 begin 226 Init; 227 end; 228 229 constructor TBGRAFreeTypeFontRenderer.Create(AShader: TCustomPhongShading; 230 AShaderOwner: boolean); 231 begin 232 Init; 233 FShader := AShader; 234 FShaderOwner := AShaderOwner; 235 end; 236 237 function TBGRAFreeTypeFontRenderer.GetFontPixelMetric: TFontPixelMetric; 238 begin 239 UpdateFont; 240 result.Baseline := round(FFont.Ascent); 241 result.CapLine:= round(FFont.Ascent*0.2); 242 result.DescentLine:= round(FFont.Ascent+FFont.Descent); 243 result.Lineheight := round(FFont.LineFullHeight); 244 result.xLine := round(FFont.Ascent*0.45); 245 result.Defined := True; 246 end; 247 248 procedure TBGRAFreeTypeFontRenderer.TextOutAngle(ADest: TBGRACustomBitmap; x, 249 y: single; orientation: integer; s: string; c: TBGRAPixel; align: TAlignment); 250 begin 251 252 end; 253 254 procedure TBGRAFreeTypeFontRenderer.TextOutAngle(ADest: TBGRACustomBitmap; x, 255 y: single; orientation: integer; s: string; texture: IBGRAScanner; 256 align: TAlignment); 257 begin 258 259 end; 260 261 procedure TBGRAFreeTypeFontRenderer.TextOut(ADest: TBGRACustomBitmap; x, 262 y: single; s: string; texture: IBGRAScanner; align: TAlignment); 263 begin 264 FDrawer.Texture := texture; 265 TextOut(ADest,x,y,s,BGRAWhite,align); 266 FDrawer.Texture := nil; 267 end; 268 269 procedure TBGRAFreeTypeFontRenderer.TextOut(ADest: TBGRACustomBitmap; x, 270 y: single; s: string; c: TBGRAPixel; align: TAlignment); 271 var 272 ftaAlign: TFreeTypeAlignments; 273 begin 274 UpdateFont; 275 ftaAlign:= [ftaTop]; 276 case align of 277 taLeftJustify: ftaAlign += [ftaLeft]; 278 taCenter: ftaAlign += [ftaCenter]; 279 taRightJustify: ftaAlign += [ftaRight]; 280 end; 281 GetDrawer(ADest).DrawText(s,FFont,x,y,BGRAToFPColor(c),ftaAlign); 282 end; 283 284 procedure TBGRAFreeTypeFontRenderer.TextRect(ADest: TBGRACustomBitmap; 285 ARect: TRect; x, y: integer; s: string; style: TTextStyle; c: TBGRAPixel); 286 var align: TFreeTypeAlignments; 287 intersectedClip,previousClip: TRect; 288 begin 289 previousClip := ADest.ClipRect; 290 if style.Clipping then 291 begin 292 intersectedClip := rect(0,0,0,0); 293 if not IntersectRect(intersectedClip, previousClip, ARect) then exit; 294 ADest.ClipRect := intersectedClip; 295 end; 296 UpdateFont; 297 align := []; 298 case style.Alignment of 299 taCenter: begin ARect.Left := x; align += [ftaCenter]; end; 300 taRightJustify: begin ARect.Left := x; align += [ftaRight]; end; 301 else 302 align += [ftaLeft]; 303 end; 304 case style.Layout of 305 {$IF (lcl_fullversion>=1010000)} 306 tlCenter: begin ARect.Top := y; align += [ftaVerticalCenter]; end; 307 {$ENDIF} 308 tlBottom: begin ARect.top := y; align += [ftaBottom]; end; 309 else align += [ftaTop]; 310 end; 311 try 312 {$IF (lcl_fullversion>=1010000)} 313 if style.Wordbreak then 314 GetDrawer(ADest).DrawTextRect(s, FFont, ARect.Left,ARect.Top,ARect.Right,ARect.Bottom,BGRAToFPColor(c),align) 315 else 316 {$ENDIF} 317 begin 318 case style.Layout of 319 tlCenter: y := (ARect.Top+ARect.Bottom) div 2; 320 tlBottom: y := ARect.Bottom; 321 else 322 y := ARect.Top; 323 end; 324 case style.Alignment of 325 taLeftJustify: GetDrawer(ADest).DrawText(s,FFont,ARect.Left,y,BGRAToFPColor(c),align); 326 taCenter: GetDrawer(ADest).DrawText(s,FFont,(ARect.Left+ARect.Right-1) div 2,y,BGRAToFPColor(c),align); 327 taRightJustify: GetDrawer(ADest).DrawText(s,FFont,ARect.Right,y,BGRAToFPColor(c),align); 328 end; 329 end; 330 finally 331 if style.Clipping then 332 ADest.ClipRect := previousClip; 333 end; 334 end; 335 336 procedure TBGRAFreeTypeFontRenderer.TextRect(ADest: TBGRACustomBitmap; 337 ARect: TRect; x, y: integer; s: string; style: TTextStyle; 338 texture: IBGRAScanner); 339 begin 340 FDrawer.Texture := texture; 341 TextRect(ADest,ARect,x,y,s,style,BGRAWhite); 342 FDrawer.Texture := nil; 343 end; 344 345 function TBGRAFreeTypeFontRenderer.TextSize(s: string): TSize; 346 begin 347 result.cx := round(FFont.TextWidth(s)); 348 result.cy := round(FFont.LineFullHeight); 349 end; 350 351 destructor TBGRAFreeTypeFontRenderer.Destroy; 352 begin 353 FDrawer.Free; 354 FFont.Free; 355 if FShaderOwner then FShader.Free; 356 inherited Destroy; 357 end; 33 358 34 359 { TBGRAFreeTypeDrawer } … … 45 370 if (y < 0) or (y >= Destination.height) or (x < 0) or (x > Destination.width-tx) then exit; 46 371 47 c := FColor;48 372 psrc := pbyte(data); 49 373 pdest := Destination.ScanLine[y]+x; 50 while tx > 0 do 51 begin 52 DrawPixelInlineWithAlphaCheck(pdest,c,psrc^); 53 inc(psrc); 54 inc(pdest); 55 dec(tx); 374 if Texture = nil then 375 begin 376 c := FColor; 377 while tx > 0 do 378 begin 379 DrawPixelInlineWithAlphaCheck(pdest,c,psrc^); 380 inc(psrc); 381 inc(pdest); 382 dec(tx); 383 end; 384 end else 385 begin 386 Texture.ScanMoveTo(x,y); 387 while tx > 0 do 388 begin 389 DrawPixelInlineWithAlphaCheck(pdest,Texture.ScanNextPixel,psrc^); 390 inc(psrc); 391 inc(pdest); 392 dec(tx); 393 end; 56 394 end; 57 395 end; … … 95 433 pdest^.blue := ((psrc+1)^ + (psrc+2)^ + (psrc+2)^) div 3; 96 434 end; 97 BGRAFillClearTypeRGBMask(Destination,x div 3,y,FMask,FColor,nil,ClearTypeRGBOrder); 98 end; 435 BGRAFillClearTypeRGBMask(Destination,x div 3,y,FMask,FColor,Texture,ClearTypeRGBOrder); 436 end; 437 end; 438 439 function TBGRAFreeTypeDrawer.ShadowActuallyVisible: boolean; 440 begin 441 result := ShadowVisible and (ShadowColor.alpha <> 0); 442 end; 443 444 function TBGRAFreeTypeDrawer.OutlineActuallyVisible: boolean; 445 begin 446 result := ((OutlineTexture <> nil) or (OutlineColor.alpha <> 0)) and OutlineVisible; 447 end; 448 449 function TBGRAFreeTypeDrawer.ShaderActuallyActive: boolean; 450 begin 451 result := (Shader <> nil) and ShaderActive; 99 452 end; 100 453 … … 103 456 Destination := ADestination; 104 457 ClearTypeRGBOrder:= true; 458 ShaderActive := true; 105 459 end; 106 460 107 461 procedure TBGRAFreeTypeDrawer.DrawText(AText: string; 108 462 AFont: TFreeTypeRenderableFont; x, y: single; AColor: TFPColor); 109 begin 110 FColor := FPColorToBGRA(AColor); 111 if AFont.ClearType then 112 AFont.RenderText(AText, x, y, Destination.ClipRect, @RenderDirectlyClearType) 113 else 114 AFont.RenderText(AText, x, y, Destination.ClipRect, @RenderDirectly); 463 var fx: TBGRATextEffect; 464 procedure DoOutline; 465 begin 466 if OutlineActuallyVisible then 467 begin 468 if OutlineTexture <> nil then 469 fx.DrawOutline(Destination,round(x),round(y), OutlineTexture) 470 else 471 fx.DrawOutline(Destination,round(x),round(y), OutlineColor); 472 end; 473 end; 474 begin 475 if not FInCreateTextEffect and (ShadowActuallyVisible or OutlineActuallyVisible or ShaderActuallyActive) then 476 begin 477 fx := CreateTextEffect(AText, AFont); 478 y -= AFont.Ascent; 479 if ShadowActuallyVisible then fx.DrawShadow(Destination, round(x+ShadowOffset.X),round(y+ShadowOffset.Y), ShadowRadius, ShadowColor); 480 if OuterOutlineOnly then DoOutline; 481 482 if texture <> nil then 483 begin 484 if ShaderActuallyActive then 485 fx.DrawShaded(Destination,floor(x),floor(y), Shader, round(fx.TextSize.cy*0.05), texture) 486 else 487 fx.Draw(Destination,round(x),round(y), texture); 488 end else 489 begin 490 if ShaderActuallyActive then 491 fx.DrawShaded(Destination,floor(x),floor(y), Shader, round(fx.TextSize.cy*0.05), FPColorToBGRA(AColor)) 492 else 493 fx.Draw(Destination,round(x),round(y), FPColorToBGRA(AColor)); 494 end; 495 if not OuterOutlineOnly then DoOutline; 496 fx.Free; 497 end else 498 begin 499 FColor := FPColorToBGRA(AColor); 500 if AFont.ClearType then 501 AFont.RenderText(AText, x, y, Destination.ClipRect, @RenderDirectlyClearType) 502 else 503 AFont.RenderText(AText, x, y, Destination.ClipRect, @RenderDirectly); 504 end; 115 505 end; 116 506 … … 128 518 end; 129 519 520 function TBGRAFreeTypeDrawer.CreateTextEffect(AText: string; 521 AFont: TFreeTypeRenderableFont): TBGRATextEffect; 522 var 523 mask: TBGRACustomBitmap; 524 tx,ty,marginHoriz,marginVert: integer; 525 tempDest: TBGRACustomBitmap; 526 tempTex: IBGRAScanner; 527 tempClearType: boolean; 528 begin 529 FInCreateTextEffect:= True; 530 try 531 tx := ceil(AFont.TextWidth(AText)); 532 ty := ceil(AFont.TextHeight(AText)); 533 marginHoriz := ty div 2; 534 marginVert := 1; 535 mask := BGRABitmapFactory.Create(tx+2*marginHoriz,ty+2*marginVert,BGRABlack); 536 tempDest := Destination; 537 tempTex := Texture; 538 tempClearType:= AFont.ClearType; 539 Destination := mask; 540 Texture := nil; 541 AFont.ClearType := false; 542 DrawText(AText,AFont,marginHoriz,marginVert,BGRAWhite,[ftaTop,ftaLeft]); 543 Destination := tempDest; 544 Texture := tempTex; 545 AFont.ClearType := tempClearType; 546 mask.ConvertToLinearRGB; 547 result := TBGRATextEffect.Create(mask, true,tx,ty,point(-marginHoriz,-marginVert)); 548 finally 549 FInCreateTextEffect:= false; 550 end; 551 end; 552 130 553 destructor TBGRAFreeTypeDrawer.Destroy; 131 554 begin
Note:
See TracChangeset
for help on using the changeset viewer.