source: trunk/Packages/bgrabitmap/bgrafreetype.pas

Last change on this file was 2, checked in by chronos, 5 years ago
File size: 23.2 KB
Line 
1unit BGRAFreeType;
2
3{$mode objfpc}{$H+}
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 define the default FreeType font collection
14 >> using EasyLazFreeType 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
26interface
27
28{$i bgrabitmap.inc}
29
30uses
31 Types, Classes, SysUtils, BGRAGraphics, BGRABitmapTypes, EasyLazFreeType, FPimage,
32 BGRACustomTextFX, BGRAPhongTypes;
33
34type
35 TBGRAFreeTypeDrawer = class;
36
37 //this is the class to assign to FontRenderer property of TBGRABitmap
38 { TBGRAFreeTypeFontRenderer }
39
40 TBGRAFreeTypeFontRenderer = class(TBGRACustomFontRenderer)
41 private
42 FDrawer: TBGRAFreeTypeDrawer;
43 FFont: TFreeTypeFont;
44 function GetCollection: TCustomFreeTypeFontCollection;
45 function GetDrawer(ASurface: TBGRACustomBitmap): TBGRAFreeTypeDrawer;
46 function GetShaderLightPosition: TPoint;
47 procedure SetShaderLightPosition(AValue: TPoint);
48 protected
49 FShaderOwner: boolean;
50 FShader: TCustomPhongShading;
51 procedure UpdateFont;
52 procedure Init;
53 procedure TextOutAnglePatch(ADest: TBGRACustomBitmap; x, y: single; orientation: integer; s: string;
54 c: TBGRAPixel; tex: IBGRAScanner; align: TAlignment);
55 public
56 FontHinted: boolean;
57
58 ShaderActive: boolean;
59
60 ShadowVisible: boolean;
61 ShadowColor: TBGRAPixel;
62 ShadowRadius: integer;
63 ShadowOffset: TPoint;
64 ShadowQuality: TRadialBlurType;
65
66 OutlineColor: TBGRAPixel;
67 OutlineVisible,OuterOutlineOnly: boolean;
68 OutlineTexture: IBGRAScanner;
69
70 constructor Create; overload;
71 constructor Create(AShader: TCustomPhongShading; AShaderOwner: boolean); overload;
72 function GetFontPixelMetric: TFontPixelMetric; override;
73 procedure TextOutAngle(ADest: TBGRACustomBitmap; x, y: single; orientation: integer; s: string; c: TBGRAPixel; align: TAlignment); overload; override;
74 procedure TextOutAngle(ADest: TBGRACustomBitmap; x, y: single; orientation: integer; s: string; texture: IBGRAScanner; align: TAlignment); overload; override;
75 procedure TextOut(ADest: TBGRACustomBitmap; x, y: single; s: string; texture: IBGRAScanner; align: TAlignment); overload; override;
76 procedure TextOut(ADest: TBGRACustomBitmap; x, y: single; s: string; c: TBGRAPixel; align: TAlignment); overload; override;
77 procedure TextRect(ADest: TBGRACustomBitmap; ARect: TRect; x, y: integer; s: string; style: TTextStyle; c: TBGRAPixel); overload; override;
78 procedure TextRect(ADest: TBGRACustomBitmap; ARect: TRect; x, y: integer; s: string; style: TTextStyle; texture: IBGRAScanner); overload; override;
79 function TextSize(s: string): TSize; overload; override;
80 function TextSize(sUTF8: string; AMaxWidth: integer; {%H-}ARightToLeft: boolean): TSize; overload; override;
81 function TextFitInfo(sUTF8: string; AMaxWidth: integer): integer; override;
82 destructor Destroy; override;
83 property Collection: TCustomFreeTypeFontCollection read GetCollection;
84 property ShaderLightPosition: TPoint read GetShaderLightPosition write SetShaderLightPosition;
85 end;
86
87 { TBGRAFreeTypeDrawer }
88
89 TBGRAFreeTypeDrawer = class(TFreeTypeDrawer)
90 private
91 FMask: TBGRACustomBitmap;
92 FColor: TBGRAPixel;
93 FInCreateTextEffect: boolean;
94 procedure RenderDirectly(x, y, tx: integer; data: pointer);
95 procedure RenderDirectlyClearType(x, y, tx: integer; data: pointer);
96 function ShadowActuallyVisible :boolean;
97 function OutlineActuallyVisible: boolean;
98 function ShaderActuallyActive : boolean;
99 public
100 Destination: TBGRACustomBitmap;
101 ClearTypeRGBOrder: boolean;
102 Texture: IBGRAScanner;
103
104 Shader: TCustomPhongShading;
105 ShaderActive: boolean;
106
107 ShadowVisible: boolean;
108 ShadowColor: TBGRAPixel;
109 ShadowRadius: integer;
110 ShadowOffset: TPoint;
111 ShadowQuality: TRadialBlurType;
112
113 OutlineColor: TBGRAPixel;
114 OutlineVisible,OuterOutlineOnly: boolean;
115 OutlineTexture: IBGRAScanner;
116
117 constructor Create(ADestination: TBGRACustomBitmap);
118 procedure DrawText(AText: string; AFont: TFreeTypeRenderableFont; x,y: single; AColor: TFPColor); overload; override;
119 procedure DrawText(AText: string; AFont: TFreeTypeRenderableFont; x,y: single; AColor: TBGRAPixel); overload;
120 procedure DrawText(AText: string; AFont: TFreeTypeRenderableFont; x,y: single; AColor: TBGRAPixel; AAlign: TFreeTypeAlignments); overload;
121 { If this code does not compile, you probably have an older version of Lazarus. To fix the problem,
122 go into "bgrabitmap.inc" and comment the compiler directives }
123 {$IFDEF BGRABITMAP_USE_LCL12}
124 procedure DrawTextWordBreak(AText: string; AFont: TFreeTypeRenderableFont; x, y, AMaxWidth: Single; AColor: TBGRAPixel; AAlign: TFreeTypeAlignments); overload;
125 procedure DrawTextRect(AText: string; AFont: TFreeTypeRenderableFont; X1,Y1,X2,Y2: Single; AColor: TBGRAPixel; AAlign: TFreeTypeAlignments); overload;
126 {$ENDIF}
127 {$IFDEF BGRABITMAP_USE_LCL15}
128 procedure DrawGlyph(AGlyph: integer; AFont: TFreeTypeRenderableFont; x,y: single; AColor: TFPColor); overload; override;
129 procedure DrawGlyph(AGlyph: integer; AFont: TFreeTypeRenderableFont; x,y: single; AColor: TBGRAPixel); overload;
130 procedure DrawGlyph(AGlyph: integer; AFont: TFreeTypeRenderableFont; x,y: single; AColor: TBGRAPixel; AAlign: TFreeTypeAlignments); overload;
131 {$ENDIF}
132 function CreateTextEffect(AText: string; AFont: TFreeTypeRenderableFont): TBGRACustomTextEffect;
133 destructor Destroy; override;
134 end;
135
136
137implementation
138
139uses BGRABlend, Math, BGRATransform;
140
141{ TBGRAFreeTypeFontRenderer }
142
143function TBGRAFreeTypeFontRenderer.GetCollection: TCustomFreeTypeFontCollection;
144begin
145 result := EasyLazFreeType.FontCollection;
146end;
147
148function TBGRAFreeTypeFontRenderer.GetDrawer(ASurface: TBGRACustomBitmap): TBGRAFreeTypeDrawer;
149begin
150 result := FDrawer;
151 result.ShadowColor := ShadowColor;
152 result.ShadowOffset := ShadowOffset;
153 result.ShadowRadius := ShadowRadius;
154 result.ShadowVisible := ShadowVisible;
155 result.ShadowQuality := ShadowQuality;
156 result.ClearTypeRGBOrder := FontQuality <> fqFineClearTypeBGR;
157 result.Destination := ASurface;
158 result.OutlineColor := OutlineColor;
159 result.OutlineVisible := OutlineVisible;
160 result.OuterOutlineOnly := OuterOutlineOnly;
161 result.OutlineTexture := OutlineTexture;
162 if ShaderActive then result.Shader := FShader
163 else result.Shader := nil;
164end;
165
166function TBGRAFreeTypeFontRenderer.GetShaderLightPosition: TPoint;
167begin
168 if FShader = nil then
169 result := point(0,0)
170 else
171 result := FShader.LightPosition;
172end;
173
174procedure TBGRAFreeTypeFontRenderer.SetShaderLightPosition(AValue: TPoint);
175begin
176 if FShader <> nil then
177 FShader.LightPosition := AValue;
178end;
179
180procedure TBGRAFreeTypeFontRenderer.UpdateFont;
181var fts: TFreeTypeStyles;
182 filename: string;
183begin
184 fts := [];
185 if fsBold in FontStyle then fts += [ftsBold];
186 if fsItalic in FontStyle then fts += [ftsItalic];
187 try
188 filename := FontName;
189 {$IFDEF BGRABITMAP_USE_LCL12}
190 FFont.SetNameAndStyle(filename,fts);
191 {$ELSE}
192 FFont.Name := filename;
193 FFont.Style := fts;
194 {$ENDIF}
195 except
196 on ex: exception do
197 begin
198 end;
199 end;
200 if FontEmHeight >= 0 then
201 FFont.SizeInPixels := FontEmHeight
202 else
203 FFont.LineFullHeight := -FontEmHeight;
204 case FontQuality of
205 fqSystem:
206 begin
207 FFont.Quality := grqMonochrome;
208 FFont.ClearType := false;
209 end;
210 fqSystemClearType:
211 begin
212 FFont.Quality:= grqLowQuality;
213 FFont.ClearType:= true;
214 end;
215 fqFineAntialiasing:
216 begin
217 FFont.Quality:= grqHighQuality;
218 FFont.ClearType:= false;
219 end;
220 fqFineClearTypeRGB,fqFineClearTypeBGR:
221 begin
222 FFont.Quality:= grqHighQuality;
223 FFont.ClearType:= true;
224 end;
225 end;
226 FFont.Hinted := FontHinted;
227 {$IFDEF BGRABITMAP_USE_LCL12}
228 FFont.StrikeOutDecoration := fsStrikeOut in FontStyle;
229 FFont.UnderlineDecoration := fsUnderline in FontStyle;
230 {$ENDIF}
231end;
232
233procedure TBGRAFreeTypeFontRenderer.Init;
234begin
235 ShaderActive := true;
236
237 FDrawer := TBGRAFreeTypeDrawer.Create(nil);
238 FFont := TFreeTypeFont.Create;
239 FontHinted:= True;
240
241 ShadowColor := BGRABlack;
242 ShadowVisible := false;
243 ShadowOffset := Point(5,5);
244 ShadowRadius := 5;
245 ShadowQuality:= rbFast;
246end;
247
248procedure TBGRAFreeTypeFontRenderer.TextOutAnglePatch(ADest: TBGRACustomBitmap;
249 x, y: single; orientation: integer; s: string; c: TBGRAPixel;
250 tex: IBGRAScanner; align: TAlignment);
251const orientationToDeg = -0.1;
252var
253 temp: TBGRACustomBitmap;
254 coord: TPointF;
255 angleDeg: single;
256 OldOrientation: integer;
257 filter: TResampleFilter;
258 OldFontQuality: TBGRAFontQuality;
259begin
260 OldOrientation := FontOrientation;
261 FontOrientation:= 0;
262 OldFontQuality := FontQuality;
263
264 if FontQuality in[fqFineClearTypeRGB,fqFineClearTypeBGR] then FontQuality:= fqFineAntialiasing
265 else if FontQuality = fqSystemClearType then FontQuality:= fqSystem;
266
267 temp := BGRABitmapFactory.Create;
268 with TextSize(s) do
269 temp.SetSize(cx,cy);
270 temp.FillTransparent;
271 if tex<>nil then
272 TextOut(temp,0,0, s, tex, taLeftJustify)
273 else
274 TextOut(temp,0,0, s, c, taLeftJustify);
275
276 orientation:= orientation mod 3600;
277 if orientation < 0 then orientation += 3600;
278
279 angleDeg := orientation * orientationToDeg;
280 coord := PointF(x,y);
281 case align of
282 taRightJustify: coord -= AffineMatrixRotationDeg(angleDeg)*PointF(temp.Width,0);
283 taCenter: coord -= AffineMatrixRotationDeg(angleDeg)*PointF(temp.Width,0)*0.5;
284 end;
285 case orientation of
286 0,900,1800,2700: filter := rfBox;
287 else filter := rfCosine;
288 end;
289 ADest.PutImageAngle(coord.x,coord.y, temp, angleDeg, filter);
290 temp.Free;
291
292 FontOrientation:= OldOrientation;
293 FontQuality:= OldFontQuality;
294end;
295
296constructor TBGRAFreeTypeFontRenderer.Create;
297begin
298 Init;
299end;
300
301constructor TBGRAFreeTypeFontRenderer.Create(AShader: TCustomPhongShading;
302 AShaderOwner: boolean);
303begin
304 Init;
305 FShader := AShader;
306 FShaderOwner := AShaderOwner;
307end;
308
309function TBGRAFreeTypeFontRenderer.GetFontPixelMetric: TFontPixelMetric;
310begin
311 UpdateFont;
312 result.Baseline := round(FFont.Ascent);
313 result.CapLine:= round(FFont.Ascent*0.2);
314 result.DescentLine:= round(FFont.Ascent+FFont.Descent);
315 result.Lineheight := round(FFont.LineFullHeight);
316 result.xLine := round(FFont.Ascent*0.45);
317 result.Defined := True;
318end;
319
320procedure TBGRAFreeTypeFontRenderer.TextOutAngle(ADest: TBGRACustomBitmap; x,
321 y: single; orientation: integer; s: string; c: TBGRAPixel; align: TAlignment);
322begin
323 TextOutAnglePatch(ADest, x,y, orientation, s, c, nil, align);
324{procedure TForm1.TextOutAnglePatch(ADest: TBGRABitmap;
325 x, y: single; orientationTenthDegCCW: integer;
326 s: string; c: TBGRAPixel; AAlign: TAlignment; AResampleFilter: TResampleFilter);
327const orientationToDeg = -0.1;
328var
329 temp: TBGRABitmap;
330 coord: TPointF;
331 angleDeg: single;
332begin
333 temp := TBGRABitmap.Create;
334 ADest.CopyPropertiesTo(temp);
335 temp.FontOrientation := 0;
336 with temp.TextSize(s) do
337 temp.SetSize(cx,cy);
338 temp.FillTransparent;
339+
340 temp.TextOut(0,0, s, c);
341
342 angleDeg := orientationTenthDegCCW * orientationToDeg;
343 coord := PointF(x,y);
344 case AAlign of
345 taRightJustify: coord -= AffineMatrixRotationDeg(angleDeg)*PointF(temp.Width,0);
346 taCenter: coord -= AffineMatrixRotationDeg(angleDeg)*PointF(temp.Width,0)*0.5;
347 end;
348
349 ADest.PutImageAngle(coord.x,coord.y, temp, angleDeg, rfBox);
350 temp.Free;
351end; }
352
353end;
354
355procedure TBGRAFreeTypeFontRenderer.TextOutAngle(ADest: TBGRACustomBitmap; x,
356 y: single; orientation: integer; s: string; texture: IBGRAScanner;
357 align: TAlignment);
358begin
359 TextOutAnglePatch(ADest, x,y, orientation, s, BGRAPixelTransparent, texture, align);
360end;
361
362procedure TBGRAFreeTypeFontRenderer.TextOut(ADest: TBGRACustomBitmap; x,
363 y: single; s: string; texture: IBGRAScanner; align: TAlignment);
364begin
365 FDrawer.Texture := texture;
366 TextOut(ADest,x,y,s,BGRAWhite,align);
367 FDrawer.Texture := nil;
368end;
369
370procedure TBGRAFreeTypeFontRenderer.TextOut(ADest: TBGRACustomBitmap; x,
371 y: single; s: string; c: TBGRAPixel; align: TAlignment);
372var
373 ftaAlign: TFreeTypeAlignments;
374begin
375 UpdateFont;
376 ftaAlign:= [ftaTop];
377 case align of
378 taLeftJustify: ftaAlign += [ftaLeft];
379 taCenter: ftaAlign += [ftaCenter];
380 taRightJustify: ftaAlign += [ftaRight];
381 end;
382 GetDrawer(ADest).DrawText(s,FFont,x,y,BGRAToFPColor(c),ftaAlign);
383end;
384
385procedure TBGRAFreeTypeFontRenderer.TextRect(ADest: TBGRACustomBitmap;
386 ARect: TRect; x, y: integer; s: string; style: TTextStyle; c: TBGRAPixel);
387var align: TFreeTypeAlignments;
388 intersectedClip,previousClip: TRect;
389begin
390 previousClip := ADest.ClipRect;
391 if style.Clipping then
392 begin
393 intersectedClip := rect(0,0,0,0);
394 if not IntersectRect(intersectedClip, previousClip, ARect) then exit;
395 ADest.ClipRect := intersectedClip;
396 end;
397 UpdateFont;
398 align := [];
399 case style.Alignment of
400 taCenter: begin ARect.Left := x; align += [ftaCenter]; end;
401 taRightJustify: begin ARect.Left := x; align += [ftaRight]; end;
402 else
403 align += [ftaLeft];
404 end;
405 case style.Layout of
406 {$IFDEF BGRABITMAP_USE_LCL12}
407 tlCenter: begin ARect.Top := y; align += [ftaVerticalCenter]; end;
408 {$ENDIF}
409 tlBottom: begin ARect.top := y; align += [ftaBottom]; end;
410 else align += [ftaTop];
411 end;
412 try
413 {$IFDEF BGRABITMAP_USE_LCL12}
414 if style.Wordbreak then
415 GetDrawer(ADest).DrawTextRect(s, FFont, ARect.Left,ARect.Top,ARect.Right,ARect.Bottom,BGRAToFPColor(c),align)
416 else
417 {$ENDIF}
418 begin
419 case style.Layout of
420 tlCenter: y := (ARect.Top+ARect.Bottom) div 2;
421 tlBottom: y := ARect.Bottom;
422 else
423 y := ARect.Top;
424 end;
425 case style.Alignment of
426 taLeftJustify: GetDrawer(ADest).DrawText(s,FFont,ARect.Left,y,BGRAToFPColor(c),align);
427 taCenter: GetDrawer(ADest).DrawText(s,FFont,(ARect.Left+ARect.Right-1) div 2,y,BGRAToFPColor(c),align);
428 taRightJustify: GetDrawer(ADest).DrawText(s,FFont,ARect.Right,y,BGRAToFPColor(c),align);
429 end;
430 end;
431 finally
432 if style.Clipping then
433 ADest.ClipRect := previousClip;
434 end;
435end;
436
437procedure TBGRAFreeTypeFontRenderer.TextRect(ADest: TBGRACustomBitmap;
438 ARect: TRect; x, y: integer; s: string; style: TTextStyle;
439 texture: IBGRAScanner);
440begin
441 FDrawer.Texture := texture;
442 TextRect(ADest,ARect,x,y,s,style,BGRAWhite);
443 FDrawer.Texture := nil;
444end;
445
446function TBGRAFreeTypeFontRenderer.TextSize(s: string): TSize;
447begin
448 UpdateFont;
449 result.cx := round(FFont.TextWidth(s));
450 result.cy := round(FFont.LineFullHeight);
451end;
452
453function TBGRAFreeTypeFontRenderer.TextSize(sUTF8: string; AMaxWidth: integer;
454 ARightToLeft: boolean): TSize;
455var
456 remains: string;
457 w,h,totalH: single;
458begin
459 UpdateFont;
460
461 result.cx := 0;
462 totalH := 0;
463 h := FFont.LineFullHeight;
464 repeat
465 FFont.SplitText(sUTF8, AMaxWidth, remains);
466 w := FFont.TextWidth(sUTF8);
467 if round(w)>result.cx then result.cx := round(w);
468 totalH += h;
469 sUTF8 := remains;
470 until remains = '';
471 result.cy := ceil(totalH);
472end;
473
474function TBGRAFreeTypeFontRenderer.TextFitInfo(sUTF8: string; AMaxWidth: integer): integer;
475var
476 remains: string;
477begin
478 UpdateFont;
479 FFont.SplitText(sUTF8, AMaxWidth, remains);
480 result := length(sUTF8);
481end;
482
483destructor TBGRAFreeTypeFontRenderer.Destroy;
484begin
485 FDrawer.Free;
486 FFont.Free;
487 if FShaderOwner then FShader.Free;
488 inherited Destroy;
489end;
490
491{ TBGRAFreeTypeDrawer }
492
493procedure TBGRAFreeTypeDrawer.RenderDirectly( x,y,tx: integer;
494 data: pointer );
495var psrc: pbyte;
496 pdest: PBGRAPixel;
497 c: TBGRAPixel;
498begin
499 if Destination <> nil then
500 begin
501 //ensure rendering in bounds
502 if (y < 0) or (y >= Destination.height) or (x < 0) or (x > Destination.width-tx) then exit;
503
504 psrc := pbyte(data);
505 pdest := Destination.ScanLine[y]+x;
506 if Texture = nil then
507 begin
508 c := FColor;
509 while tx > 0 do
510 begin
511 DrawPixelInlineWithAlphaCheck(pdest,c,psrc^);
512 inc(psrc);
513 inc(pdest);
514 dec(tx);
515 end;
516 end else
517 begin
518 Texture.ScanMoveTo(x,y);
519 while tx > 0 do
520 begin
521 DrawPixelInlineWithAlphaCheck(pdest,Texture.ScanNextPixel,psrc^);
522 inc(psrc);
523 inc(pdest);
524 dec(tx);
525 end;
526 end;
527 end;
528end;
529
530procedure TBGRAFreeTypeDrawer.RenderDirectlyClearType(x, y, tx: integer; data: pointer);
531var xb: integer;
532 psrc: pbyte;
533 pdest: PBGRAPixel;
534begin
535 if Destination <> nil then
536 begin
537 tx := tx div 3;
538 if tx=0 then exit;
539 if (FMask <> nil) and (FMask.Width <> tx) then
540 FMask.SetSize(tx,1)
541 else if FMask = nil then FMask := BGRABitmapFactory.create(tx,1);
542
543 pdest := FMask.Data;
544 psrc := pbyte(data);
545 pdest^.red := (psrc^ + psrc^ + (psrc+1)^) div 3;
546 pdest^.green := (psrc^+ (psrc+1)^ + (psrc+2)^) div 3;
547 if tx > 1 then
548 pdest^.blue := ((psrc+1)^ + (psrc+2)^ + (psrc+3)^) div 3
549 else
550 pdest^.blue := ((psrc+1)^ + (psrc+2)^ + (psrc+2)^) div 3;
551 inc(pdest);
552 inc(psrc,3);
553 for xb := 1 to tx-2 do
554 begin
555 pdest^.red := ((psrc-1)^+ psrc^ + (psrc+1)^) div 3;
556 pdest^.green := (psrc^+ (psrc+1)^ + (psrc+2)^) div 3;
557 pdest^.blue := ((psrc+1)^ + (psrc+2)^ + (psrc+3)^) div 3;
558 inc(pdest);
559 inc(psrc,3);
560 end;
561 if tx > 1 then
562 begin
563 pdest^.red := ((psrc-1)^+ psrc^ + (psrc+1)^) div 3;
564 pdest^.green := (psrc^+ (psrc+1)^ + (psrc+2)^) div 3;
565 pdest^.blue := ((psrc+1)^ + (psrc+2)^ + (psrc+2)^) div 3;
566 end;
567 BGRAFillClearTypeRGBMask(Destination,x div 3,y,FMask,FColor,Texture,ClearTypeRGBOrder);
568 end;
569end;
570
571function TBGRAFreeTypeDrawer.ShadowActuallyVisible: boolean;
572begin
573 result := ShadowVisible and (ShadowColor.alpha <> 0);
574end;
575
576function TBGRAFreeTypeDrawer.OutlineActuallyVisible: boolean;
577begin
578 result := ((OutlineTexture <> nil) or (OutlineColor.alpha <> 0)) and OutlineVisible;
579end;
580
581function TBGRAFreeTypeDrawer.ShaderActuallyActive: boolean;
582begin
583 result := (Shader <> nil) and ShaderActive;
584end;
585
586constructor TBGRAFreeTypeDrawer.Create(ADestination: TBGRACustomBitmap);
587begin
588 Destination := ADestination;
589 ClearTypeRGBOrder:= true;
590 ShaderActive := true;
591 ShadowQuality:= rbFast;
592end;
593
594procedure TBGRAFreeTypeDrawer.DrawText(AText: string;
595 AFont: TFreeTypeRenderableFont; x, y: single; AColor: TFPColor);
596var fx: TBGRACustomTextEffect;
597 procedure DoOutline;
598 begin
599 if OutlineActuallyVisible then
600 begin
601 if OutlineTexture <> nil then
602 fx.DrawOutline(Destination,round(x),round(y), OutlineTexture)
603 else
604 fx.DrawOutline(Destination,round(x),round(y), OutlineColor);
605 end;
606 end;
607begin
608 if not FInCreateTextEffect and (ShadowActuallyVisible or OutlineActuallyVisible or ShaderActuallyActive) then
609 begin
610 fx := CreateTextEffect(AText, AFont);
611 fx.ShadowQuality := ShadowQuality;
612 y -= AFont.Ascent;
613 if ShadowActuallyVisible then fx.DrawShadow(Destination, round(x+ShadowOffset.X),round(y+ShadowOffset.Y), ShadowRadius, ShadowColor);
614 if OuterOutlineOnly then DoOutline;
615
616 if texture <> nil then
617 begin
618 if ShaderActuallyActive then
619 fx.DrawShaded(Destination,floor(x),floor(y), Shader, round(fx.TextSize.cy*0.05), texture)
620 else
621 fx.Draw(Destination,round(x),round(y), texture);
622 end else
623 begin
624 if ShaderActuallyActive then
625 fx.DrawShaded(Destination,floor(x),floor(y), Shader, round(fx.TextSize.cy*0.05), FPColorToBGRA(AColor))
626 else
627 fx.Draw(Destination,round(x),round(y), FPColorToBGRA(AColor));
628 end;
629 if not OuterOutlineOnly then DoOutline;
630 fx.Free;
631 end else
632 begin
633 FColor := FPColorToBGRA(AColor);
634 if AFont.ClearType then
635 AFont.RenderText(AText, x, y, Destination.ClipRect, @RenderDirectlyClearType)
636 else
637 AFont.RenderText(AText, x, y, Destination.ClipRect, @RenderDirectly);
638 end;
639end;
640
641procedure TBGRAFreeTypeDrawer.DrawText(AText: string;
642 AFont: TFreeTypeRenderableFont; x, y: single; AColor: TBGRAPixel);
643begin
644 DrawText(AText, AFont, x,y, BGRAToFPColor(AColor));
645end;
646
647procedure TBGRAFreeTypeDrawer.DrawText(AText: string;
648 AFont: TFreeTypeRenderableFont; x, y: single; AColor: TBGRAPixel;
649 AAlign: TFreeTypeAlignments);
650begin
651 DrawText(AText, AFont, x,y, BGRAToFPColor(AColor), AAlign);
652end;
653
654{$IFDEF BGRABITMAP_USE_LCL12}
655procedure TBGRAFreeTypeDrawer.DrawTextWordBreak(AText: string;
656 AFont: TFreeTypeRenderableFont; x, y, AMaxWidth: Single; AColor: TBGRAPixel;
657 AAlign: TFreeTypeAlignments);
658begin
659 DrawTextWordBreak(AText,AFont,x,y,AMaxWidth,BGRAToFPColor(AColor),AAlign);
660end;
661
662procedure TBGRAFreeTypeDrawer.DrawTextRect(AText: string;
663 AFont: TFreeTypeRenderableFont; X1, Y1, X2, Y2: Single; AColor: TBGRAPixel;
664 AAlign: TFreeTypeAlignments);
665begin
666 DrawTextRect(AText,AFont,X1,Y1,X2,Y2,BGRAToFPColor(AColor),AAlign);
667end;
668{$ENDIF}
669
670{$IFDEF BGRABITMAP_USE_LCL15}
671procedure TBGRAFreeTypeDrawer.DrawGlyph(AGlyph: integer;
672 AFont: TFreeTypeRenderableFont; x, y: single; AColor: TFPColor);
673var f: TFreeTypeFont;
674begin
675 if not (AFont is TFreeTypeFont) then exit;
676 f := TFreeTypeFont(Afont);
677 FColor := FPColorToBGRA(AColor);
678 if AFont.ClearType then
679 f.RenderGlyph(AGlyph, x, y, Destination.ClipRect, @RenderDirectlyClearType)
680 else
681 f.RenderGlyph(AGlyph, x, y, Destination.ClipRect, @RenderDirectly);
682end;
683
684procedure TBGRAFreeTypeDrawer.DrawGlyph(AGlyph: integer;
685 AFont: TFreeTypeRenderableFont; x, y: single; AColor: TBGRAPixel);
686begin
687 DrawGlyph(AGlyph, AFont, x,y, BGRAToFPColor(AColor));
688end;
689
690procedure TBGRAFreeTypeDrawer.DrawGlyph(AGlyph: integer;
691 AFont: TFreeTypeRenderableFont; x, y: single; AColor: TBGRAPixel;
692 AAlign: TFreeTypeAlignments);
693begin
694 DrawGlyph(AGlyph, AFont, x,y, BGRAToFPColor(AColor), AAlign);
695end;
696{$ENDIF}
697
698function TBGRAFreeTypeDrawer.CreateTextEffect(AText: string;
699 AFont: TFreeTypeRenderableFont): TBGRACustomTextEffect;
700var
701 mask: TBGRACustomBitmap;
702 tx,ty,marginHoriz,marginVert: integer;
703 tempDest: TBGRACustomBitmap;
704 tempTex: IBGRAScanner;
705 tempClearType: boolean;
706begin
707 FInCreateTextEffect:= True;
708 try
709 tx := ceil(AFont.TextWidth(AText));
710 ty := ceil(AFont.TextHeight(AText));
711 marginHoriz := ty div 2;
712 marginVert := 1;
713 mask := BGRABitmapFactory.Create(tx+2*marginHoriz,ty+2*marginVert,BGRABlack);
714 tempDest := Destination;
715 tempTex := Texture;
716 tempClearType:= AFont.ClearType;
717 Destination := mask;
718 Texture := nil;
719 AFont.ClearType := false;
720 DrawText(AText,AFont,marginHoriz,marginVert,BGRAWhite,[ftaTop,ftaLeft]);
721 Destination := tempDest;
722 Texture := tempTex;
723 AFont.ClearType := tempClearType;
724 mask.ConvertToLinearRGB;
725 result := TBGRACustomTextEffect.Create(mask, true,tx,ty,point(-marginHoriz,-marginVert));
726 finally
727 FInCreateTextEffect:= false;
728 end;
729end;
730
731destructor TBGRAFreeTypeDrawer.Destroy;
732begin
733 FMask.Free;
734 inherited Destroy;
735end;
736
737end.
Note: See TracBrowser for help on using the repository browser.