Ignore:
Timestamp:
Apr 9, 2015, 9:58:36 PM (9 years ago)
Author:
chronos
Message:
  • Fixed: Use csOpaque control style also to Image, PaintBox and OpenGLControl.
  • Modified: Change size of test frame with SpinEdits as delayed using timer.
  • Updated: BRGABitmap package to version 8.1.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • GraphicTest/Packages/bgrabitmap/bgratextfx.pas

    r452 r472  
    33{$mode objfpc}{$H+}
    44
     5{
     6  Font rendering units : BGRAText, BGRATextFX, BGRAVectorize, BGRAFreeType
     7
     8  This unit provide text effects. The simplest way to render effects is to use TBGRATextEffectFontRenderer class.
     9  To do this, create an instance of this class and assign it to a TBGRABitmap.FontRenderer property. Now functions
     10  to draw text like TBGRABitmap.TextOut will use the chosen renderer. To set the effects, keep a variable containing
     11  the TBGRATextEffectFontRenderer class and modify ShadowVisible and other effects parameters.
     12
     13  The TBGRATextEffectFontRenderer class makes use of other classes depending on the situation. For example,
     14  TBGRATextEffect, which is also in this unit, provides effects on a text mask. But the renderer also uses
     15  BGRAVectorize unit in order to have big texts or to rotate them at will.
     16
     17  Note that you may need TBGRATextEffect if you want to have more control over text effects, especially
     18  if you always draw the same text. Keeping the same TBGRATextEffect object will avoid creating the text
     19  mask over and over again.
     20
     21  TextShadow function is a simple function to compute an image containing a text with shadow.
     22
     23}
     24
    525interface
    626
    727uses
    8   Classes, SysUtils, Graphics, Types, BGRABitmapTypes, BGRAPhongTypes;
     28  Classes, SysUtils, Graphics, Types, BGRABitmapTypes, BGRAPhongTypes, BGRAText, BGRAVectorize;
    929
    1030type
     31  TBGRATextEffect = class;
     32
     33  { TBGRATextEffectFontRenderer }
     34
     35  TBGRATextEffectFontRenderer = class(TCustomLCLFontRenderer)
     36  private
     37    function GetShaderLightPosition: TPoint;
     38    function GetVectorizedRenderer: TBGRAVectorizedFontRenderer;
     39    procedure SetShaderLightPosition(AValue: TPoint);
     40  protected
     41    FShaderOwner: boolean;
     42    FShader: TCustomPhongShading;
     43    FVectorizedRenderer: TBGRAVectorizedFontRenderer;
     44    function ShadowActuallyVisible :boolean;
     45    function ShaderActuallyActive: boolean;
     46    function OutlineActuallyVisible: boolean;
     47    procedure Init;
     48    function VectorizedFontNeeded: boolean;
     49    procedure InternalTextOut(ADest: TBGRACustomBitmap; x, y: single; s: string; c: TBGRAPixel; texture: IBGRAScanner; align: TAlignment);
     50  public
     51    ShaderActive: boolean;
     52
     53    ShadowVisible: boolean;
     54    ShadowColor: TBGRAPixel;
     55    ShadowRadius: integer;
     56    ShadowOffset: TPoint;
     57    ShadowQuality: TRadialBlurType;
     58
     59    OutlineColor: TBGRAPixel;
     60    OutlineWidth: single;
     61    OutlineVisible,OuterOutlineOnly: boolean;
     62    OutlineTexture: IBGRAScanner;
     63    constructor Create;
     64    constructor Create(AShader: TCustomPhongShading; AShaderOwner: boolean);
     65    destructor Destroy; override;
     66    procedure TextOutAngle(ADest: TBGRACustomBitmap; x, y: single; orientation: integer;
     67      s: string; texture: IBGRAScanner; align: TAlignment); override;
     68    procedure TextOutAngle(ADest: TBGRACustomBitmap; x, y: single; orientation: integer;
     69      s: string; c: TBGRAPixel; align: TAlignment); override;
     70    procedure TextOut(ADest: TBGRACustomBitmap; x, y: single; s: string;
     71      texture: IBGRAScanner; align: TAlignment); override;
     72    procedure TextOut(ADest: TBGRACustomBitmap; x, y: single; s: string; c: TBGRAPixel;
     73      align: TAlignment); override;
     74    function TextSize(sUTF8: string): TSize; override;
     75    property Shader: TCustomPhongShading read FShader;
     76    property ShaderLightPosition: TPoint read GetShaderLightPosition write SetShaderLightPosition;
     77    property VectorizedFontRenderer: TBGRAVectorizedFontRenderer read GetVectorizedRenderer;
     78  end;
    1179
    1280  { TBGRATextEffect }
     
    1482  TBGRATextEffect = class
    1583  private
     84    FShadowQuality: TRadialBlurType;
    1685    function GetBounds: TRect;
    17     function GetHeight: integer;
     86    function GetMaskHeight: integer;
     87    class function GetOutlineWidth: integer; static;
    1888    function GetShadowBounds(ARadius: integer): TRect;
    19     function GetWidth: integer;
     89    function GetMaskWidth: integer;
     90    function GetTextHeight: integer;
     91    function GetTextWidth: integer;
     92    procedure SetShadowQuality(AValue: TRadialBlurType);
    2093  protected
    2194    FTextMask: TBGRACustomBitmap;
     
    2497    FShadingAltitude: integer;
    2598    FShadingRounded: boolean;
    26     FWidth,FHeight: integer;
     99    FTextSize: TSize;
    27100    FOffset: TPoint;
    28     procedure DrawMaskMulticolored(ADest: TBGRACustomBitmap; AMask: TBGRACustomBitmap; X,Y: Integer; const AColors: array of TBGRAPixel);
    29     procedure DrawMask(ADest: TBGRACustomBitmap; AMask: TBGRACustomBitmap; X,Y: Integer; AColor: TBGRAPixel);
    30     procedure DrawMask(ADest: TBGRACustomBitmap; AMask: TBGRACustomBitmap; X,Y: Integer; ATexture: IBGRAScanner);
     101    function DrawMaskMulticolored(ADest: TBGRACustomBitmap; AMask: TBGRACustomBitmap; X,Y: Integer; const AColors: array of TBGRAPixel): TRect;
     102    function DrawMask(ADest: TBGRACustomBitmap; AMask: TBGRACustomBitmap; X,Y: Integer; AColor: TBGRAPixel): TRect;
     103    function DrawMask(ADest: TBGRACustomBitmap; AMask: TBGRACustomBitmap; X,Y: Integer; ATexture: IBGRAScanner): TRect;
    31104    function InternalDrawShaded(ADest: TBGRACustomBitmap; X,Y: integer; Shader: TCustomPhongShading; Altitude: integer; AColor: TBGRAPixel; ATexture: IBGRAScanner; ARounded: Boolean): TRect;
     105    procedure InitImproveReadability(AText: string; Font: TFont; SubOffsetX,SubOffsetY: single);
    32106    procedure Init(AText: string; Font: TFont; Antialiasing: boolean; SubOffsetX,SubOffsetY: single; GrainX, GrainY: Integer);
     107    procedure InitWithFontName(AText: string; AFontName: string; AFullHeight: integer; AStyle: TFontStyles; Antialiasing: boolean; SubOffsetX,SubOffsetY: single);
    33108  public
    34109    constructor Create(AText: string; Font: TFont; Antialiasing: boolean);
    35110    constructor Create(AText: string; Font: TFont; Antialiasing: boolean; SubOffsetX,SubOffsetY: single);
    36111    constructor Create(AText: string; Font: TFont; Antialiasing: boolean; SubOffsetX,SubOffsetY: single; GrainX, GrainY: Integer);
     112    constructor Create(AText: string; AFontName: string; AFullHeight: integer; Antialiasing: boolean);
     113    constructor Create(AText: string; AFontName: string; AFullHeight: integer; Antialiasing: boolean; SubOffsetX,SubOffsetY: single);
     114    constructor Create(AText: string; AFontName: string; AFullHeight: integer; AStyle: TFontStyles; Antialiasing: boolean);
     115    constructor Create(AText: string; AFontName: string; AFullHeight: integer; AStyle: TFontStyles; Antialiasing: boolean; SubOffsetX,SubOffsetY: single);
     116    constructor Create(AMask: TBGRACustomBitmap; AMaskOwner: boolean; AWidth,AHeight: integer; AOffset: TPoint);
    37117    procedure ApplySphere;
    38118    procedure ApplyVerticalCylinder;
    39119    procedure ApplyHorizontalCylinder;
    40     procedure Draw(ADest: TBGRACustomBitmap; X,Y: integer; AColor: TBGRAPixel);
    41     procedure Draw(ADest: TBGRACustomBitmap; X,Y: integer; ATexture: IBGRAScanner);
    42     procedure Draw(ADest: TBGRACustomBitmap; X, Y: integer; AColor: TBGRAPixel; AAlign: TAlignment);
    43     procedure Draw(ADest: TBGRACustomBitmap; X, Y: integer; ATexture: IBGRAScanner; AAlign: TAlignment);
     120    function Draw(ADest: TBGRACustomBitmap; X,Y: integer; AColor: TBGRAPixel): TRect;
     121    function Draw(ADest: TBGRACustomBitmap; X,Y: integer; ATexture: IBGRAScanner): TRect;
     122    function Draw(ADest: TBGRACustomBitmap; X, Y: integer; AColor: TBGRAPixel; AAlign: TAlignment): TRect;
     123    function Draw(ADest: TBGRACustomBitmap; X, Y: integer; ATexture: IBGRAScanner; AAlign: TAlignment): TRect;
    44124
    45125    function DrawShaded(ADest: TBGRACustomBitmap; X,Y: integer; Shader: TCustomPhongShading; Altitude: integer; AColor: TBGRAPixel; ARounded: Boolean = true): TRect;
     
    48128    function DrawShaded(ADest: TBGRACustomBitmap; X, Y: integer; Shader: TCustomPhongShading; Altitude: integer; ATexture: IBGRAScanner; AAlign: TAlignment; ARounded: Boolean = true): TRect;
    49129
    50     procedure DrawMulticolored(ADest: TBGRACustomBitmap; X,Y: integer; const AColors: array of TBGRAPixel);
    51     procedure DrawMulticolored(ADest: TBGRACustomBitmap; X,Y: integer; const AColors: array of TBGRAPixel; AAlign: TAlignment);
    52     procedure DrawOutline(ADest: TBGRACustomBitmap; X,Y: integer; AColor: TBGRAPixel);
    53     procedure DrawOutline(ADest: TBGRACustomBitmap; X,Y: integer; ATexture: IBGRAScanner);
    54     procedure DrawOutline(ADest: TBGRACustomBitmap; X,Y: integer; AColor: TBGRAPixel; AAlign: TAlignment);
    55     procedure DrawOutline(ADest: TBGRACustomBitmap; X,Y: integer; ATexture: IBGRAScanner; AAlign: TAlignment);
    56     procedure DrawShadow(ADest: TBGRACustomBitmap; X,Y,Radius: integer; AColor: TBGRAPixel);
    57     procedure DrawShadow(ADest: TBGRACustomBitmap; X,Y,Radius: integer; AColor: TBGRAPixel; AAlign: TAlignment);
     130    function DrawMulticolored(ADest: TBGRACustomBitmap; X,Y: integer; const AColors: array of TBGRAPixel): TRect;
     131    function DrawMulticolored(ADest: TBGRACustomBitmap; X,Y: integer; const AColors: array of TBGRAPixel; AAlign: TAlignment): TRect;
     132    function DrawOutline(ADest: TBGRACustomBitmap; X,Y: integer; AColor: TBGRAPixel): TRect;
     133    function DrawOutline(ADest: TBGRACustomBitmap; X,Y: integer; ATexture: IBGRAScanner): TRect;
     134    function DrawOutline(ADest: TBGRACustomBitmap; X,Y: integer; AColor: TBGRAPixel; AAlign: TAlignment): TRect;
     135    function DrawOutline(ADest: TBGRACustomBitmap; X,Y: integer; ATexture: IBGRAScanner; AAlign: TAlignment): TRect;
     136    function DrawShadow(ADest: TBGRACustomBitmap; X,Y,Radius: integer; AColor: TBGRAPixel): TRect;
     137    function DrawShadow(ADest: TBGRACustomBitmap; X,Y,Radius: integer; AColor: TBGRAPixel; AAlign: TAlignment): TRect;
    58138    destructor Destroy; override;
    59139    property TextMask: TBGRACustomBitmap read FTextMask;
    60140    property TextMaskOffset: TPoint read FOffset;
    61     property Width: integer read GetWidth;
    62     property Height: integer read GetHeight;
     141    property Width: integer read GetTextWidth; deprecated;
     142    property Height: integer read GetTextHeight; deprecated;
     143    property MaskWidth: integer read GetMaskWidth;
     144    property MaskHeight: integer read GetMaskHeight;
     145    property TextSize: TSize read FTextSize;
     146    property TextWidth: integer read GetTextWidth;
     147    property TextHeight: integer read GetTextHeight;
    63148    property Bounds: TRect read GetBounds;
    64149    property ShadowBounds[ARadius: integer]: TRect read GetShadowBounds;
     150    property ShadowQuality: TRadialBlurType read FShadowQuality write SetShadowQuality;
     151    class property OutlineWidth: integer read GetOutlineWidth;
    65152  end;
    66153
     
    68155    AOffSetX,AOffSetY: Integer; ARadius: Integer = 0; AFontStyle: TFontStyles = []; AFontName: String = 'Default'; AShowText: Boolean = True; AFontQuality: TBGRAFontQuality = fqFineAntialiasing): TBGRACustomBitmap;
    69156
    70 procedure BGRATextOutImproveReadability(bmp: TBGRACustomBitmap; AFont: TFont; xf,yf: single; text: string; color: TBGRAPixel; tex: IBGRAScanner; align: TAlignment; useClearType: boolean; ClearTypeRGBOrder: boolean);
     157procedure BGRATextOutImproveReadability(bmp: TBGRACustomBitmap; AFont: TFont; xf,yf: single; text: string; color: TBGRAPixel; tex: IBGRAScanner; align: TAlignment; mode : TBGRATextOutImproveReadabilityMode);
    71158
    72159implementation
    73160
    74 uses BGRAGradientScanner, BGRAText, GraphType, Math;
    75 
    76 procedure BGRATextOutImproveReadability(bmp: TBGRACustomBitmap; AFont: TFont; xf,yf: single; text: string; color: TBGRAPixel; tex: IBGRAScanner; align: TAlignment; useClearType: boolean; ClearTypeRGBOrder: boolean);
     161uses BGRAGradientScanner, GraphType, Math, BGRAGrayscaleMask;
     162
     163const DefaultOutlineWidth = 3;
     164
     165procedure BGRATextOutImproveReadability(bmp: TBGRACustomBitmap; AFont: TFont; xf,yf: single; text: string; color: TBGRAPixel; tex: IBGRAScanner; align: TAlignment; mode : TBGRATextOutImproveReadabilityMode);
    77166var
     167  useClearType,clearTypeRGBOrder: boolean;
    78168  metric: TFontPixelMetric;
    79169  deltaX: single;
     
    81171  toAdd: integer;
    82172  lines: array[0..3] of integer;
    83   parts: array[0..3] of TBGRACustomBitmap;
    84   n,nbLines,v: integer;
    85   alphaMax: byte;
     173  parts: array[0..3] of TGrayscaleMask;
     174  n,nbLines: integer;
     175  alphaMax: NativeUint;
    86176  ptrPart: TBGRACustomBitmap;
    87   pmask: PBGRAPixel;
     177  pmask: PByte;
    88178  fx: TBGRATextEffect;
    89179  FxFont: TFont;
     
    92182
    93183begin
     184  useClearType:= mode in[irClearTypeRGB,irClearTypeBGR];
     185  clearTypeRGBOrder := mode <> irClearTypeBGR;
    94186  deltaX := xf-floor(xf);
    95187  x := round(floor(xf));
     
    105197    begin
    106198      if ClearTypeRGBOrder then
    107         BGRATextOut(bmp, AFont, fqFineClearTypeRGB, xf,yf, text, color, tex, align) else
     199        BGRATextOut(bmp, AFont, fqFineClearTypeRGB, xf,yf, text, color, tex, align)
     200      else
    108201        BGRATextOut(bmp, AFont, fqFineClearTypeBGR, xf,yf, text, color, tex, align)
    109202    end else
     
    144237    fx := TBGRATextEffect.Create(text,FxFont,False,deltaX*FontAntialiasingLevel,0,FontAntialiasingLevel,FontAntialiasingLevel) else
    145238    fx := TBGRATextEffect.Create(text,FxFont,False,0,0,3,0);
     239
     240  if fx.TextMask = nil then
     241  begin
     242    fx.Free;
     243    FxFont.Free;
     244    exit;
     245  end;
    146246  alphaMax := 0;
    147247  prevCenter := 0;
     
    156256      ptrPart := fx.TextMask.GetPtrBitmap(fromy,lines[yb]);
    157257      if useClearType then
    158         parts[yb] := ptrPart.Resample(round(ptrPart.Width/FontAntialiasingLevel*3),round(ptrPart.Height/FontAntialiasingLevel),rmSimpleStretch)
     258        parts[yb] := TGrayscaleMask.CreateDownSample(ptrPart,round(ptrPart.Width/FontAntialiasingLevel*3),round(ptrPart.Height/FontAntialiasingLevel))
    159259      else
    160         parts[yb] := ptrPart.Resample(round(ptrPart.Width/FontAntialiasingLevel),round(ptrPart.Height/FontAntialiasingLevel),rmSimpleStretch);
     260        parts[yb] := TGrayscaleMask.CreateDownSample(ptrPart,round(ptrPart.Width/FontAntialiasingLevel),round(ptrPart.Height/FontAntialiasingLevel));
    161261      ptrPart.Free;
    162262
    163263      if alphaMax < 255 then
    164264      begin
    165         pmask := parts[yb].data;
     265        pmask := parts[yb].Data;
    166266        for n := parts[yb].NbPixels-1 downto 0 do
    167267        begin
    168           v := pmask^.green;
    169           if v > alphaMax then alphaMax := v;
     268          if pmask^ > alphaMax then alphaMax := pmask^;
    170269          inc(pmask);
    171270        end;
     
    194293  begin
    195294    case align of
    196     taCenter: xThird:= xThird+round(((fx.TextMaskOffset.x-fx.Width/2)/FontAntialiasingLevel+deltaX)*3);
    197     taRightJustify: xThird:= xThird+round(((fx.TextMaskOffset.x-fx.Width)/FontAntialiasingLevel+deltaX)*3);
     295    taCenter: xThird:= xThird+round(((fx.TextMaskOffset.x-fx.TextWidth/2)/FontAntialiasingLevel+deltaX)*3);
     296    taRightJustify: xThird:= xThird+round(((fx.TextMaskOffset.x-fx.TextWidth)/FontAntialiasingLevel+deltaX)*3);
    198297    else xThird:= xThird+round((fx.TextMaskOffset.x/FontAntialiasingLevel+deltaX)*3);
    199298    end;
     
    201300  begin
    202301    case align of
    203     taCenter: x:= x+round((fx.TextMaskOffset.x-fx.Width/2)/FontAntialiasingLevel);
    204     taRightJustify: x:= x+round((fx.TextMaskOffset.x-fx.Width)/FontAntialiasingLevel);
     302    taCenter: x:= x+round((fx.TextMaskOffset.x-fx.TextWidth/2)/FontAntialiasingLevel);
     303    taRightJustify: x:= x+round((fx.TextMaskOffset.x-fx.TextWidth)/FontAntialiasingLevel);
    205304    else x:= x+round(fx.TextMaskOffset.x/FontAntialiasingLevel);
    206305    end;
     
    215314      for n := parts[yb].NbPixels-1 downto 0 do
    216315      begin
    217         v := integer(pmask^.green)*255 div alphaMax;
    218         if v > 255 then v := 255;
    219         pmask^.green := v;
    220         pmask^.red := v;
    221         pmask^.blue := v;
     316        pmask^ := pmask^*255 div alphaMax;
    222317        inc(pmask);
    223318      end;
    224319    end;
    225320    if useClearType then
     321      BGRAFillClearTypeGrayscaleMask(bmp,x,cury,xThird,parts[yb],color,tex,ClearTypeRGBOrder)
     322    else if mode = irMask then
     323      parts[yb].Draw(bmp,x,cury)
     324    else
    226325    begin
    227326      if tex <> nil then
    228         bmp.FillClearTypeMask(x,cury,xThird,parts[yb],tex,ClearTypeRGBOrder) else
    229         bmp.FillClearTypeMask(x,cury,xThird,parts[yb],color,ClearTypeRGBOrder);
    230     end else
    231     begin
    232       if tex <> nil then
    233         bmp.FillMask(x,cury,parts[yb],tex) else
    234         bmp.FillMask(x,cury,parts[yb],color);
     327        parts[yb].DrawAsAlpha(bmp,x,cury,tex) else
     328        parts[yb].DrawAsAlpha(bmp,x,cury,color);
    235329    end;
    236330    inc(cury,parts[yb].Height);
     
    249343
    250344function TextShadow(AWidth,AHeight: Integer; AText: String; AFontHeight: Integer; ATextColor,AShadowColor: TBGRAPixel;
    251   AOffSetX,AOffSetY: Integer; ARadius: Integer = 0; AFontStyle: TFontStyles = []; AFontName: String = 'Default'; AShowText: Boolean = True; AFontQuality: TBGRAFontQuality = fqFineAntialiasing): TBGRACustomBitmap;
     345  AOffSetX,AOffSetY: Integer; ARadius: Integer = 0; AFontStyle: TFontStyles = []; AFontName: String = 'Default'; AShowText: Boolean = True;
     346  AFontQuality: TBGRAFontQuality = fqFineAntialiasing): TBGRACustomBitmap;
    252347var
    253348  bmpOut,bmpSdw: TBGRACustomBitmap; OutTxtSize: TSize; OutX,OutY: Integer;
     
    281376end;
    282377
     378{ TBGRATextEffectFontRenderer }
     379
     380function TBGRATextEffectFontRenderer.GetShaderLightPosition: TPoint;
     381begin
     382  if FShader = nil then
     383    result := point(0,0)
     384  else
     385    result := FShader.LightPosition;
     386end;
     387
     388function TBGRATextEffectFontRenderer.GetVectorizedRenderer: TBGRAVectorizedFontRenderer;
     389begin
     390  FVectorizedRenderer.FontEmHeight := FontEmHeight;
     391  FVectorizedRenderer.FontName := FontName;
     392  FVectorizedRenderer.FontOrientation:= FontOrientation;
     393  FVectorizedRenderer.FontQuality := FontQuality;
     394  FVectorizedRenderer.FontStyle:= FontStyle;
     395
     396  FVectorizedRenderer.ShadowColor := ShadowColor;
     397  FVectorizedRenderer.ShadowVisible := ShadowVisible;
     398  FVectorizedRenderer.ShadowOffset := ShadowOffset;
     399  FVectorizedRenderer.ShadowRadius := ShadowRadius;
     400
     401  FVectorizedRenderer.OutlineColor := OutlineColor;
     402  FVectorizedRenderer.OutlineVisible := OutlineVisible;
     403  FVectorizedRenderer.OutlineWidth := OutlineWidth;
     404  FVectorizedRenderer.OutlineTexture := OutlineTexture;
     405  FVectorizedRenderer.OuterOutlineOnly := OuterOutlineOnly;
     406  result := FVectorizedRenderer;
     407end;
     408
     409procedure TBGRATextEffectFontRenderer.SetShaderLightPosition(AValue: TPoint);
     410begin
     411  if FShader <> nil then
     412    FShader.LightPosition := AValue;
     413end;
     414
     415function TBGRATextEffectFontRenderer.ShadowActuallyVisible: boolean;
     416begin
     417  result := ShadowVisible and (ShadowColor.alpha <> 0);
     418end;
     419
     420function TBGRATextEffectFontRenderer.ShaderActuallyActive: boolean;
     421begin
     422  result := (FShader <> nil) and ShaderActive;
     423end;
     424
     425function TBGRATextEffectFontRenderer.OutlineActuallyVisible: boolean;
     426begin
     427  result := (OutlineWidth <> 0) and ((OutlineTexture <> nil) or (OutlineColor.alpha <> 0)) and OutlineVisible;
     428end;
     429
     430procedure TBGRATextEffectFontRenderer.Init;
     431begin
     432  ShaderActive := true;
     433
     434  ShadowColor := BGRABlack;
     435  ShadowVisible := false;
     436  ShadowOffset := Point(5,5);
     437  ShadowRadius := 5;
     438  ShadowQuality:= rbFast;
     439
     440  OutlineColor := BGRAPixelTransparent;
     441  OutlineVisible := True;
     442  OutlineWidth:= DefaultOutlineWidth;
     443  OuterOutlineOnly:= false;
     444  FVectorizedRenderer := TBGRAVectorizedFontRenderer.Create;
     445end;
     446
     447function TBGRATextEffectFontRenderer.VectorizedFontNeeded: boolean;
     448var bAntialiasing, bBigFont, bSpecialOutline, bOriented, bEffectVectorizedSupported: boolean;
     449  textsz: TSize;
     450begin
     451  bAntialiasing := FontQuality in [fqFineAntialiasing,fqFineClearTypeRGB,fqFineClearTypeBGR];
     452  textsz := inherited TextSize('Hg');
     453  bBigFont := (not OutlineActuallyVisible and (textsz.cy >= 24)) or
     454     (OutlineActuallyVisible and (textsz.cy > 42));
     455  bSpecialOutline:= OutlineActuallyVisible and (abs(OutlineWidth) <> DefaultOutlineWidth);
     456  bOriented := FontOrientation <> 0;
     457  bEffectVectorizedSupported := OutlineActuallyVisible or ShadowActuallyVisible;
     458  if ShaderActuallyActive and (FontOrientation = 0) then
     459    result := false //shader not supported by vectorized font
     460  else
     461    result := bSpecialOutline or
     462              (bAntialiasing and bBigFont) or
     463              (bOriented and bEffectVectorizedSupported);
     464end;
     465
     466procedure TBGRATextEffectFontRenderer.InternalTextOut(ADest: TBGRACustomBitmap;
     467  x, y: single; s: string; c: TBGRAPixel; texture: IBGRAScanner;
     468  align: TAlignment);
     469var fx: TBGRATextEffect;
     470  procedure DoOutline;
     471  begin
     472    if OutlineActuallyVisible then
     473    begin
     474      if OutlineTexture <> nil then
     475        fx.DrawOutline(ADest,round(x),round(y), OutlineTexture, align)
     476      else
     477        fx.DrawOutline(ADest,round(x),round(y), OutlineColor, align);
     478    end;
     479  end;
     480begin
     481  UpdateFont;
     482  if (FFont.Orientation <> 0) or (not ShaderActuallyActive and not ShadowActuallyVisible and not OutlineActuallyVisible) then
     483  begin
     484    if texture <> nil then
     485      inherited TextOut(ADest,x,y,s,texture,align)
     486    else
     487      inherited TextOut(ADest,x,y,s,c,align);
     488    exit;
     489  end;
     490  fx := TBGRATextEffect.Create(s, FFont, FontQuality in[fqFineAntialiasing,fqFineClearTypeBGR,fqFineClearTypeRGB], x-floor(x),y-floor(y));
     491  if ShadowActuallyVisible then
     492  begin
     493    fx.ShadowQuality := ShadowQuality;
     494    fx.DrawShadow(ADest,round(x)+ShadowOffset.X,round(y)+ShadowOffset.Y,ShadowRadius,ShadowColor, align);
     495  end;
     496  if OuterOutlineOnly then DoOutline;
     497  if texture <> nil then
     498  begin
     499    if ShaderActuallyActive then
     500      fx.DrawShaded(ADest,floor(x),floor(y), Shader, round(fx.TextSize.cy*0.05), texture, align)
     501    else
     502      fx.Draw(ADest,round(x),round(y), texture, align);
     503  end else
     504  begin
     505    if ShaderActuallyActive then
     506      fx.DrawShaded(ADest,floor(x),floor(y), Shader, round(fx.TextSize.cy*0.05), c, align)
     507    else
     508      fx.Draw(ADest,round(x),round(y), c, align);
     509  end;
     510  if not OuterOutlineOnly then DoOutline;
     511  fx.Free;
     512end;
     513
     514constructor TBGRATextEffectFontRenderer.Create;
     515begin
     516  inherited Create;
     517  FShader := nil;
     518  FShaderOwner:= false;
     519  Init;
     520end;
     521
     522constructor TBGRATextEffectFontRenderer.Create(AShader: TCustomPhongShading;
     523  AShaderOwner: boolean);
     524begin
     525  inherited Create;
     526  Init;
     527  FShader := AShader;
     528  FShaderOwner := AShaderOwner;
     529end;
     530
     531destructor TBGRATextEffectFontRenderer.Destroy;
     532begin
     533  if FShaderOwner then FShader.Free;
     534  FVectorizedRenderer.Free;
     535  inherited Destroy;
     536end;
     537
     538procedure TBGRATextEffectFontRenderer.TextOutAngle(ADest: TBGRACustomBitmap; x,
     539  y: single; orientation: integer; s: string; texture: IBGRAScanner;
     540  align: TAlignment);
     541begin
     542  VectorizedFontRenderer.TextOutAngle(ADest, x, y, orientation, s, texture, align);
     543end;
     544
     545procedure TBGRATextEffectFontRenderer.TextOutAngle(ADest: TBGRACustomBitmap; x,
     546  y: single; orientation: integer; s: string; c: TBGRAPixel; align: TAlignment);
     547begin
     548  VectorizedFontRenderer.TextOutAngle(ADest, x, y, orientation, s, c, align);
     549end;
     550
     551procedure TBGRATextEffectFontRenderer.TextOut(ADest: TBGRACustomBitmap; x,
     552  y: single; s: string; texture: IBGRAScanner; align: TAlignment);
     553begin
     554  if VectorizedFontNeeded then
     555    VectorizedFontRenderer.TextOut(ADest,x,y,s,texture,align)
     556  else
     557    InternalTextOut(ADest,x,y,s,BGRAPixelTransparent,texture,align);
     558end;
     559
     560procedure TBGRATextEffectFontRenderer.TextOut(ADest: TBGRACustomBitmap; x,
     561  y: single; s: string; c: TBGRAPixel; align: TAlignment);
     562begin
     563  if VectorizedFontNeeded then
     564    VectorizedFontRenderer.TextOut(ADest,x,y,s,c,align)
     565  else
     566    InternalTextOut(ADest,x,y,s,c,nil,align);
     567end;
     568
     569function TBGRATextEffectFontRenderer.TextSize(sUTF8: string): TSize;
     570begin
     571  if VectorizedFontNeeded then
     572    result := VectorizedFontRenderer.TextSize(sUTF8)
     573  else
     574  begin
     575    result := inherited TextSize(sUTF8);
     576  end;
     577end;
     578
    283579{ TBGRATextEffect }
    284580
     
    291587end;
    292588
    293 function TBGRATextEffect.GetHeight: integer;
    294 begin
    295   result := FHeight;
     589function TBGRATextEffect.GetMaskHeight: integer;
     590begin
     591  if FTextMask = nil then
     592    result := 0
     593  else
     594    result := FTextMask.Height;
     595end;
     596
     597class function TBGRATextEffect.GetOutlineWidth: integer; static;
     598begin
     599  result := DefaultOutlineWidth;
    296600end;
    297601
     
    308612end;
    309613
    310 function TBGRATextEffect.GetWidth: integer;
    311 begin
    312   result := FWidth;
    313 end;
    314 
    315 procedure TBGRATextEffect.DrawMaskMulticolored(ADest: TBGRACustomBitmap;
    316   AMask: TBGRACustomBitmap; X, Y: Integer; const AColors: array of TBGRAPixel);
     614function TBGRATextEffect.GetMaskWidth: integer;
     615begin
     616  if FTextMask = nil then
     617    result := 0
     618  else
     619    result := FTextMask.Width;
     620end;
     621
     622function TBGRATextEffect.GetTextHeight: integer;
     623begin
     624  result := FTextSize.cy;
     625end;
     626
     627function TBGRATextEffect.GetTextWidth: integer;
     628begin
     629  result := FTextSize.cx;
     630end;
     631
     632procedure TBGRATextEffect.SetShadowQuality(AValue: TRadialBlurType);
     633begin
     634  if FShadowQuality=AValue then Exit;
     635  FShadowQuality:=AValue;
     636  FreeAndNil(FShadowMask);
     637end;
     638
     639function TBGRATextEffect.DrawMaskMulticolored(ADest: TBGRACustomBitmap;
     640  AMask: TBGRACustomBitmap; X, Y: Integer; const AColors: array of TBGRAPixel
     641  ): TRect;
    317642var
    318643  scan: TBGRASolidColorMaskScanner;
     
    321646  emptyCol, nextCol: boolean;
    322647begin
    323   if (AMask = nil) or (length(AColors)=0) then exit;
     648  if (AMask = nil) or (length(AColors)=0) then
     649  begin
     650    result := EmptyRect;
     651    exit;
     652  end;
    324653  if (length(AColors)=0) then
    325654  begin
    326     DrawMask(ADest,AMask,X,Y,AColors[0]);
     655    result := DrawMask(ADest,AMask,X,Y,AColors[0]);
    327656    exit;
    328657  end;
     
    399728    ADest.FillRect(X+startX,Y,X+AMask.Width,Y+AMask.Height,scan,dmDrawWithTransparency);
    400729  scan.Free;
    401 end;
    402 
    403 procedure TBGRATextEffect.DrawMask(ADest: TBGRACustomBitmap; AMask: TBGRACustomBitmap; X,
    404   Y: Integer; AColor: TBGRAPixel);
     730  result := rect(X,Y,X+AMask.Width,Y+AMask.Height);
     731end;
     732
     733function TBGRATextEffect.DrawMask(ADest: TBGRACustomBitmap;
     734  AMask: TBGRACustomBitmap; X, Y: Integer; AColor: TBGRAPixel): TRect;
    405735var
    406736  scan: TBGRACustomScanner;
    407737begin
    408   if AMask = nil then exit;
     738  if AMask = nil then
     739  begin
     740    result := EmptyRect;
     741    exit;
     742  end;
    409743  scan := TBGRASolidColorMaskScanner.Create(AMask,Point(-X,-Y),AColor);
    410744  ADest.FillRect(X,Y,X+AMask.Width,Y+AMask.Height,scan,dmDrawWithTransparency);
    411745  scan.Free;
    412 end;
    413 
    414 procedure TBGRATextEffect.DrawMask(ADest: TBGRACustomBitmap; AMask: TBGRACustomBitmap; X,
    415   Y: Integer; ATexture: IBGRAScanner);
     746  result := rect(X,Y,X+AMask.Width,Y+AMask.Height);
     747end;
     748
     749function TBGRATextEffect.DrawMask(ADest: TBGRACustomBitmap;
     750  AMask: TBGRACustomBitmap; X, Y: Integer; ATexture: IBGRAScanner): TRect;
    416751var
    417752  scan: TBGRACustomScanner;
    418753begin
    419   if AMask = nil then exit;
     754  if AMask = nil then
     755  begin
     756    result := EmptyRect;
     757    exit;
     758  end;
    420759  scan := TBGRATextureMaskScanner.Create(AMask,Point(-X,-Y),ATexture);
    421760  ADest.FillRect(X,Y,X+AMask.Width,Y+AMask.Height,scan,dmDrawWithTransparency);
    422761  scan.Free;
     762  result := rect(X,Y,X+AMask.Width,Y+AMask.Height);
    423763end;
    424764
     
    433773  iBlurRadius: integer;
    434774begin
    435   if FTextMask = nil then
     775  if (FTextMask = nil) or (FTextMask.Width = 0) or (FTextMask.Height = 0) then
    436776  begin
    437777    result := EmptyRect;
     
    491831  end;
    492832
     833  inc(X, FOffset.X);
     834  Inc(Y, FOffset.Y);
    493835  if ATexture <> nil then
    494     Shader.DrawScan(ADest,FShadingMask,Altitude,X+FOffset.X,Y+FOffset.Y, ATexture)
     836    Shader.DrawScan(ADest,FShadingMask,Altitude,X,Y, ATexture)
    495837  else
    496     Shader.Draw(ADest,FShadingMask,Altitude,X+FOffset.X,Y+FOffset.Y, AColor);
    497   result := rect(X+FOffset.X,Y+FOffset.Y, X+FOffset.X+FShadingMask.Width,Y+FOffset.Y+FShadingMask.Height);
    498 end;
    499 
    500 procedure TBGRATextEffect.Draw(ADest: TBGRACustomBitmap; X, Y: integer;
    501   AColor: TBGRAPixel; AAlign: TAlignment);
     838    Shader.Draw(ADest,FShadingMask,Altitude,X,Y, AColor);
     839  result := rect(X,Y, X+FShadingMask.Width,Y+FShadingMask.Height);
     840end;
     841
     842procedure TBGRATextEffect.InitImproveReadability(AText: string; Font: TFont;
     843  SubOffsetX, SubOffsetY: single);
     844var size: TSize;
     845  overhang: integer;
     846begin
     847  if SubOffsetX < 0 then SubOffsetX := 0;
     848  if SubOffsetY < 0 then SubOffsetY := 0;
     849  size := BGRATextSize(Font, fqFineAntialiasing, AText, FontAntialiasingLevel);
     850  FTextSize := size;
     851  if size.cy = 0 then FTextSize.cy := BGRATextSize(Font, fqFineAntialiasing, 'Hg', FontAntialiasingLevel).cy;
     852  overhang := size.cy div 2;
     853  size.cx += 2*overhang + ceil(SubOffsetX);
     854  size.cy += 2 + ceil(SubOffsetY);
     855
     856  FOffset := Point(-overhang,-1); //include overhang
     857  FTextMask := BGRABitmapFactory.Create(size.cx,size.cy,BGRABlack);
     858  BGRATextOutImproveReadability(FTextMask, Font, overhang+SubOffsetX,1+SubOffsetY, AText, BGRAWhite, nil, taLeftJustify, irMask);
     859end;
     860
     861function TBGRATextEffect.Draw(ADest: TBGRACustomBitmap; X, Y: integer;
     862  AColor: TBGRAPixel; AAlign: TAlignment): TRect;
    502863begin
    503864  Case AAlign of
    504   taLeftJustify: Draw(ADest,X,Y,AColor);
    505   taRightJustify: Draw(ADest,X-Width,Y,AColor);
    506   taCenter: Draw(ADest,X-Width div 2,Y,AColor);
    507   end;
    508 end;
    509 
    510 procedure TBGRATextEffect.Draw(ADest: TBGRACustomBitmap; X, Y: integer;
    511   ATexture: IBGRAScanner; AAlign: TAlignment);
     865  taRightJustify: result := Draw(ADest,X-TextSize.cx,Y,AColor);
     866  taCenter: result := Draw(ADest,X-TextSize.cx div 2,Y,AColor);
     867  else result := Draw(ADest,X,Y,AColor);
     868  end;
     869end;
     870
     871function TBGRATextEffect.Draw(ADest: TBGRACustomBitmap; X, Y: integer;
     872  ATexture: IBGRAScanner; AAlign: TAlignment): TRect;
    512873begin
    513874  Case AAlign of
    514   taLeftJustify: Draw(ADest,X,Y,ATexture);
    515   taRightJustify: Draw(ADest,X-Width,Y,ATexture);
    516   taCenter: Draw(ADest,X-Width div 2,Y,ATexture);
     875  taRightJustify: result := Draw(ADest,X-TextSize.cx,Y,ATexture);
     876  taCenter: result := Draw(ADest,X-TextSize.cx div 2,Y,ATexture);
     877  else result := Draw(ADest,X,Y,ATexture);
    517878  end;
    518879end;
     
    538899  Case AAlign of
    539900  taLeftJustify: result := DrawShaded(ADest,X,Y,Shader,Altitude,AColor,ARounded);
    540   taRightJustify: result := DrawShaded(ADest,X-Width,Y,Shader,Altitude,AColor,ARounded);
    541   taCenter: result := DrawShaded(ADest,X-Width div 2,Y,Shader,Altitude,AColor,ARounded);
     901  taRightJustify: result := DrawShaded(ADest,X-TextSize.cx,Y,Shader,Altitude,AColor,ARounded);
     902  taCenter: result := DrawShaded(ADest,X-TextSize.cx div 2,Y,Shader,Altitude,AColor,ARounded);
    542903  else
    543904    result := EmptyRect;
     
    551912  Case AAlign of
    552913  taLeftJustify: result := DrawShaded(ADest,X,Y,Shader,Altitude,ATexture,ARounded);
    553   taRightJustify: result := DrawShaded(ADest,X-Width,Y,Shader,Altitude,ATexture,ARounded);
    554   taCenter: result := DrawShaded(ADest,X-Width div 2,Y,Shader,Altitude,ATexture,ARounded);
     914  taRightJustify: result := DrawShaded(ADest,X-TextSize.cx,Y,Shader,Altitude,ATexture,ARounded);
     915  taCenter: result := DrawShaded(ADest,X-TextSize.cx div 2,Y,Shader,Altitude,ATexture,ARounded);
    555916  else
    556917    result := EmptyRect;
     
    571932end;
    572933
    573 procedure TBGRATextEffect.Init(AText: string; Font: TFont;
    574   Antialiasing: boolean; SubOffsetX,SubOffsetY: single; GrainX, GrainY: Integer);
     934constructor TBGRATextEffect.Create(AText: string; AFontName: string;
     935  AFullHeight: integer; Antialiasing: boolean);
     936begin
     937  InitWithFontName(AText, AFontName, AFullHeight, [], Antialiasing, 0, 0);
     938end;
     939
     940constructor TBGRATextEffect.Create(AText: string; AFontName: string;
     941  AFullHeight: integer; Antialiasing: boolean; SubOffsetX, SubOffsetY: single);
     942begin
     943  InitWithFontName(AText, AFontName, AFullHeight, [], Antialiasing, SubOffsetX, SubOffsetY);
     944end;
     945
     946constructor TBGRATextEffect.Create(AText: string; AFontName: string;
     947  AFullHeight: integer; AStyle: TFontStyles; Antialiasing: boolean);
     948begin
     949  InitWithFontName(AText, AFontName, AFullHeight, AStyle, Antialiasing, 0, 0);
     950end;
     951
     952constructor TBGRATextEffect.Create(AText: string; AFontName: string;
     953  AFullHeight: integer; AStyle: TFontStyles; Antialiasing: boolean; SubOffsetX,
     954  SubOffsetY: single);
     955begin
     956  InitWithFontName(AText, AFontName, AFullHeight, AStyle, Antialiasing, SubOffsetX, SubOffsetY);
     957end;
     958
     959constructor TBGRATextEffect.Create(AMask: TBGRACustomBitmap; AMaskOwner: boolean; AWidth,
     960  AHeight: integer; AOffset: TPoint);
     961begin
     962  FTextSize := Size(AWidth,AHeight);
     963  FOffset := AOffset;
     964  if not AMaskOwner then
     965    FTextMask := AMask.Duplicate()
     966  else
     967    FTextMask := AMask;
     968end;
     969
     970procedure TBGRATextEffect.Init(AText: string; Font: TFont; Antialiasing: boolean; SubOffsetX,SubOffsetY: single; GrainX, GrainY: Integer);
     971const FXAntialiasingLevel = FontAntialiasingLevel;
    575972var temp: TBGRACustomBitmap;
    576973    size: TSize;
     
    583980    iSubX,iSubY: integer;
    584981begin
     982  FShadowQuality := rbFast;
     983  if Antialiasing and Assigned(BGRATextOutImproveReadabilityProc) then
     984  begin
     985    InitImproveReadability(AText, Font, SubOffsetX,SubOffsetY);
     986    exit;
     987  end;
    585988  if Antialiasing then
    586989    quality := fqFineAntialiasing
    587990  else
    588991    quality := fqSystem;
    589   size := BGRAOriginalTextSize(Font,quality,AText,FontAntialiasingLevel);
     992  size := BGRAOriginalTextSize(Font,quality,AText,FXAntialiasingLevel);
    590993  if (size.cx = 0) or (size.cy = 0) then
    591994  begin
    592     size := BGRATextSize(Font,quality,'Hg',FontAntialiasingLevel);
    593     FWidth := 0;
    594     FHeight := size.cy;
     995    size := BGRATextSize(Font,quality,'Hg',FXAntialiasingLevel);
     996    FTextSize.cx := 0;
     997    FTextSize.cy := size.cy;
    595998    FOffset := Point(0,0);
    596999    exit;
    5971000  end;
     1001  FTextSize := size;
    5981002
    5991003  sizeX := size.cx+size.cy;
     
    6071011  if Antialiasing then
    6081012  begin
    609     sizeX := (sizeX + FontAntialiasingLevel-1);
    610     sizeX -= sizeX mod FontAntialiasingLevel;
    611 
    612     sizeY := (sizeY + FontAntialiasingLevel-1);
    613     sizeY -= sizeY mod FontAntialiasingLevel;
     1013    sizeX := (sizeX + FXAntialiasingLevel-1);
     1014    sizeX -= sizeX mod FXAntialiasingLevel;
     1015
     1016    sizeY := (sizeY + FXAntialiasingLevel-1);
     1017    sizeY -= sizeY mod FXAntialiasingLevel;
    6141018
    6151019    if SubOffsetX <> 0 then
    6161020    begin
    617       sizeX += ceil(SubOffsetX*FontAntialiasingLevel);
    618       iSubX := round(SubOffsetX*FontAntialiasingLevel);
     1021      sizeX += ceil(SubOffsetX*FXAntialiasingLevel);
     1022      iSubX := round(SubOffsetX*FXAntialiasingLevel);
    6191023    end;
    6201024    if SubOffsetY <> 0 then
    6211025    begin
    622       sizeY += ceil(SubOffsetY*FontAntialiasingLevel);
    623       iSubY := round(SubOffsetY*FontAntialiasingLevel);
    624     end;
    625 
    626     OnePixel := FontAntialiasingLevel;
     1026      sizeY += ceil(SubOffsetY*FXAntialiasingLevel);
     1027      iSubY := round(SubOffsetY*FXAntialiasingLevel);
     1028    end;
     1029
     1030    OnePixel := FXAntialiasingLevel;
    6271031  end else
    6281032  begin
     
    6621066  if Antialiasing then
    6631067  begin
    664     FWidth := round(size.cx/FontAntialiasingLevel);
    665     FHeight := round(size.cy/FontAntialiasingLevel);
    666     FOffset := Point(round(FOffset.X/FontAntialiasingLevel),round(FOffset.Y/FontAntialiasingLevel));
    667 
    668     FTextMask := temp.Resample(round(temp.width/FontAntialiasingLevel),round(temp.Height/FontAntialiasingLevel),rmSimpleStretch);
     1068    FTextSize.cx := round(FTextSize.cx/FXAntialiasingLevel);
     1069    FTextSize.cy := round(FTextSize.cy/FXAntialiasingLevel);
     1070    FOffset := Point(round(FOffset.X/FXAntialiasingLevel),round(FOffset.Y/FXAntialiasingLevel));
     1071
     1072    FTextMask := temp.Resample(round(temp.width/FXAntialiasingLevel),round(temp.Height/FXAntialiasingLevel),rmSimpleStretch);
    6691073
    6701074    maxAlpha := 0;
     
    6921096  else
    6931097  begin
    694     FWidth := size.cx;
    695     FHeight := size.cy;
    696 
    6971098    FTextMask := temp;
    6981099    p := FTextMask.data;
     
    7051106    end;
    7061107  end;
     1108end;
     1109
     1110procedure TBGRATextEffect.InitWithFontName(AText: string; AFontName: string;
     1111  AFullHeight: integer; AStyle: TFontStyles; Antialiasing: boolean; SubOffsetX, SubOffsetY: single);
     1112var lFont: TFont;
     1113begin
     1114  lFont := TFont.Create;
     1115  lFont.Name := AFontName;
     1116  lFont.Height := AFullHeight * FontFullHeightSign;
     1117  lFont.Style := AStyle;
     1118  Init(AText, lFont, Antialiasing, SubOffsetX, SubOffsetY, 0,0);
     1119  lFont.Free;
    7071120end;
    7081121
     
    7461159end;
    7471160
    748 procedure TBGRATextEffect.Draw(ADest: TBGRACustomBitmap; X, Y: integer;
    749   AColor: TBGRAPixel);
    750 begin
    751   if FTextMask = nil then exit;
    752   DrawMask(ADest,FTextMask,X+FOffset.X,Y+FOffset.Y,AColor);
    753 end;
    754 
    755 procedure TBGRATextEffect.Draw(ADest: TBGRACustomBitmap; X, Y: integer;
    756   ATexture: IBGRAScanner);
    757 begin
    758   if FTextMask = nil then exit;
    759   DrawMask(ADest,FTextMask,X+FOffset.X,Y+FOffset.Y,ATexture);
    760 end;
    761 
    762 procedure TBGRATextEffect.DrawMulticolored(ADest: TBGRACustomBitmap; X, Y: integer;
    763   const AColors: array of TBGRAPixel);
    764 begin
    765   if FTextMask = nil then exit;
    766   DrawMaskMulticolored(ADest,FTextMask,X+FOffset.X,Y+FOffset.Y,AColors);
    767 end;
    768 
    769 procedure TBGRATextEffect.DrawMulticolored(ADest: TBGRACustomBitmap; X,
    770   Y: integer; const AColors: array of TBGRAPixel; AAlign: TAlignment);
     1161function TBGRATextEffect.Draw(ADest: TBGRACustomBitmap; X, Y: integer;
     1162  AColor: TBGRAPixel): TRect;
     1163begin
     1164  result := DrawMask(ADest,FTextMask,X+FOffset.X,Y+FOffset.Y,AColor);
     1165end;
     1166
     1167function TBGRATextEffect.Draw(ADest: TBGRACustomBitmap; X, Y: integer;
     1168  ATexture: IBGRAScanner): TRect;
     1169begin
     1170  result := DrawMask(ADest,FTextMask,X+FOffset.X,Y+FOffset.Y,ATexture);
     1171end;
     1172
     1173function TBGRATextEffect.DrawMulticolored(ADest: TBGRACustomBitmap; X,
     1174  Y: integer; const AColors: array of TBGRAPixel): TRect;
     1175begin
     1176  result := DrawMaskMulticolored(ADest,FTextMask,X+FOffset.X,Y+FOffset.Y,AColors);
     1177end;
     1178
     1179function TBGRATextEffect.DrawMulticolored(ADest: TBGRACustomBitmap; X,
     1180  Y: integer; const AColors: array of TBGRAPixel; AAlign: TAlignment): TRect;
    7711181begin
    7721182  Case AAlign of
    773   taLeftJustify: DrawMulticolored(ADest,X,Y,AColors);
    774   taRightJustify: DrawMulticolored(ADest,X-Width,Y,AColors);
    775   taCenter: DrawMulticolored(ADest,X-Width div 2,Y,AColors);
    776   end;
    777 end;
    778 
    779 procedure TBGRATextEffect.DrawOutline(ADest: TBGRACustomBitmap; X, Y: integer;
    780   AColor: TBGRAPixel);
    781 begin
    782   if FTextMask = nil then exit;
     1183  taRightJustify: result := DrawMulticolored(ADest,X-TextSize.cx,Y,AColors);
     1184  taCenter: result := DrawMulticolored(ADest,X-TextSize.cx div 2,Y,AColors);
     1185  else result := DrawMulticolored(ADest,X,Y,AColors);
     1186  end;
     1187end;
     1188
     1189function TBGRATextEffect.DrawOutline(ADest: TBGRACustomBitmap; X, Y: integer;
     1190  AColor: TBGRAPixel): TRect;
     1191begin
     1192  if (FTextMask = nil) or (FTextMask.Width = 0) or (FTextMask.Height = 0) then
     1193  begin
     1194    result := EmptyRect;
     1195    exit;
     1196  end;
    7831197  if FOutlineMask = nil then
    7841198  begin
     
    7861200    FOutlineMask.LinearNegative;
    7871201  end;
    788   DrawMask(ADest,FOutlineMask,X+FOffset.X,Y+FOffset.Y,AColor);
    789 end;
    790 
    791 procedure TBGRATextEffect.DrawOutline(ADest: TBGRACustomBitmap; X, Y: integer;
    792   ATexture: IBGRAScanner);
    793 begin
    794   if FTextMask = nil then exit;
     1202  result := DrawMask(ADest,FOutlineMask,X+FOffset.X,Y+FOffset.Y,AColor);
     1203end;
     1204
     1205function TBGRATextEffect.DrawOutline(ADest: TBGRACustomBitmap; X, Y: integer;
     1206  ATexture: IBGRAScanner): TRect;
     1207begin
     1208  if (FTextMask = nil) or (FTextMask.Width = 0) or (FTextMask.Height = 0) then
     1209  begin
     1210    result := EmptyRect;
     1211    exit;
     1212  end;
    7951213  if FOutlineMask = nil then
    7961214  begin
     
    7981216    FOutlineMask.LinearNegative;
    7991217  end;
    800   DrawMask(ADest,FOutlineMask,X+FOffset.X,Y+FOffset.Y,ATexture);
    801 end;
    802 
    803 procedure TBGRATextEffect.DrawOutline(ADest: TBGRACustomBitmap; X, Y: integer;
    804   AColor: TBGRAPixel; AAlign: TAlignment);
     1218  result := DrawMask(ADest,FOutlineMask,X+FOffset.X,Y+FOffset.Y,ATexture);
     1219end;
     1220
     1221function TBGRATextEffect.DrawOutline(ADest: TBGRACustomBitmap; X, Y: integer;
     1222  AColor: TBGRAPixel; AAlign: TAlignment): TRect;
    8051223begin
    8061224  Case AAlign of
    807   taLeftJustify: DrawOutline(ADest,X,Y,AColor);
    808   taRightJustify: DrawOutline(ADest,X-Width,Y,AColor);
    809   taCenter: DrawOutline(ADest,X-Width div 2,Y,AColor);
    810   end;
    811 end;
    812 
    813 procedure TBGRATextEffect.DrawOutline(ADest: TBGRACustomBitmap; X, Y: integer;
    814   ATexture: IBGRAScanner; AAlign: TAlignment);
     1225  taRightJustify: result := DrawOutline(ADest,X-TextSize.cx,Y,AColor);
     1226  taCenter: result := DrawOutline(ADest,X-TextSize.cx div 2,Y,AColor);
     1227  else result := DrawOutline(ADest,X,Y,AColor);
     1228  end;
     1229end;
     1230
     1231function TBGRATextEffect.DrawOutline(ADest: TBGRACustomBitmap; X, Y: integer;
     1232  ATexture: IBGRAScanner; AAlign: TAlignment): TRect;
    8151233begin
    8161234  Case AAlign of
    817   taLeftJustify: DrawOutline(ADest,X,Y,ATexture);
    818   taRightJustify: DrawOutline(ADest,X-Width,Y,ATexture);
    819   taCenter: DrawOutline(ADest,X-Width div 2,Y,ATexture);
    820   end;
    821 end;
    822 
    823 procedure TBGRATextEffect.DrawShadow(ADest: TBGRACustomBitmap; X, Y,Radius: integer;
    824   AColor: TBGRAPixel);
    825 begin
    826   if Radius <= 0 then
    827   begin
    828     Draw(ADest,X,Y,AColor);
     1235  taRightJustify: result := DrawOutline(ADest,X-TextSize.cx,Y,ATexture);
     1236  taCenter: result := DrawOutline(ADest,X-TextSize.cx div 2,Y,ATexture);
     1237  else result := DrawOutline(ADest,X,Y,ATexture);
     1238  end;
     1239end;
     1240
     1241function TBGRATextEffect.DrawShadow(ADest: TBGRACustomBitmap; X, Y,
     1242  Radius: integer; AColor: TBGRAPixel): TRect;
     1243begin
     1244  if (Radius <= 0) or (FTextMask = nil) or (FTextMask.Width = 0) or (FTextMask.Height = 0) then
     1245  begin
     1246    result := Draw(ADest,X,Y,AColor);
    8291247    exit;
    8301248  end;
    831   if FTextMask = nil then exit;
    832   if FShadowRadius <> Radius then
     1249  if (FShadowRadius <> Radius) or (FShadowMask = nil) then
    8331250  begin
    8341251    FShadowRadius := Radius;
     
    8361253    FShadowMask := BGRABitmapFactory.Create(FTextMask.Width+Radius*2,FTextMask.Height+Radius*2,BGRABlack);
    8371254    FShadowMask.PutImage(Radius,Radius,FTextMask,dmSet);
    838     BGRAReplace(FShadowMask, FShadowMask.FilterBlurRadial(Radius,rbFast));
    839   end;
    840   DrawMask(ADest,FShadowMask,X-Radius+FOffset.X,Y-Radius+FOffset.Y,AColor)
    841 end;
    842 
    843 procedure TBGRATextEffect.DrawShadow(ADest: TBGRACustomBitmap; X, Y,
    844   Radius: integer; AColor: TBGRAPixel; AAlign: TAlignment);
     1255    BGRAReplace(FShadowMask, FShadowMask.FilterBlurRadial(Radius,ShadowQuality));
     1256  end;
     1257  Inc(X,FOffset.X-Radius);
     1258  Inc(Y,FOffset.Y-Radius);
     1259  DrawMask(ADest,FShadowMask,X,Y,AColor);
     1260  result := rect(X,Y,X+FShadowMask.Width,Y+FShadowMask.Height);
     1261end;
     1262
     1263function TBGRATextEffect.DrawShadow(ADest: TBGRACustomBitmap; X, Y,
     1264  Radius: integer; AColor: TBGRAPixel; AAlign: TAlignment): TRect;
    8451265begin
    8461266  Case AAlign of
    847   taLeftJustify: DrawShadow(ADest,X,Y,Radius,AColor);
    848   taRightJustify: DrawShadow(ADest,X-Width,Y,Radius,AColor);
    849   taCenter: DrawShadow(ADest,X-Width div 2,Y,Radius,AColor);
     1267  taRightJustify: result := DrawShadow(ADest,X-TextSize.cx,Y,Radius,AColor);
     1268  taCenter: result := DrawShadow(ADest,X-TextSize.cx div 2,Y,Radius,AColor);
     1269  else result := DrawShadow(ADest,X,Y,Radius,AColor);
    8501270  end;
    8511271end;
     
    8601280end;
    8611281
     1282initialization
     1283
     1284  BGRATextOutImproveReadabilityProc := @BGRATextOutImproveReadability;
     1285
    8621286end.
    8631287
Note: See TracChangeset for help on using the changeset viewer.