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/bgradefaultbitmap.pas

    r452 r472  
    3333
    3434uses
    35   Classes, SysUtils, Types, FPImage, Graphics, BGRABitmapTypes, GraphType, FPImgCanv, BGRACanvas, BGRACanvas2D, FPWritePng;
     35  Classes, SysUtils, Types, FPImage, Graphics, BGRABitmapTypes, GraphType, FPImgCanv,
     36  BGRACanvas, BGRACanvas2D, FPWritePng, BGRAArrow, BGRAPen;
    3637
    3738type
     
    4344      if the coordinates are visible and return true if it is the case, swap
    4445      coordinates if necessary and make them fit into the clipping rectangle }
    45     function CheckHorizLineBounds(var x, y, x2: integer): boolean; inline;
    46     function CheckVertLineBounds(var x, y, y2: integer; out delta: integer): boolean; inline;
     46    function CheckHorizLineBounds(var x, y, x2: int32or64): boolean; inline;
     47    function CheckVertLineBounds(var x, y, y2: int32or64; out delta: int32or64): boolean; inline;
    4748    function CheckRectBounds(var x,y,x2,y2: integer; minsize: integer): boolean; inline;
    4849    function CheckClippedRectBounds(var x,y,x2,y2: integer): boolean; inline;
    49     function CheckPutImageBounds(x, y, tx, ty: integer; out minxb, minyb, maxxb, maxyb, ignoreleft: integer): boolean; inline;
    5050    function CheckAntialiasRectBounds(var x,y,x2,y2: single; w: single): boolean;
    5151    function GetCanvasBGRA: TBGRACanvas;
     
    7575    FCanvasFP: TFPImageCanvas;
    7676    FCanvasDrawModeFP: TDrawMode;
    77     FCanvasPixelProcFP: procedure(x, y: integer; col: TBGRAPixel) of object;
     77    FCanvasPixelProcFP: procedure(x, y: int32or64; col: TBGRAPixel) of object;
    7878
    7979    //canvas-like with antialiasing and texturing
     
    8383    //drawing options
    8484    FEraseMode: boolean;      //when polygons are erased instead of drawn
    85     FFont: TFont;             //font parameters
    8685    FFontHeight: integer;
    87     FFontHeightSign: integer; //sign correction
     86    FFontRenderer: TBGRACustomFontRenderer;
    8887
    8988    { Pen style can be defined by PenStyle property of by CustomPenStyle property.
     
    9291    FCustomPenStyle:  TBGRAPenStyle;
    9392    FPenStyle: TPenStyle;
     93    FArrow: TBGRAArrow;
     94    FLineCap: TPenEndCap;
    9495
    9596    //Pixel data
     
    99100      AlwaysReplaceAlpha: boolean = False; RaiseErrorOnInvalidPixelFormat: boolean = True): boolean;
    100101    function GetDataPtr: PBGRAPixel; override;
    101     procedure ClearTransparentPixels;
     102    procedure ClearTransparentPixels; override;
    102103    function GetScanlineFast(y: integer): PBGRAPixel; inline;
    103104    function GetLineOrder: TRawImageLineOrder; override;
     
    144145    function GetAveragePixel: TBGRAPixel; override;
    145146    function CreateAdaptedPngWriter: TFPWriterPNG;
    146     function LoadAsBmp32(Str: TStream): boolean; override;
    147147
    148148    //drawing
     
    151151    procedure SetPenStyle(const AValue: TPenStyle); override;
    152152    function GetPenStyle: TPenStyle; override;
    153 
    154     procedure UpdateFont;
     153    function GetLineCap: TPenEndCap; override;
     154    procedure SetLineCap(AValue: TPenEndCap); override;
     155    function GetArrowEndSize: TPointF; override;
     156    function GetArrowStartSize: TPointF; override;
     157    procedure SetArrowEndSize(AValue: TPointF); override;
     158    procedure SetArrowStartSize(AValue: TPointF); override;
     159    function GetArrowEndOffset: single; override;
     160    function GetArrowStartOffset: single; override;
     161    procedure SetArrowEndOffset(AValue: single); override;
     162    procedure SetArrowStartOffset(AValue: single); override;
     163    function GetArrowEndRepeat: integer; override;
     164    function GetArrowStartRepeat: integer; override;
     165    procedure SetArrowEndRepeat(AValue: integer); override;
     166    procedure SetArrowStartRepeat(AValue: integer); override;
     167
    155168    function GetFontHeight: integer; override;
    156169    procedure SetFontHeight(AHeight: integer); override;
     
    158171    procedure SetFontFullHeight(AHeight: integer); override;
    159172    function GetFontPixelMetric: TFontPixelMetric; override;
     173    function GetFontRenderer: TBGRACustomFontRenderer; override;
     174    procedure SetFontRenderer(AValue: TBGRACustomFontRenderer); override;
    160175
    161176    function GetClipRect: TRect; override;
    162177    procedure SetClipRect(const AValue: TRect); override;
    163178
    164     function GetPixelCycleInline(ix,iy: integer; iFactX,iFactY: integer): TBGRAPixel; inline;
     179    function InternalGetPixelCycle256(ix,iy: int32or64; iFactX,iFactY: int32or64): TBGRAPixel;
     180    function InternalGetPixel256(ix,iy: int32or64; iFactX,iFactY: int32or64; smoothBorder: boolean): TBGRAPixel;
     181    function GetPolyLineOption: TBGRAPolyLineOptions;
     182    function GetArrow: TBGRAArrow;
     183    procedure SetArrowStart(AStyle: TBGRAArrowStyle; ATipStyle: TPenJoinStyle = pjsMiter; ARelativePenWidth: single = 1; ATriangleBackOffset: single = 0); override;
     184    procedure SetArrowEnd(AStyle: TBGRAArrowStyle; ATipStyle: TPenJoinStyle = pjsMiter; ARelativePenWidth: single = 1; ATriangleBackOffset: single = 0); override;
    165185
    166186  public
     
    170190    function GetUnique: TBGRACustomBitmap;
    171191
    172     {TFPCustomImage override}
    173     constructor Create(AWidth, AHeight: integer); override;
    174     procedure SetSize(AWidth, AHeight: integer); override;
    175 
    176     {Constructors}
    177     constructor Create; override;
    178     constructor Create(ABitmap: TBitmap); override;
    179     constructor Create(AWidth, AHeight: integer; Color: TColor); override;
    180     constructor Create(AWidth, AHeight: integer; Color: TBGRAPixel); override;
    181     constructor Create(AFilename: string); override;
    182     constructor Create(AStream: TStream); override;
    183     destructor Destroy; override;
    184 
    185     {Loading functions}
    186     function NewBitmap(AWidth, AHeight: integer): TBGRACustomBitmap; override;
    187     function NewBitmap(AWidth, AHeight: integer; Color: TBGRAPixel): TBGRACustomBitmap; override;
    188     function NewBitmap(Filename: string): TBGRACustomBitmap; override;
    189 
    190     procedure LoadFromFile(const filename: string); override;
     192    {------------------------- Constructors from TFPCustomImage----------------}
     193    constructor Create(AWidth, AHeight: integer); override; //Creates a new bitmap, initialize properties and bitmap data
     194    procedure SetSize(AWidth, AHeight: integer); override;  //Can only be called with an existing instance of TBGRABitmap.
     195                                                            //Sets the dimensions of an existing TBGRABitmap instance.
     196
     197    {------------------------- Constructors from TBGRACustomBitmap-------------}
     198    constructor Create; override;                    //Creates an image of width and height equal to zero.
     199    constructor Create(ABitmap: TBitmap); override;  //Creates an image of dimensions AWidth and AHeight and filled with transparent pixels.
     200    constructor Create(AWidth, AHeight: integer; Color: TColor); override;      //Creates an image of dimensions AWidth and AHeight and fills it with the opaque color Color.
     201    constructor Create(AWidth, AHeight: integer; Color: TBGRAPixel); override;  //Creates an image of dimensions AWidth and AHeight and fills it with Color.
     202
     203    constructor Create(AFilename: string); override; // Creates an image by loading its content from the file AFilename.
     204                                                     // The encoding of the string is the default one for the operating system.
     205                                                     // It is recommended to use the next constructor and UTF8 encoding.
     206
     207    constructor Create(AFilename: string; AIsUtf8: boolean); override; //Creates an image by loading its content from the file AFilename.
     208                                                                       //The boolean AIsUtf8Filename specifies if UTF8 encoding is assumed for the filename.
     209
     210    constructor Create(AStream: TStream); override;  // Creates an image by loading its content from the stream AStream.
     211    destructor Destroy; override;                    // Free the object and all its resources
     212
     213    {------------------------- Quasi-constructors -----------------------------}
     214    function NewBitmap(AWidth, AHeight: integer): TBGRACustomBitmap; override;  //Can only be called from an existing instance of TBGRABitmap.
     215                                                                                //Creates a new instance with dimensions AWidth and AHeight,
     216                                                                                //containing transparent pixels.
     217
     218    function NewBitmap(AWidth, AHeight: integer; Color: TBGRAPixel): TBGRACustomBitmap; override;  //Can only be called from an existing instance of TBGRABitmap.
     219                                                                                //Creates a new instance with dimensions AWidth and AHeight,
     220                                                                                //and fills it with Color.
     221
     222    function NewBitmap(Filename: string): TBGRACustomBitmap; override;          //Can only be called from an existing instance of TBGRABitmap.
     223                                                                                //Creates a new instance with by loading its content
     224                                                                                //from the file Filename. The encoding of the string
     225                                                                                //is the default one for the operating system.
     226
     227    function NewBitmap(Filename: string; AIsUtf8: boolean): TBGRACustomBitmap; override; //Can only be called from an existing instance of TBGRABitmap.
     228                                                                                //Creates a new instance with by loading its content
     229                                                                                //from the file Filename.
     230
    191231    procedure SaveToFile(const filename: string); override;
    192232    procedure SaveToStreamAsPng(Str: TStream); override;
    193     procedure Assign(ABitmap: TBitmap); override; overload;
     233    procedure Assign(ARaster: TRasterImage); override; overload;
    194234    procedure Assign(MemBitmap: TBGRACustomBitmap);override; overload;
    195235    procedure Serialize(AStream: TStream); override;
     
    198238
    199239    {Pixel functions}
    200     function PtInClipRect(x, y: integer): boolean; inline;
    201     procedure SetPixel(x, y: integer; c: TColor); override;
    202     procedure SetPixel(x, y: integer; c: TBGRAPixel); override;
    203     procedure XorPixel(x, y: integer; c: TBGRAPixel); override;
    204     procedure DrawPixel(x, y: integer; c: TBGRAPixel); override;
    205     procedure DrawPixel(x, y: integer; ec: TExpandedPixel); override;
    206     procedure FastBlendPixel(x, y: integer; c: TBGRAPixel); override;
    207     procedure ErasePixel(x, y: integer; alpha: byte); override;
    208     procedure AlphaPixel(x, y: integer; alpha: byte); override;
    209     function GetPixel(x, y: integer): TBGRAPixel; override;
    210     function GetPixel(x, y: single; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel; override;
     240    function PtInClipRect(x, y: int32or64): boolean; inline;
     241    procedure SetPixel(x, y: int32or64; c: TColor); override;
     242    procedure SetPixel(x, y: int32or64; c: TBGRAPixel); override;
     243    procedure XorPixel(x, y: int32or64; c: TBGRAPixel); override;
     244    procedure DrawPixel(x, y: int32or64; c: TBGRAPixel); override;
     245    procedure DrawPixel(x, y: int32or64; ec: TExpandedPixel); override;
     246    procedure FastBlendPixel(x, y: int32or64; c: TBGRAPixel); override;
     247    procedure ErasePixel(x, y: int32or64; alpha: byte); override;
     248    procedure AlphaPixel(x, y: int32or64; alpha: byte); override;
     249    function GetPixel(x, y: int32or64): TBGRAPixel; override;
     250    function GetPixel256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter = rfLinear; smoothBorder: boolean = true): TBGRAPixel; override;
     251    function GetPixel(x, y: single; AResampleFilter: TResampleFilter = rfLinear; smoothBorder: boolean = true): TBGRAPixel; override;
    211252    function GetPixelCycle(x, y: single; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel; override;
    212     function GetPixelCycle(x, y: single; AResampleFilter: TResampleFilter;
    213       repeatX: boolean; repeatY: boolean): TBGRAPixel; override; overload;
     253    function GetPixelCycle(x, y: single; AResampleFilter: TResampleFilter; repeatX: boolean; repeatY: boolean): TBGRAPixel; override;
     254    function GetPixelCycle256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel; override;
     255    function GetPixelCycle256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter; repeatX: boolean; repeatY: boolean): TBGRAPixel; override;
    214256
    215257    {Line primitives}
    216     procedure SetHorizLine(x, y, x2: integer; c: TBGRAPixel); override;
    217     procedure XorHorizLine(x, y, x2: integer; c: TBGRAPixel); override;
    218     procedure DrawHorizLine(x, y, x2: integer; c: TBGRAPixel); override;
    219     procedure DrawHorizLine(x, y, x2: integer; ec: TExpandedPixel); override;
    220     procedure DrawHorizLine(x, y, x2: integer; texture: IBGRAScanner); override;
    221     procedure FastBlendHorizLine(x, y, x2: integer; c: TBGRAPixel); override;
    222     procedure AlphaHorizLine(x, y, x2: integer; alpha: byte); override;
    223     procedure SetVertLine(x, y, y2: integer; c: TBGRAPixel); override;
    224     procedure XorVertLine(x, y, y2: integer; c: TBGRAPixel); override;
    225     procedure DrawVertLine(x, y, y2: integer; c: TBGRAPixel); override;
    226     procedure AlphaVertLine(x, y, y2: integer; alpha: byte); override;
    227     procedure FastBlendVertLine(x, y, y2: integer; c: TBGRAPixel); override;
    228     procedure DrawHorizLineDiff(x, y, x2: integer; c, compare: TBGRAPixel;
     258    procedure SetHorizLine(x, y, x2: int32or64; c: TBGRAPixel); override;
     259    procedure XorHorizLine(x, y, x2: int32or64; c: TBGRAPixel); override;
     260    procedure DrawHorizLine(x, y, x2: int32or64; c: TBGRAPixel); override;
     261    procedure DrawHorizLine(x, y, x2: int32or64; ec: TExpandedPixel); override;
     262    procedure HorizLine(x, y, x2: int32or64; texture: IBGRAScanner; ADrawMode : TDrawMode); override;
     263
     264    procedure FastBlendHorizLine(x, y, x2: int32or64; c: TBGRAPixel); override;
     265    procedure AlphaHorizLine(x, y, x2: int32or64; alpha: byte); override;
     266    procedure SetVertLine(x, y, y2: int32or64; c: TBGRAPixel); override;
     267    procedure XorVertLine(x, y, y2: int32or64; c: TBGRAPixel); override;
     268    procedure DrawVertLine(x, y, y2: int32or64; c: TBGRAPixel); override;
     269    procedure AlphaVertLine(x, y, y2: int32or64; alpha: byte); override;
     270    procedure FastBlendVertLine(x, y, y2: int32or64; c: TBGRAPixel); override;
     271    procedure DrawHorizLineDiff(x, y, x2: int32or64; c, compare: TBGRAPixel;
    229272      maxDiff: byte); override;
    230273
    231274    {Shapes}
    232     procedure DrawLine(x1, y1, x2, y2: integer; c: TBGRAPixel; DrawLastPixel: boolean); override;
     275    procedure DrawPath(APath: IBGRAPath; c: TBGRAPixel; w: single); override;
     276    procedure DrawPath(APath: IBGRAPath; texture: IBGRAScanner; w: single); override;
     277
     278    procedure DrawLine(x1, y1, x2, y2: integer; c: TBGRAPixel; DrawLastPixel: boolean; ADrawMode: TDrawMode = dmDrawWithTransparency); override;
    233279    procedure DrawLineAntialias(x1, y1, x2, y2: integer; c: TBGRAPixel; DrawLastPixel: boolean); override;
    234280    procedure DrawLineAntialias(x1, y1, x2, y2: integer; c1, c2: TBGRAPixel; dashLen: integer; DrawLastPixel: boolean); override;
     
    242288    procedure DrawPolyLineAntialias(const points: array of TPointF; texture: IBGRAScanner; w: single); override;
    243289    procedure DrawPolyLineAntialias(const points: array of TPointF; c: TBGRAPixel; w: single; Closed: boolean); override;
     290    procedure DrawPolyLineAntialias(const points: array of TPointF; c: TBGRAPixel; w: single; fillcolor: TBGRAPixel); override;
    244291    procedure DrawPolygonAntialias(const points: array of TPointF; c: TBGRAPixel; w: single); override;
    245292    procedure DrawPolygonAntialias(const points: array of TPointF; texture: IBGRAScanner; w: single); override;
     293    procedure DrawPolygonAntialias(const points: array of TPointF; c: TBGRAPixel; w: single; fillcolor: TBGRAPixel); override;
    246294
    247295    procedure EraseLine(x1, y1, x2, y2: integer; alpha: byte; DrawLastPixel: boolean); override;
     
    250298    procedure EraseLineAntialias(x1, y1, x2, y2: single; alpha: byte; w: single; Closed: boolean); override;
    251299    procedure ErasePolyLineAntialias(const points: array of TPointF; alpha: byte; w: single); override;
     300
     301    procedure FillPath(APath: IBGRAPath; c: TBGRAPixel); override;
     302    procedure FillPath(APath: IBGRAPath; texture: IBGRAScanner); override;
    252303
    253304    procedure FillTriangleLinearColor(pt1,pt2,pt3: TPointF; c1,c2,c3: TBGRAPixel); override;
     
    263314    procedure FillQuadLinearMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); override;
    264315    procedure FillQuadPerspectiveMapping(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); override;
     316    procedure FillQuadPerspectiveMapping(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; ACleanBorders: TRect); override;
    265317    procedure FillQuadPerspectiveMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); override;
     318    procedure FillQuadPerspectiveMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; ACleanBorders: TRect); override;
    266319
    267320    procedure FillPolyLinearMapping(const points: array of TPointF; texture: IBGRAScanner; texCoords: array of TPointF; TextureInterpolation: Boolean); override;
     
    270323    procedure FillPolyPerspectiveMapping(const points: array of TPointF; const pointsZ: array of single; texture: IBGRAScanner; texCoords: array of TPointF; TextureInterpolation: Boolean; zbuffer: psingle = nil); override;
    271324    procedure FillPolyPerspectiveMappingLightness(const points: array of TPointF; const pointsZ: array of single; texture: IBGRAScanner; texCoords: array of TPointF; lightnesses: array of word; TextureInterpolation: Boolean; zbuffer: psingle = nil); override;
     325
    272326    procedure FillPoly(const points: array of TPointF; c: TBGRAPixel; drawmode: TDrawMode); override;
    273327    procedure FillPoly(const points: array of TPointF; texture: IBGRAScanner; drawmode: TDrawMode); override;
     
    276330    procedure ErasePoly(const points: array of TPointF; alpha: byte); override;
    277331    procedure ErasePolyAntialias(const points: array of TPointF; alpha: byte); override;
     332
     333    procedure FillShape(shape: TBGRACustomFillInfo; c: TBGRAPixel; drawmode: TDrawMode); override;
     334    procedure FillShape(shape: TBGRACustomFillInfo; texture: IBGRAScanner; drawmode: TDrawMode); override;
     335    procedure FillShapeAntialias(shape: TBGRACustomFillInfo; c: TBGRAPixel); override;
     336    procedure FillShapeAntialias(shape: TBGRACustomFillInfo; texture: IBGRAScanner); override;
     337    procedure EraseShape(shape: TBGRACustomFillInfo; alpha: byte); override;
     338    procedure EraseShapeAntialias(shape: TBGRACustomFillInfo; alpha: byte); override;
    278339
    279340    procedure EllipseAntialias(x, y, rx, ry: single; c: TBGRAPixel; w: single); override;
     
    295356    procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; penTexture: IBGRAScanner; w: single; fillTexture: IBGRAScanner; options: TRoundRectangleOptions = []); override;
    296357
    297     procedure FillRect(x, y, x2, y2: integer; c: TBGRAPixel; mode: TDrawMode); override;
    298     procedure FillRect(x, y, x2, y2: integer; texture: IBGRAScanner; mode: TDrawMode); override;
     358    procedure FillRect(x, y, x2, y2: integer; c: TBGRAPixel; mode: TDrawMode); override; overload;
     359    procedure FillRect(x, y, x2, y2: integer; texture: IBGRAScanner; mode: TDrawMode); override; overload;
    299360    procedure FillRectAntialias(x, y, x2, y2: single; c: TBGRAPixel); override;
    300361    procedure EraseRectAntialias(x, y, x2, y2: single; alpha: byte); override;
     
    305366    procedure AlphaFillRect(x, y, x2, y2: integer; alpha: byte); override;
    306367    procedure RoundRect(X1, Y1, X2, Y2: integer; DX, DY: integer;
    307       BorderColor, FillColor: TBGRAPixel); override;
    308 
    309     procedure TextOutAngle(x, y: single; orientation: integer; s: string; c: TBGRAPixel; align: TAlignment); override;
    310     procedure TextOutAngle(x, y: single; orientation: integer; s: string; texture: IBGRAScanner; align: TAlignment); override;
    311     procedure TextOut(x, y: single; s: string; texture: IBGRAScanner; align: TAlignment); override;
    312     procedure TextOut(x, y: single; s: string; c: TBGRAPixel; align: TAlignment); override;
    313     procedure TextRect(ARect: TRect; x, y: integer; s: string; style: TTextStyle; c: TBGRAPixel); override;
    314     procedure TextRect(ARect: TRect; x, y: integer; s: string; style: TTextStyle; texture: IBGRAScanner); override;
    315     function TextSize(s: string): TSize; override;
     368      BorderColor, FillColor: TBGRAPixel; ADrawMode: TDrawMode = dmDrawWithTransparency); override;
     369    procedure RoundRect(X1, Y1, X2, Y2: integer; DX, DY: integer;
     370      BorderColor: TBGRAPixel; ADrawMode: TDrawMode = dmDrawWithTransparency); override;
     371
     372    { Draws the UTF8 encoded string, with color c.
     373      If align is taLeftJustify, (x,y) is the top-left corner.
     374      If align is taCenter, (x,y) is at the top and middle of the text.
     375      If align is taRightJustify, (x,y) is the top-right corner.
     376      The value of FontOrientation is taken into account, so that the text may be rotated. }
     377    procedure TextOut(x, y: single; sUTF8: string; c: TBGRAPixel; align: TAlignment); override; overload;
     378
     379    { Same as above functions, except that the text is filled using texture.
     380      The value of FontOrientation is taken into account, so that the text may be rotated. }
     381    procedure TextOut(x, y: single; sUTF8: string; texture: IBGRAScanner; align: TAlignment); override; overload;
     382
     383    { Same as above, except that the orientation is specified, overriding the value of the property FontOrientation. }
     384    procedure TextOutAngle(x, y: single; orientationTenthDegCCW: integer; sUTF8: string; c: TBGRAPixel; align: TAlignment); override; overload;
     385    procedure TextOutAngle(x, y: single; orientationTenthDegCCW: integer; sUTF8: string; texture: IBGRAScanner; align: TAlignment); override; overload;
     386
     387    { Draw the UTF8 encoded string at the coordinate (x,y), clipped inside the rectangle ARect.
     388      Additional style information is provided by the style parameter.
     389      The color c or texture is used to fill the text. No rotation is applied. }
     390    procedure TextRect(ARect: TRect; x, y: integer; sUTF8: string; style: TTextStyle; c: TBGRAPixel); override; overload;
     391    procedure TextRect(ARect: TRect; x, y: integer; sUTF8: string; style: TTextStyle; texture: IBGRAScanner); override; overload;
     392
     393    { Returns the total size of the string provided using the current font.
     394      Orientation is not taken into account, so that the width is along the text.  }
     395    function TextSize(sUTF8: string): TSize; override;
    316396
    317397    {Spline}
     
    344424    procedure DrawPixels(c: TBGRAPixel; start, Count: integer); override;
    345425    procedure AlphaFill(alpha: byte; start, Count: integer); override;
    346     procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; color: TBGRAPixel); override;
    347     procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; texture: IBGRAScanner); override;
     426    procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; color: TBGRAPixel; ADrawMode: TDrawMode); override;
     427    procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; texture: IBGRAScanner; ADrawMode: TDrawMode); override;
    348428    procedure FillClearTypeMask(x,y: integer; xThird: integer; AMask: TBGRACustomBitmap; color: TBGRAPixel; ARGBOrder: boolean = true); override;
    349429    procedure FillClearTypeMask(x,y: integer; xThird: integer; AMask: TBGRACustomBitmap; texture: IBGRAScanner; ARGBOrder: boolean = true); override;
     
    380460
    381461    {BGRA bitmap functions}
     462    procedure CrossFade(ARect: TRect; Source1, Source2: IBGRAScanner; AFadePosition: byte; mode: TDrawMode = dmDrawWithTransparency); override;
     463    procedure CrossFade(ARect: TRect; Source1, Source2: IBGRAScanner; AFadeMask: IBGRAScanner; mode: TDrawMode = dmDrawWithTransparency); override;
    382464    procedure PutImage(x, y: integer; Source: TBGRACustomBitmap; mode: TDrawMode; AOpacity: byte = 255); override;
    383     procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255; ARestoreOffsetAfterRotation: boolean = false); override;
    384     procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AOpacity: Byte=255); override;
     465    procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AOutputBounds: TRect; AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte=255); override;
     466    procedure StretchPutImage(ARect: TRect; Source: TBGRACustomBitmap; mode: TDrawMode; AOpacity: byte = 255); override;
     467
    385468    procedure BlendImage(x, y: integer; Source: TBGRACustomBitmap; operation: TBlendOperation); override;
    386469    procedure BlendImageOver(x, y: integer; Source: TBGRACustomBitmap; operation: TBlendOperation; AOpacity: byte = 255;
     
    394477    function Equals(comp: TBGRAPixel): boolean; override;
    395478    function GetImageBounds(Channel: TChannel = cAlpha; ANothingValue: Byte = 0): TRect; override;
    396     function GetImageBounds(Channels: TChannels): TRect; override;
     479    function GetImageBounds(Channels: TChannels; ANothingValue: Byte = 0): TRect; override;
    397480    function GetDifferenceBounds(ABitmap: TBGRACustomBitmap): TRect; override;
    398481    function MakeBitmapCopy(BackgroundColor: TColor): TBitmap; override;
     
    400483    function Resample(newWidth, newHeight: integer;
    401484      mode: TResampleMode = rmFineResample): TBGRACustomBitmap; override;
    402     procedure VerticalFlip; override;
    403     procedure HorizontalFlip; override;
     485    procedure VerticalFlip(ARect: TRect); override;
     486    procedure HorizontalFlip(ARect: TRect); override;
    404487    function RotateCW: TBGRACustomBitmap; override;
    405488    function RotateCCW: TBGRACustomBitmap; override;
    406489    procedure Negative; override;
     490    procedure NegativeRect(ABounds: TRect); override;
    407491    procedure LinearNegative; override;
     492    procedure LinearNegativeRect(ABounds: TRect); override;
     493    procedure InplaceGrayscale; override;
     494    procedure InplaceGrayscale(ABounds: TRect); override;
    408495    procedure SwapRedBlue; override;
    409496    procedure GrayscaleToAlpha; override;
    410497    procedure AlphaToGrayscale; override;
    411     procedure ApplyMask(mask: TBGRACustomBitmap); override;
     498    procedure ApplyMask(mask: TBGRACustomBitmap; ARect: TRect; AMaskRectTopLeft: TPoint); override;
    412499    procedure ApplyGlobalOpacity(alpha: byte); override;
    413500    procedure ConvertToLinearRGB; override;
    414501    procedure ConvertFromLinearRGB; override;
     502    procedure DrawCheckers(ARect: TRect; AColorEven,AColorOdd: TBGRAPixel);
    415503
    416504    {Filters}
     
    418506    function FilterMedian(Option: TMedianOption): TBGRACustomBitmap; override;
    419507    function FilterSmooth: TBGRACustomBitmap; override;
    420     function FilterSharpen: TBGRACustomBitmap; override;
     508    function FilterSharpen(Amount: single = 1): TBGRACustomBitmap; override;
     509    function FilterSharpen(ABounds: TRect; Amount: single = 1): TBGRACustomBitmap; override;
    421510    function FilterContour: TBGRACustomBitmap; override;
     511    function FilterPixelate(pixelSize: integer; useResample: boolean; filter: TResampleFilter = rfLinear): TBGRACustomBitmap; override;
    422512    function FilterBlurRadial(radius: integer;
    423513      blurType: TRadialBlurType): TBGRACustomBitmap; override;
    424     function FilterPixelate(pixelSize: integer; useResample: boolean; filter: TResampleFilter = rfLinear): TBGRACustomBitmap; override;
     514    function FilterBlurRadial(ABounds: TRect; radius: integer;
     515      blurType: TRadialBlurType): TBGRACustomBitmap; override;
    425516    function FilterBlurMotion(distance: integer; angle: single;
    426517      oriented: boolean): TBGRACustomBitmap; override;
     518    function FilterBlurMotion(ABounds: TRect; distance: integer; angle: single;
     519      oriented: boolean): TBGRACustomBitmap; override;
    427520    function FilterCustomBlur(mask: TBGRACustomBitmap): TBGRACustomBitmap; override;
     521    function FilterCustomBlur(ABounds: TRect; mask: TBGRACustomBitmap): TBGRACustomBitmap; override;
    428522    function FilterEmboss(angle: single): TBGRACustomBitmap; override;
     523    function FilterEmboss(angle: single; ABounds: TRect): TBGRACustomBitmap; override;
    429524    function FilterEmbossHighlight(FillSelection: boolean): TBGRACustomBitmap; override;
    430525    function FilterEmbossHighlight(FillSelection: boolean; BorderColor: TBGRAPixel): TBGRACustomBitmap; override;
    431526    function FilterEmbossHighlight(FillSelection: boolean; BorderColor: TBGRAPixel; var Offset: TPoint): TBGRACustomBitmap; override;
    432527    function FilterGrayscale: TBGRACustomBitmap; override;
     528    function FilterGrayscale(ABounds: TRect): TBGRACustomBitmap; override;
    433529    function FilterNormalize(eachChannel: boolean = True): TBGRACustomBitmap; override;
    434     function FilterRotate(origin: TPointF; angle: single): TBGRACustomBitmap; override;
     530    function FilterNormalize(ABounds: TRect; eachChannel: boolean = True): TBGRACustomBitmap; override;
     531    function FilterRotate(origin: TPointF; angle: single; correctBlur: boolean = false): TBGRACustomBitmap; override;
    435532    function FilterSphere: TBGRACustomBitmap; override;
    436533    function FilterTwirl(ACenter: TPoint; ARadius: Single; ATurn: Single=1; AExponent: Single=3): TBGRACustomBitmap; override;
     534    function FilterTwirl(ABounds: TRect; ACenter: TPoint; ARadius: Single; ATurn: Single=1; AExponent: Single=3): TBGRACustomBitmap; override;
    437535    function FilterCylinder: TBGRACustomBitmap; override;
    438536    function FilterPlane: TBGRACustomBitmap; override;
     
    465563
    466564uses Math, LCLIntf, LCLType,
    467   BGRABlend, BGRAFilters, BGRAPen, BGRAText, BGRATextFX, BGRAGradientScanner,
     565  BGRABlend, BGRAFilters, BGRAText, BGRATextFX, BGRAGradientScanner,
    468566  BGRAResample, BGRATransform, BGRAPolygon, BGRAPolygonAliased,
    469567  BGRAPath, FPReadPcx, FPWritePcx, FPReadXPM, FPWriteXPM;
     
    486584procedure TBitmapTracker.Changed(Sender: TObject);
    487585begin
    488   FUser.FBitmapModified := True;
     586  if FUser <> nil then
     587    FUser.FBitmapModified := True;
    489588  inherited Changed(Sender);
    490589end;
     
    570669end;
    571670
    572 { Update font properties to internal TFont object }
    573 procedure TBGRADefaultBitmap.UpdateFont;
    574 begin
    575   if FFont.Name <> FontName then
    576     FFont.Name := FontName;
    577   if FFont.Style <> FontStyle then
    578     FFont.Style := FontStyle;
    579   if FFont.Height <> FFontHeight * FFontHeightSign then
    580     FFont.Height := FFontHeight * FFontHeightSign;
    581   if FFont.Orientation <> FontOrientation then
    582     FFont.Orientation := FontOrientation;
    583   if FontQuality = fqSystemClearType then
    584     FFont.Quality := fqCleartype
    585   else
    586     FFont.Quality := FontDefaultQuality;
     671function TBGRADefaultBitmap.GetLineCap: TPenEndCap;
     672begin
     673  result := FLineCap;
     674end;
     675
     676procedure TBGRADefaultBitmap.SetLineCap(AValue: TPenEndCap);
     677begin
     678  if AValue <> FLineCap then
     679  begin
     680    FLineCap:= AValue;
     681    if Assigned(FArrow) then FArrow.LineCap := AValue;
     682  end;
     683end;
     684
     685function TBGRADefaultBitmap.GetArrowEndSize: TPointF;
     686begin
     687  result := GetArrow.EndSize;
     688end;
     689
     690function TBGRADefaultBitmap.GetArrowStartSize: TPointF;
     691begin
     692  result := GetArrow.StartSize;
     693end;
     694
     695procedure TBGRADefaultBitmap.SetArrowEndSize(AValue: TPointF);
     696begin
     697  GetArrow.EndSize := AValue;
     698end;
     699
     700procedure TBGRADefaultBitmap.SetArrowStartSize(AValue: TPointF);
     701begin
     702  GetArrow.StartSize := AValue;
     703end;
     704
     705function TBGRADefaultBitmap.GetArrowEndOffset: single;
     706begin
     707  result := GetArrow.EndOffsetX;
     708end;
     709
     710function TBGRADefaultBitmap.GetArrowStartOffset: single;
     711begin
     712  result := GetArrow.StartOffsetX;
     713end;
     714
     715procedure TBGRADefaultBitmap.SetArrowEndOffset(AValue: single);
     716begin
     717  GetArrow.EndOffsetX := AValue;
     718end;
     719
     720procedure TBGRADefaultBitmap.SetArrowStartOffset(AValue: single);
     721begin
     722  GetArrow.StartOffsetX := AValue;
     723end;
     724
     725function TBGRADefaultBitmap.GetArrowEndRepeat: integer;
     726begin
     727  result := GetArrow.EndRepeatCount;
     728end;
     729
     730function TBGRADefaultBitmap.GetArrowStartRepeat: integer;
     731begin
     732  result := GetArrow.StartRepeatCount;
     733end;
     734
     735procedure TBGRADefaultBitmap.SetArrowEndRepeat(AValue: integer);
     736begin
     737  GetArrow.EndRepeatCount := AValue;
     738end;
     739
     740procedure TBGRADefaultBitmap.SetArrowStartRepeat(AValue: integer);
     741begin
     742  GetArrow.StartRepeatCount := AValue;
    587743end;
    588744
     
    609765
    610766function TBGRADefaultBitmap.GetFontPixelMetric: TFontPixelMetric;
    611 var fxFont: TFont;
    612 begin
    613   UpdateFont;
    614   if FontQuality = fqSystem then
    615     result := BGRAText.GetFontPixelMetric(FFont)
    616   else
    617   begin
    618     FxFont := TFont.Create;
    619     FxFont.Assign(FFont);
    620     FxFont.Height := fxFont.Height*FontAntialiasingLevel;
    621     Result:= BGRAText.GetFontPixelMetric(FxFont);
    622     if Result.Baseline <> -1 then Result.Baseline:= round((Result.Baseline-1)/FontAntialiasingLevel);
    623     if Result.CapLine <> -1 then Result.CapLine:= round(Result.CapLine/FontAntialiasingLevel);
    624     if Result.DescentLine <> -1 then Result.DescentLine:= round((Result.DescentLine-1)/FontAntialiasingLevel);
    625     if Result.Lineheight <> -1 then Result.Lineheight:= round(Result.Lineheight/FontAntialiasingLevel);
    626     if Result.xLine <> -1 then Result.xLine:= round(Result.xLine/FontAntialiasingLevel);
    627   end;
     767begin
     768  result := FontRenderer.GetFontPixelMetric;
     769end;
     770
     771function TBGRADefaultBitmap.GetFontRenderer: TBGRACustomFontRenderer;
     772begin
     773  if FFontRenderer = nil then FFontRenderer := TLCLFontRenderer.Create;
     774  result := FFontRenderer;
     775  result.FontName := FontName;
     776  result.FontStyle := FontStyle;
     777  result.FontQuality := FontQuality;
     778  result.FontOrientation := FontOrientation;
     779  result.FontEmHeight := FFontHeight;
     780end;
     781
     782procedure TBGRADefaultBitmap.SetFontRenderer(AValue: TBGRACustomFontRenderer);
     783begin
     784  if AValue = FFontRenderer then exit;
     785  FFontRenderer.Free;
     786  FFontRenderer := AValue
    628787end;
    629788
     
    689848end;
    690849
    691 { Creates a new bitmap. Internally, it uses the same type so that if you
     850{ Creates a new bitmap with dimensions AWidth and AHeight and filled with
     851  transparent pixels. Internally, it uses the same type so that if you
    692852  use an optimized version, you get a new bitmap with the same optimizations }
    693853function TBGRADefaultBitmap.NewBitmap(AWidth, AHeight: integer): TBGRACustomBitmap;
     
    701861end;
    702862
     863{ Can only be called from an existing instance of TBGRABitmap.
     864  Creates a new instance with dimensions AWidth and AHeight,
     865  and fills it with Color. }
    703866function TBGRADefaultBitmap.NewBitmap(AWidth, AHeight: integer;
    704867  Color: TBGRAPixel): TBGRACustomBitmap;
     
    712875end;
    713876
    714 { Creates a new bitmap and loads it contents from a file }
     877{ Creates a new bitmap and loads it contents from a file.
     878  The encoding of the string is the default one for the operating system.
     879  It is recommended to use the next function and UTF8 encoding }
    715880function TBGRADefaultBitmap.NewBitmap(Filename: string): TBGRACustomBitmap;
    716881var
     
    719884  BGRAClass := TBGRABitmapAny(self.ClassType);
    720885  Result    := BGRAClass.Create(Filename);
     886end;
     887
     888{ Creates a new bitmap and loads it contents from a file.
     889  It is recommended to use UTF8 encoding }
     890function TBGRADefaultBitmap.NewBitmap(Filename: string; AIsUtf8: boolean): TBGRACustomBitmap;
     891var
     892  BGRAClass: TBGRABitmapAny;
     893begin
     894  BGRAClass := TBGRABitmapAny(self.ClassType);
     895  Result    := BGRAClass.Create(Filename,AIsUtf8);
    721896end;
    722897
     
    754929{---------------------- Constructors ---------------------------------}
    755930
     931{ Creates an image of width and height equal to zero. }
    756932constructor TBGRADefaultBitmap.Create;
    757933begin
     
    760936end;
    761937
     938{ Creates an image of dimensions AWidth and AHeight and filled with transparent pixels. }
    762939constructor TBGRADefaultBitmap.Create(ABitmap: TBitmap);
    763940begin
     
    767944end;
    768945
     946{ Creates an image of dimensions AWidth and AHeight and fills it with the opaque color Color. }
    769947constructor TBGRADefaultBitmap.Create(AWidth, AHeight: integer; Color: TColor);
    770948begin
     
    774952end;
    775953
     954{ Creates an image of dimensions AWidth and AHeight and fills it with Color. }
    776955constructor TBGRADefaultBitmap.Create(AWidth, AHeight: integer; Color: TBGRAPixel);
    777956begin
     
    781960end;
    782961
     962{ Creates an image by loading its content from the file AFilename.
     963  The encoding of the string is the default one for the operating system.
     964  It is recommended to use the next constructor and UTF8 encoding. }
     965constructor TBGRADefaultBitmap.Create(AFilename: string);
     966begin
     967  Init;
     968  inherited Create(0, 0);
     969  LoadFromFile(Afilename);
     970end;
     971
     972{ Free the object and all its resources }
    783973destructor TBGRADefaultBitmap.Destroy;
    784974begin
    785975  FreeData;
    786   FFont.Free;
     976  FFontRenderer.Free;
    787977  FBitmap.Free;
    788978  FCanvasFP.Free;
    789979  FCanvasBGRA.Free;
    790980  FCanvas2D.Free;
     981  FArrow.Free;
    791982  inherited Destroy;
    792983end;
     
    794985{------------------------- Loading functions ----------------------------------}
    795986
    796 constructor TBGRADefaultBitmap.Create(AFilename: string);
     987{ Creates an image by loading its content from the file AFilename.
     988  The boolean AIsUtf8Filename specifies if UTF8 encoding is assumed for the filename. }
     989constructor TBGRADefaultBitmap.Create(AFilename: string; AIsUtf8: boolean);
    797990begin
    798991  Init;
    799   inherited Create(0, 0); 
    800   LoadFromFile(Afilename);
    801 end;
    802 
     992  inherited Create(0, 0);
     993  if AIsUtf8 then
     994    LoadFromFileUTF8(Afilename)
     995  else
     996    LoadFromFile(Afilename);
     997end;
     998
     999{ Creates an image by loading its content from the stream AStream. }
    8031000constructor TBGRADefaultBitmap.Create(AStream: TStream);
    8041001begin
     
    8081005end;
    8091006
    810 procedure TBGRADefaultBitmap.Assign(ABitmap: TBitmap);
     1007procedure TBGRADefaultBitmap.Assign(ARaster: TRasterImage);
    8111008var TempBmp: TBitmap;
    8121009    ConvertOk: boolean;
    8131010begin
    8141011  DiscardBitmapChange;
    815   SetSize(ABitmap.Width, ABitmap.Height);
    816   if not LoadFromRawImage(ABitmap.RawImage,0,False,False) then
     1012  SetSize(ARaster.Width, ARaster.Height);
     1013  if not LoadFromRawImage(ARaster.RawImage,0,False,False) then
     1014  if ARaster is TBitmap then
    8171015  begin //try to convert
    8181016    TempBmp := TBitmap.Create;
    819     TempBmp.Width := ABitmap.Width;
    820     TempBmp.Height := ABitmap.Height;
    821     TempBmp.Canvas.Draw(0,0,ABitmap);
     1017    TempBmp.Width := ARaster.Width;
     1018    TempBmp.Height := ARaster.Height;
     1019    TempBmp.Canvas.Draw(0,0,ARaster);
    8221020    ConvertOk := LoadFromRawImage(TempBmp.RawImage,0,False,False);
    8231021    TempBmp.Free;
    8241022    if not ConvertOk then
    8251023      raise Exception.Create('Unable to convert image to 24 bit');
    826   end;
     1024  end else
     1025    raise Exception.Create('Unable to convert image to 24 bit');
    8271026  If Empty then AlphaFill(255); // if bitmap seems to be empty, assume
    8281027                                // it is an opaque bitmap without alpha channel
     
    8371036
    8381037procedure TBGRADefaultBitmap.Serialize(AStream: TStream);
    839 var lWidth,lHeight: integer;
     1038var lWidth,lHeight,y: integer;
    8401039begin
    8411040  lWidth := NtoLE(Width);
     
    8431042  AStream.Write(lWidth,sizeof(lWidth));
    8441043  AStream.Write(lHeight,sizeof(lHeight));
    845   AStream.Write(Data^, NbPixels*sizeof(TBGRAPixel));
     1044  for y := 0 to Height-1 do
     1045    AStream.Write(ScanLine[y]^, Width*sizeof(TBGRAPixel));
    8461046end;
    8471047
    8481048{$hints off}
    8491049procedure TBGRADefaultBitmap.Deserialize(AStream: TStream);
    850 var lWidth,lHeight: integer;
     1050var lWidth,lHeight,y: integer;
    8511051begin
    8521052  AStream.Read(lWidth,sizeof(lWidth));
     
    8551055  lHeight := LEtoN(lHeight);
    8561056  SetSize(lWidth,lHeight);
    857   AStream.Read(Data^, NbPixels*sizeof(TBGRAPixel));
     1057  for y := 0 to Height-1 do
     1058    AStream.Read(ScanLine[y]^, Width*sizeof(TBGRAPixel));
    8581059end;
    8591060{$hints on}
     
    8651066  AStream.Write(zero,sizeof(zero));
    8661067  AStream.Write(zero,sizeof(zero));
    867 end;
    868 
    869 procedure TBGRADefaultBitmap.LoadFromFile(const filename: string);
    870 var
    871   OldDrawMode: TDrawMode;
    872 begin
    873   OldDrawMode := CanvasDrawModeFP;
    874   CanvasDrawModeFP := dmSet;
    875   ClipRect := rect(0,0,Width,Height);
    876   try
    877     inherited LoadFromfile(filename);
    878   finally
    879     CanvasDrawModeFP := OldDrawMode;
    880     ClearTransparentPixels;
    881   end;
    8821068end;
    8831069
     
    9181104
    9191105{ Check if a point is in the clipping rectangle }
    920 function TBGRADefaultBitmap.PtInClipRect(x, y: integer): boolean;
     1106function TBGRADefaultBitmap.PtInClipRect(x, y: int32or64): boolean;
    9211107begin
    9221108  result := (x >= FClipRect.Left) and (y >= FClipRect.Top) and (x < FClipRect.Right) and (y < FClipRect.Bottom);
     
    9431129end;
    9441130
    945 function TBGRADefaultBitmap.GetPixelCycleInline(ix, iy: integer; iFactX,
    946   iFactY: integer): TBGRAPixel;
    947 var
    948   ixMod1,ixMod2: integer;
    949   w1,w2,w3,w4,alphaW: cardinal;
    950   bSum, gSum, rSum: cardinal;
    951   aSum: cardinal;
     1131function TBGRADefaultBitmap.InternalGetPixelCycle256(ix, iy: int32or64; iFactX,
     1132  iFactY: int32or64): TBGRAPixel;
     1133var
     1134  ixMod1,ixMod2: int32or64;
     1135  w1,w2,w3,w4,alphaW: UInt32or64;
     1136  bSum, gSum, rSum: UInt32or64;
     1137  aSum: UInt32or64;
    9521138
    9531139  c:    TBGRAPixel;
     
    9641150  aSum   := 0;
    9651151
    966   scan := GetScanlineFast(PositiveMod(iy,Height));
    967 
    968   ixMod1 := PositiveMod(ix,Width); //apply cycle
    969   c      := (scan + ixMod1)^;
     1152  scan := GetScanlineFast(iy);
     1153
     1154  ixMod1 := ix;
     1155  c      := (scan + ix)^;
    9701156  alphaW := c.alpha * w1;
    9711157  aSum   += alphaW;
     
    9751161  bSum   += c.blue * alphaW;
    9761162
    977   Inc(ix);
    978   ixMod2 := PositiveMod(ix,Width); //apply cycle
     1163  ixMod2 := ix+1;
     1164  if ixMod2=Width then ixMod2 := 0;
    9791165  c      := (scan + ixMod2)^;
    9801166  alphaW := c.alpha * w2;
     
    9861172
    9871173  Inc(iy);
    988   scan := GetScanlineFast(PositiveMod(iy,Height));
     1174  if iy = Height then iy := 0;
     1175  scan := GetScanlineFast(iy);
    9891176
    9901177  c      := (scan + ixMod2)^;
     
    10141201  end;
    10151202end;
     1203
     1204function TBGRADefaultBitmap.InternalGetPixel256(ix, iy: int32or64; iFactX,
     1205  iFactY: int32or64; smoothBorder: boolean): TBGRAPixel;
     1206var
     1207  w1,w2,w3,w4,alphaW: cardinal;
     1208  rSum, gSum, bSum: cardinal; //rgbDiv = aSum
     1209  aSum, aDiv: cardinal;
     1210  c:    TBGRAPixel;
     1211  scan: PBGRAPixel;
     1212begin
     1213  rSum   := 0;
     1214  gSum   := 0;
     1215  bSum   := 0;
     1216  aSum   := 0;
     1217  aDiv   := 0;
     1218
     1219  w4 := (iFactX*iFactY+127) shr 8;
     1220  w3 := iFactY-w4;
     1221  {$PUSH}{$HINTS OFF}
     1222  w1 := (256-iFactX)-w3;
     1223  {$POP}
     1224  w2 := iFactX-w4;
     1225
     1226  { For each pixel around the coordinate, compute
     1227    the weight for it and multiply values by it before
     1228    adding to the sum }
     1229  if (iy >= 0) and (iy < Height) then
     1230  begin
     1231    scan := GetScanlineFast(iy);
     1232
     1233    if (ix >= 0) and (ix < Width) then
     1234    begin
     1235      c      := (scan + ix)^;
     1236      alphaW := c.alpha * w1;
     1237      aDiv   += w1;
     1238      aSum   += alphaW;
     1239      rSum   += c.red * alphaW;
     1240      gSum   += c.green * alphaW;
     1241      bSum   += c.blue * alphaW;
     1242    end;
     1243
     1244    Inc(ix);
     1245    if (ix >= 0) and (ix < Width) then
     1246    begin
     1247      c      := (scan + ix)^;
     1248      alphaW := c.alpha * w2;
     1249      aDiv   += w2;
     1250      aSum   += alphaW;
     1251      rSum   += c.red * alphaW;
     1252      gSum   += c.green * alphaW;
     1253      bSum   += c.blue * alphaW;
     1254    end;
     1255  end
     1256  else
     1257  begin
     1258    Inc(ix);
     1259  end;
     1260
     1261  Inc(iy);
     1262  if (iy >= 0) and (iy < Height) then
     1263  begin
     1264    scan := GetScanlineFast(iy);
     1265
     1266    if (ix >= 0) and (ix < Width) then
     1267    begin
     1268      c      := (scan + ix)^;
     1269      alphaW := c.alpha * w4;
     1270      aDiv   += w4;
     1271      aSum   += alphaW;
     1272      rSum   += c.red * alphaW;
     1273      gSum   += c.green * alphaW;
     1274      bSum   += c.blue * alphaW;
     1275    end;
     1276
     1277    Dec(ix);
     1278    if (ix >= 0) and (ix < Width) then
     1279    begin
     1280      c      := (scan + ix)^;
     1281      alphaW := c.alpha * w3;
     1282      aDiv   += w3;
     1283      aSum   += alphaW;
     1284      rSum   += c.red * alphaW;
     1285      gSum   += c.green * alphaW;
     1286      bSum   += c.blue * alphaW;
     1287    end;
     1288  end;
     1289
     1290  if aSum < 128 then //if there is no alpha
     1291    Result := BGRAPixelTransparent
     1292  else
     1293  begin
     1294    Result.red   := (rSum + aSum shr 1) div aSum;
     1295    Result.green := (gSum + aSum shr 1) div aSum;
     1296    Result.blue  := (bSum + aSum shr 1) div aSum;
     1297    if smoothBorder or (aDiv = 256) then
     1298      Result.alpha := (aSum + 128) shr 8
     1299    else
     1300      Result.alpha := (aSum + aDiv shr 1) div aDiv;
     1301  end;
     1302end;
     1303
     1304function TBGRADefaultBitmap.GetPolyLineOption: TBGRAPolyLineOptions;
     1305begin
     1306  result := [];
     1307  if Assigned(FArrow) and FArrow.IsStartDefined then result += [plNoStartCap];
     1308  if Assigned(FArrow) and FArrow.IsEndDefined then result += [plNoEndCap];
     1309end;
     1310
     1311function TBGRADefaultBitmap.GetArrow: TBGRAArrow;
     1312begin
     1313  if FArrow = nil then
     1314  begin
     1315    FArrow := TBGRAArrow.Create;
     1316    FArrow.LineCap := LineCap;
     1317  end;
     1318  result := FArrow;
     1319end;
     1320
    10161321{-------------------------- Pixel functions -----------------------------------}
    10171322
    1018 procedure TBGRADefaultBitmap.SetPixel(x, y: integer; c: TBGRAPixel);
     1323procedure TBGRADefaultBitmap.SetPixel(x, y: int32or64; c: TBGRAPixel);
    10191324begin
    10201325  if not PtInClipRect(x,y) then exit;
     
    10241329end;
    10251330
    1026 procedure TBGRADefaultBitmap.XorPixel(x, y: integer; c: TBGRAPixel);
     1331procedure TBGRADefaultBitmap.XorPixel(x, y: int32or64; c: TBGRAPixel);
    10271332var
    10281333  p : PDWord;
     
    10351340end;
    10361341
    1037 procedure TBGRADefaultBitmap.SetPixel(x, y: integer; c: TColor);
     1342procedure TBGRADefaultBitmap.SetPixel(x, y: int32or64; c: TColor);
    10381343var
    10391344  p: PByte;
     
    10521357end;
    10531358
    1054 procedure TBGRADefaultBitmap.DrawPixel(x, y: integer; c: TBGRAPixel);
     1359procedure TBGRADefaultBitmap.DrawPixel(x, y: int32or64; c: TBGRAPixel);
    10551360begin
    10561361  if not PtInClipRect(x,y) then exit;
     
    10601365end;
    10611366
    1062 procedure TBGRADefaultBitmap.DrawPixel(x, y: integer; ec: TExpandedPixel);
     1367procedure TBGRADefaultBitmap.DrawPixel(x, y: int32or64; ec: TExpandedPixel);
    10631368begin
    10641369  if not PtInClipRect(x,y) then exit;
     
    10681373end;
    10691374
    1070 procedure TBGRADefaultBitmap.FastBlendPixel(x, y: integer; c: TBGRAPixel);
     1375procedure TBGRADefaultBitmap.FastBlendPixel(x, y: int32or64; c: TBGRAPixel);
    10711376begin
    10721377  if not PtInClipRect(x,y) then exit;
     
    10761381end;
    10771382
    1078 procedure TBGRADefaultBitmap.ErasePixel(x, y: integer; alpha: byte);
     1383procedure TBGRADefaultBitmap.ErasePixel(x, y: int32or64; alpha: byte);
    10791384begin
    10801385  if not PtInClipRect(x,y) then exit;
     
    10841389end;
    10851390
    1086 procedure TBGRADefaultBitmap.AlphaPixel(x, y: integer; alpha: byte);
     1391procedure TBGRADefaultBitmap.AlphaPixel(x, y: int32or64; alpha: byte);
    10871392begin
    10881393  if not PtInClipRect(x,y) then exit;
     
    10951400end;
    10961401
    1097 function TBGRADefaultBitmap.GetPixel(x, y: integer): TBGRAPixel;
     1402function TBGRADefaultBitmap.GetPixel(x, y: int32or64): TBGRAPixel;
    10981403begin
    10991404  if (x < 0) or (x >= Width) or (y < 0) or (y >= Height) then //it is possible to read pixels outside of the cliprect
     
    11061411end;
    11071412
     1413function TBGRADefaultBitmap.GetPixel256(x, y, fracX256, fracY256: int32or64;
     1414  AResampleFilter: TResampleFilter; smoothBorder: boolean = true): TBGRAPixel;
     1415begin
     1416  if (fracX256 = 0) and (fracY256 = 0) then
     1417    result := GetPixel(x,y)
     1418  else if AResampleFilter = rfBox then
     1419  begin
     1420    if fracX256 >= 128 then inc(x);
     1421    if fracY256 >= 128 then inc(y);
     1422    result := GetPixel(x,y);
     1423  end else
     1424  begin
     1425    LoadFromBitmapIfNeeded;
     1426    result := InternalGetPixel256(x,y,FineInterpolation256(fracX256,AResampleFilter),FineInterpolation256(fracY256,AResampleFilter),smoothBorder);
     1427  end;
     1428end;
     1429
    11081430{$hints off}
    11091431{ This function compute an interpolated pixel at floating point coordinates }
    1110 function TBGRADefaultBitmap.GetPixel(x, y: single; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel;
    1111 var
    1112   ix, iy: integer;
    1113   w1,w2,w3,w4,alphaW: cardinal;
    1114   rSum, gSum, bSum: cardinal; //rgbDiv = aSum
    1115   aSum: cardinal;
    1116   c:    TBGRAPixel;
    1117   scan: PBGRAPixel;
    1118   factX,factY: single;
    1119   iFactX,iFactY: integer;
    1120 begin
    1121   ix := floor(x);
    1122   iy := floor(y);
    1123   factX := x-ix; //distance from integer coordinate
    1124   factY := y-iy;
     1432function TBGRADefaultBitmap.GetPixel(x, y: single; AResampleFilter: TResampleFilter = rfLinear; smoothBorder: boolean = true): TBGRAPixel;
     1433var
     1434  ix, iy: Int32or64;
     1435  iFactX,iFactY: Int32or64;
     1436begin
     1437  ix := round(x*256);
     1438  if (ix<= -256) or (ix>=Width shl 8) then
     1439  begin
     1440    result := BGRAPixelTransparent;
     1441    exit;
     1442  end;
     1443  iy := round(y*256);
     1444  if (iy<= -256) or (iy>=Height shl 8) then
     1445  begin
     1446    result := BGRAPixelTransparent;
     1447    exit;
     1448  end;
     1449
     1450  iFactX := ix and 255; //distance from integer coordinate
     1451  iFactY := iy and 255;
     1452  if ix<0 then ix := -1 else ix := ix shr 8;
     1453  if iy<0 then iy := -1 else iy := iy shr 8;
    11251454
    11261455  //if the coordinate is integer, then call standard GetPixel function
    1127   if (factX = 0) and (factY = 0) then
    1128   begin
    1129     Result := GetPixel(ix, iy);
     1456  if (iFactX = 0) and (iFactY = 0) then
     1457  begin
     1458    Result := (GetScanlineFast(iy)+ix)^;
    11301459    exit;
    11311460  end;
     1461
    11321462  LoadFromBitmapIfNeeded;
    1133 
    1134   rSum   := 0;
    1135   gSum   := 0;
    1136   bSum   := 0;
    1137   aSum   := 0;
    1138 
    1139   //apply interpolation filter
    1140   factX := FineInterpolation( factX, AResampleFilter );
    1141   factY := FineInterpolation( factY, AResampleFilter );
    1142 
    1143   iFactX := round(factX*256); //integer values for fractionnal part
    1144   iFactY := round(factY*256);
    1145 
    1146   w4 := (iFactX*iFactY+127) shr 8;
    1147   w3 := iFactY-w4;
    1148   w1 := (256-iFactX)-w3;
    1149   w2 := iFactX-w4;
    1150 
    1151   { For each pixel around the coordinate, compute
    1152     the weight for it and multiply values by it before
    1153     adding to the sum }
    1154   if (iy >= 0) and (iy < Height) then
    1155   begin
    1156     scan := GetScanlineFast(iy);
    1157 
    1158     if (ix >= 0) and (ix < Width) then
    1159     begin
    1160       c      := (scan + ix)^;
    1161       alphaW := c.alpha * w1;
    1162       aSum   += alphaW;
    1163       rSum   += c.red * alphaW;
    1164       gSum   += c.green * alphaW;
    1165       bSum   += c.blue * alphaW;
    1166     end;
    1167 
    1168     Inc(ix);
    1169     if (ix >= 0) and (ix < Width) then
    1170     begin
    1171       c      := (scan + ix)^;
    1172       alphaW := c.alpha * w2;
    1173       aSum   += alphaW;
    1174       rSum   += c.red * alphaW;
    1175       gSum   += c.green * alphaW;
    1176       bSum   += c.blue * alphaW;
    1177     end;
    1178   end
    1179   else
    1180   begin
    1181     Inc(ix);
    1182   end;
    1183 
    1184   Inc(iy);
    1185   if (iy >= 0) and (iy < Height) then
    1186   begin
    1187     scan := GetScanlineFast(iy);
    1188 
    1189     if (ix >= 0) and (ix < Width) then
    1190     begin
    1191       c      := (scan + ix)^;
    1192       alphaW := c.alpha * w4;
    1193       aSum   += alphaW;
    1194       rSum   += c.red * alphaW;
    1195       gSum   += c.green * alphaW;
    1196       bSum   += c.blue * alphaW;
    1197     end;
    1198 
    1199     Dec(ix);
    1200     if (ix >= 0) and (ix < Width) then
    1201     begin
    1202       c      := (scan + ix)^;
    1203       alphaW := c.alpha * w3;
    1204       aSum   += alphaW;
    1205       rSum   += c.red * alphaW;
    1206       gSum   += c.green * alphaW;
    1207       bSum   += c.blue * alphaW;
    1208     end;
    1209   end;
    1210 
    1211   if aSum < 128 then //if there is no alpha
    1212     Result := BGRAPixelTransparent
    1213   else
    1214   begin
    1215     Result.red   := (rSum + aSum shr 1) div aSum;
    1216     Result.green := (gSum + aSum shr 1) div aSum;
    1217     Result.blue  := (bSum + aSum shr 1) div aSum;
    1218     Result.alpha := (aSum + 128) shr 8;
    1219   end;
     1463  result := InternalGetPixel256(ix,iy,FineInterpolation256(iFactX,AResampleFilter),FineInterpolation256(iFactY,AResampleFilter),smoothBorder);
    12201464end;
    12211465
     
    12231467function TBGRADefaultBitmap.GetPixelCycle(x, y: single; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel;
    12241468var
    1225   ix, iy: integer;
    1226   iFactX,iFactY: integer;
    1227 begin
     1469  ix, iy: Int32or64;
     1470  iFactX,iFactY: Int32or64;
     1471begin
     1472  if FData = nil then
     1473  begin
     1474    result := BGRAPixelTransparent;
     1475    exit;
     1476  end;
    12281477  LoadFromBitmapIfNeeded;
    1229   iFactX := round(x*256);
    1230   iFactY := round(y*256);
    1231   ix := (iFactX shr 8)+ScanOffset.X;
    1232   iy := (iFactY shr 8)+ScanOffset.Y;
    1233   iFactX := iFactX and 255;
    1234   iFactY := iFactY and 255;
    1235 
     1478  ix := round(x*256);
     1479  iy := round(y*256);
     1480  iFactX := ix and 255;
     1481  iFactY := iy and 255;
     1482  ix := PositiveMod(ix, FWidth shl 8) shr 8;
     1483  iy := PositiveMod(iy, FHeight shl 8) shr 8;
    12361484  if (iFactX = 0) and (iFactY = 0) then
    12371485  begin
    1238     result := (ScanLine[PositiveMod(iy, FHeight)]+PositiveMod(ix, FWidth))^;
     1486    result := (GetScanlineFast(iy)+ix)^;
    12391487    exit;
    12401488  end;
    1241 
    12421489  if ScanInterpolationFilter <> rfLinear then
    12431490  begin
     
    12451492    iFactY := FineInterpolation256( iFactY, ScanInterpolationFilter );
    12461493  end;
    1247 
    1248   result := GetPixelCycleInline(ix,iy, iFactX,iFactY);
     1494  result := InternalGetPixelCycle256(ix,iy, iFactX,iFactY);
    12491495end;
    12501496
     
    12531499  ): TBGRAPixel;
    12541500var
    1255   alpha: byte;
    1256 begin
    1257   alpha := 255;
    1258   if not repeatX then
    1259   begin
    1260     if (x < -0.5) or (x > Width-0.5) then
    1261     begin
    1262       result := BGRAPixelTransparent;
    1263       exit;
     1501  ix, iy: Int32or64;
     1502  iFactX,iFactY: Int32or64;
     1503begin
     1504  if FData = nil then
     1505  begin
     1506    result := BGRAPixelTransparent;
     1507    exit;
     1508  end;
     1509  ix := round(x*256);
     1510  iy := round(y*256);
     1511  iFactX := ix and 255;
     1512  iFactY := iy and 255;
     1513  if ix < 0 then ix := -((iFactX-ix) shr 8)
     1514  else ix := ix shr 8;
     1515  if iy < 0 then iy := -((iFactY-iy) shr 8)
     1516  else iy := iy shr 8;
     1517  result := GetPixelCycle256(ix,iy,iFactX,iFactY,AResampleFilter,repeatX,repeatY);
     1518end;
     1519
     1520function TBGRADefaultBitmap.GetPixelCycle256(x, y, fracX256,
     1521  fracY256: int32or64; AResampleFilter: TResampleFilter): TBGRAPixel;
     1522begin
     1523  if (fracX256 = 0) and (fracY256 = 0) then
     1524    result := GetPixelCycle(x,y)
     1525  else if AResampleFilter = rfBox then
     1526  begin
     1527    if fracX256 >= 128 then inc(x);
     1528    if fracY256 >= 128 then inc(y);
     1529    result := GetPixelCycle(x,y);
     1530  end else
     1531  begin
     1532    LoadFromBitmapIfNeeded;
     1533    result := InternalGetPixelCycle256(PositiveMod(x,FWidth),PositiveMod(y,FHeight),FineInterpolation256(fracX256,AResampleFilter),FineInterpolation256(fracY256,AResampleFilter));
     1534  end;
     1535end;
     1536
     1537function TBGRADefaultBitmap.GetPixelCycle256(x, y, fracX256,
     1538  fracY256: int32or64; AResampleFilter: TResampleFilter; repeatX: boolean;
     1539  repeatY: boolean): TBGRAPixel;
     1540begin
     1541  if not repeatX and not repeatY then
     1542    result := GetPixel256(x,y,fracX256,fracY256,AResampleFilter)
     1543  else if repeatX and repeatY then
     1544    result := GetPixelCycle256(x,y,fracX256,fracY256,AResampleFilter)
     1545  else
     1546  begin
     1547    if not repeatX then
     1548    begin
     1549      if x < 0 then
     1550      begin
     1551        if x < -1 then
     1552        begin
     1553          result := BGRAPixelTransparent;
     1554          exit;
     1555        end;
     1556        result := GetPixelCycle256(0,y,0,fracY256,AResampleFilter);
     1557        result.alpha:= result.alpha*fracX256 shr 8;
     1558        if result.alpha = 0 then
     1559          result := BGRAPixelTransparent;
     1560        exit;
     1561      end;
     1562      if x >= FWidth-1 then
     1563      begin
     1564        if x >= FWidth then
     1565        begin
     1566          result := BGRAPixelTransparent;
     1567          exit;
     1568        end;
     1569        result := GetPixelCycle256(FWidth-1,y,0,fracY256,AResampleFilter);
     1570        result.alpha:= result.alpha*(256-fracX256) shr 8;
     1571        if result.alpha = 0 then
     1572          result := BGRAPixelTransparent;
     1573        exit;
     1574      end;
     1575    end else
     1576    begin
     1577      if y < 0 then
     1578      begin
     1579        if y < -1 then
     1580        begin
     1581          result := BGRAPixelTransparent;
     1582          exit;
     1583        end;
     1584        result := GetPixelCycle256(x,0,fracX256,0,AResampleFilter);
     1585        result.alpha:= result.alpha*fracY256 shr 8;
     1586        if result.alpha = 0 then
     1587          result := BGRAPixelTransparent;
     1588        exit;
     1589      end;
     1590      if y >= FHeight-1 then
     1591      begin
     1592        if y >= FHeight then
     1593        begin
     1594          result := BGRAPixelTransparent;
     1595          exit;
     1596        end;
     1597        result := GetPixelCycle256(x,FHeight-1,fracX256,0,AResampleFilter);
     1598        result.alpha:= result.alpha*(256-fracY256) shr 8;
     1599        if result.alpha = 0 then
     1600          result := BGRAPixelTransparent;
     1601        exit;
     1602      end;
    12641603    end;
    1265     if x < 0 then
    1266     begin
    1267       alpha := round((0.5+x)*510);
    1268       x := 0;
    1269     end
    1270     else
    1271     if x > Width-1 then
    1272     begin
    1273       alpha := round((Width-0.5-x)*510);
    1274       x := Width-1;
    1275     end;
    1276   end;
    1277   if not repeatY then
    1278   begin
    1279     if (y < -0.5) or (y > Height-0.5) then
    1280     begin
    1281       result := BGRAPixelTransparent;
    1282       exit;
    1283     end;
    1284     if y < 0 then
    1285     begin
    1286       alpha := round((0.5+y)*2*alpha);
    1287       y := 0;
    1288     end
    1289     else
    1290     if y > Height-1 then
    1291     begin
    1292       alpha := round((Height-0.5-y)*2*alpha);
    1293       y := Height-1;
    1294     end;
    1295   end;
    1296   result := GetPixelCycle(x,y,AResampleFilter);
    1297   if alpha<>255 then
    1298     result.alpha := ApplyOpacity(result.alpha,alpha);
     1604    result := GetPixelCycle256(x,y,fracX256,fracY256,AResampleFilter);
     1605  end;
    12991606end;
    13001607
     
    15401847    (ARawImage.Description.BlueShift = 8) and
    15411848    (ARawImage.Description.ByteOrder = riboMSBFirst)) then
    1542     mustSwapRedBlue:= true
     1849  begin
     1850    mustSwapRedBlue:= true;
     1851    mustReverse32 := false;
     1852  end
    15431853  else
    15441854  begin
     
    16551965end;
    16561966
     1967procedure TBGRADefaultBitmap.CrossFade(ARect: TRect; Source1, Source2: IBGRAScanner; AFadePosition: byte; mode: TDrawMode = dmDrawWithTransparency);
     1968var constScanner: TBGRAConstantScanner;
     1969begin
     1970  if AFadePosition = 0 then
     1971    FillRect(ARect, Source1, mode) else
     1972  if AFadePosition = 255 then
     1973    FillRect(ARect, Source2, mode) else
     1974  begin
     1975    constScanner := TBGRAConstantScanner.Create(BGRA(AFadePosition,AFadePosition,AFadePosition,255));
     1976    CrossFade(ARect, Source1,Source2, constScanner, mode);
     1977    constScanner.Free;
     1978  end;
     1979end;
     1980
     1981procedure TBGRADefaultBitmap.CrossFade(ARect: TRect; Source1, Source2: IBGRAScanner; AFadeMask: IBGRAScanner; mode: TDrawMode = dmDrawWithTransparency);
     1982var xb,yb: NativeInt;
     1983  pdest: PBGRAPixel;
     1984  c: TBGRAPixel;
     1985  fadePos: byte;
     1986begin
     1987  if not IntersectRect(ARect,ARect,ClipRect) then exit;
     1988  for yb := ARect.top to ARect.Bottom-1 do
     1989  begin
     1990    pdest := GetScanlineFast(yb)+ARect.Left;
     1991    Source1.ScanMoveTo(ARect.left, yb);
     1992    Source2.ScanMoveTo(ARect.left, yb);
     1993    AFadeMask.ScanMoveTo(ARect.left, yb);
     1994    for xb := ARect.left to ARect.Right-1 do
     1995    begin
     1996      fadePos := AFadeMask.ScanNextPixel.green;
     1997      c := MergeBGRAWithGammaCorrection(Source1.ScanNextPixel,not fadePos,Source2.ScanNextPixel,fadePos);
     1998      case mode of
     1999      dmSet: pdest^ := c;
     2000      dmDrawWithTransparency: DrawPixelInlineWithAlphaCheck(pdest, c);
     2001      dmLinearBlend: FastBlendPixelInline(pdest,c);
     2002      dmSetExceptTransparent: if c.alpha = 255 then pdest^ := c;
     2003      end;
     2004      inc(pdest);
     2005    end;
     2006  end;
     2007  InvalidateBitmap;
     2008end;
     2009
    16572010procedure TBGRADefaultBitmap.DiscardBitmapChange; inline;
    16582011begin
     
    16772030  FillMode := fmWinding;
    16782031
    1679   FFont     := TFont.Create;
    16802032  FontName  := 'Arial';
    16812033  FontStyle := [];
    16822034  FontAntialias := False;
    16832035  FFontHeight := 20;
    1684   FFontHeightSign := GetFontHeightSign(FFont);
    16852036
    16862037  PenStyle := psSolid;
     
    17562107{---------------------------- Line primitives ---------------------------------}
    17572108
    1758 function TBGRADefaultBitmap.CheckHorizLineBounds(var x,y,x2: integer): boolean; inline;
    1759 var
    1760   temp: integer;
     2109function TBGRADefaultBitmap.CheckHorizLineBounds(var x,y,x2: int32or64): boolean; inline;
     2110var
     2111  temp: int32or64;
    17612112begin
    17622113  if (x2 < x) then
     
    17782129end;
    17792130
    1780 procedure TBGRADefaultBitmap.SetHorizLine(x, y, x2: integer; c: TBGRAPixel);
     2131procedure TBGRADefaultBitmap.SetHorizLine(x, y, x2: int32or64; c: TBGRAPixel);
    17812132begin
    17822133  if not CheckHorizLineBounds(x,y,x2) then exit;
     
    17852136end;
    17862137
    1787 procedure TBGRADefaultBitmap.XorHorizLine(x, y, x2: integer; c: TBGRAPixel);
     2138procedure TBGRADefaultBitmap.XorHorizLine(x, y, x2: int32or64; c: TBGRAPixel);
    17882139begin
    17892140  if not CheckHorizLineBounds(x,y,x2) then exit;
     
    17922143end;
    17932144
    1794 procedure TBGRADefaultBitmap.DrawHorizLine(x, y, x2: integer; c: TBGRAPixel);
     2145procedure TBGRADefaultBitmap.DrawHorizLine(x, y, x2: int32or64; c: TBGRAPixel);
    17952146begin
    17962147  if not CheckHorizLineBounds(x,y,x2) then exit;
     
    17992150end;
    18002151
    1801 procedure TBGRADefaultBitmap.DrawHorizLine(x, y, x2: integer; ec: TExpandedPixel
     2152procedure TBGRADefaultBitmap.DrawHorizLine(x, y, x2: int32or64; ec: TExpandedPixel
    18022153  );
    18032154begin
     
    18072158end;
    18082159
    1809 procedure TBGRADefaultBitmap.DrawHorizLine(x, y, x2: integer;
    1810   texture: IBGRAScanner);
     2160procedure TBGRADefaultBitmap.HorizLine(x, y, x2: int32or64;
     2161  texture: IBGRAScanner; ADrawMode : TDrawMode);
    18112162begin
    18122163  if not CheckHorizLineBounds(x,y,x2) then exit;
    18132164  texture.ScanMoveTo(x,y);
    1814   ScannerPutPixels(texture,scanline[y] + x, x2 - x + 1,dmDrawWithTransparency);
     2165  ScannerPutPixels(texture,scanline[y] + x, x2 - x + 1,ADrawMode);
    18152166  InvalidateBitmap;
    18162167end;
    18172168
    1818 procedure TBGRADefaultBitmap.FastBlendHorizLine(x, y, x2: integer; c: TBGRAPixel);
     2169procedure TBGRADefaultBitmap.FastBlendHorizLine(x, y, x2: int32or64; c: TBGRAPixel);
    18192170begin
    18202171  if not CheckHorizLineBounds(x,y,x2) then exit;
     
    18232174end;
    18242175
    1825 procedure TBGRADefaultBitmap.AlphaHorizLine(x, y, x2: integer; alpha: byte);
     2176procedure TBGRADefaultBitmap.AlphaHorizLine(x, y, x2: int32or64; alpha: byte);
    18262177begin
    18272178  if alpha = 0 then
     
    18352186end;
    18362187
    1837 function TBGRADefaultBitmap.CheckVertLineBounds(var x,y,y2: integer; out delta: integer): boolean; inline;
    1838 var
    1839   temp: integer;
     2188function TBGRADefaultBitmap.CheckVertLineBounds(var x,y,y2: int32or64; out delta: int32or64): boolean; inline;
     2189var
     2190  temp: int32or64;
    18402191begin
    18412192  if FLineOrder = riloBottomToTop then
     
    18652216end;
    18662217
    1867 procedure TBGRADefaultBitmap.SetVertLine(x, y, y2: integer; c: TBGRAPixel);
    1868 var
    1869   n, delta: integer;
     2218procedure TBGRADefaultBitmap.SetVertLine(x, y, y2: int32or64; c: TBGRAPixel);
     2219var
     2220  n, delta: int32or64;
    18702221  p: PBGRAPixel;
    18712222begin
     
    18802231end;
    18812232
    1882 procedure TBGRADefaultBitmap.XorVertLine(x, y, y2: integer; c: TBGRAPixel);
    1883 var
    1884   n, delta: integer;
     2233procedure TBGRADefaultBitmap.XorVertLine(x, y, y2: int32or64; c: TBGRAPixel);
     2234var
     2235  n, delta: int32or64;
    18852236  p: PBGRAPixel;
    18862237begin
     
    18952246end;
    18962247
    1897 procedure TBGRADefaultBitmap.DrawVertLine(x, y, y2: integer; c: TBGRAPixel);
    1898 var
    1899   n, delta: integer;
     2248procedure TBGRADefaultBitmap.DrawVertLine(x, y, y2: int32or64; c: TBGRAPixel);
     2249var
     2250  n, delta: int32or64;
    19002251  p: PBGRAPixel;
    19012252begin
     
    19152266end;
    19162267
    1917 procedure TBGRADefaultBitmap.AlphaVertLine(x, y, y2: integer; alpha: byte);
    1918 var
    1919   n, delta: integer;
     2268procedure TBGRADefaultBitmap.AlphaVertLine(x, y, y2: int32or64; alpha: byte);
     2269var
     2270  n, delta: int32or64;
    19202271  p: PBGRAPixel;
    19212272begin
     
    19352286end;
    19362287
    1937 procedure TBGRADefaultBitmap.FastBlendVertLine(x, y, y2: integer; c: TBGRAPixel);
    1938 var
    1939   n, delta: integer;
     2288procedure TBGRADefaultBitmap.FastBlendVertLine(x, y, y2: int32or64; c: TBGRAPixel);
     2289var
     2290  n, delta: int32or64;
    19402291  p: PBGRAPixel;
    19412292begin
     
    19502301end;
    19512302
    1952 procedure TBGRADefaultBitmap.DrawHorizLineDiff(x, y, x2: integer;
     2303procedure TBGRADefaultBitmap.DrawHorizLineDiff(x, y, x2: int32or64;
    19532304  c, compare: TBGRAPixel; maxDiff: byte);
    19542305begin
     
    19582309end;
    19592310
     2311procedure TBGRADefaultBitmap.SetArrowStart(AStyle: TBGRAArrowStyle;
     2312  ATipStyle: TPenJoinStyle; ARelativePenWidth: single; ATriangleBackOffset: single);
     2313begin
     2314  GetArrow.SetStart(AStyle,ATipStyle,ARelativePenWidth,ATriangleBackOffset);
     2315end;
     2316
     2317procedure TBGRADefaultBitmap.SetArrowEnd(AStyle: TBGRAArrowStyle;
     2318  ATipStyle: TPenJoinStyle; ARelativePenWidth: single; ATriangleBackOffset: single);
     2319begin
     2320  GetArrow.SetEnd(AStyle,ATipStyle,ARelativePenWidth,ATriangleBackOffset);
     2321end;
     2322
     2323procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; c: TBGRAPixel; w: single);
     2324var tempCanvas: TBGRACanvas2D;
     2325begin
     2326  tempCanvas:= TBGRACanvas2D.Create(self);
     2327  tempCanvas.strokeStyle(c);
     2328  tempCanvas.lineWidth := w;
     2329  tempCanvas.lineStyle(CustomPenStyle);
     2330  tempCanvas.lineCapLCL := LineCap;
     2331  tempCanvas.lineJoinLCL := JoinStyle;
     2332  tempCanvas.path(APath);
     2333  tempCanvas.stroke;
     2334  tempCanvas.Free;
     2335end;
     2336
     2337procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; texture: IBGRAScanner; w: single);
     2338var tempCanvas: TBGRACanvas2D;
     2339begin
     2340  tempCanvas:= TBGRACanvas2D.Create(self);
     2341  tempCanvas.strokeStyle(texture);
     2342  tempCanvas.lineWidth := w;
     2343  tempCanvas.lineStyle(CustomPenStyle);
     2344  tempCanvas.lineCapLCL := LineCap;
     2345  tempCanvas.lineJoinLCL := JoinStyle;
     2346  tempCanvas.path(APath);
     2347  tempCanvas.stroke;
     2348  tempCanvas.Free;
     2349end;
     2350
    19602351{---------------------------- Lines ---------------------------------}
    19612352{ Call appropriate functions }
    19622353
    19632354procedure TBGRADefaultBitmap.DrawLine(x1, y1, x2, y2: integer;
    1964   c: TBGRAPixel; DrawLastPixel: boolean);
    1965 begin
    1966   BGRADrawLineAliased(self,x1,y1,x2,y2,c,DrawLastPixel);
     2355  c: TBGRAPixel; DrawLastPixel: boolean; ADrawMode: TDrawMode);
     2356begin
     2357  BGRADrawLineAliased(self,x1,y1,x2,y2,c,DrawLastPixel,ADrawMode);
    19672358end;
    19682359
     
    19702361  c: TBGRAPixel; DrawLastPixel: boolean);
    19712362begin
    1972   BGRADrawLineAntialias(self,x1,y1,x2,y2,c,DrawLastPixel);
     2363  BGRADrawLineAntialias(self,x1,y1,x2,y2,c,DrawLastPixel,LinearAntialiasing);
    19732364end;
    19742365
     
    19782369begin
    19792370  DashPos := 0;
    1980   BGRADrawLineAntialias(self,x1,y1,x2,y2,c1,c2,dashLen,DrawLastPixel,DashPos);
     2371  BGRADrawLineAntialias(self,x1,y1,x2,y2,c1,c2,dashLen,DrawLastPixel,DashPos,LinearAntialiasing);
    19812372end;
    19822373
     
    19842375  c2: TBGRAPixel; dashLen: integer; DrawLastPixel: boolean; var DashPos: integer);
    19852376begin
    1986   BGRADrawLineAntialias(self,x1,y1,x2,y2,c1,c2,dashLen,DrawLastPixel,DashPos);
     2377  BGRADrawLineAntialias(self,x1,y1,x2,y2,c1,c2,dashLen,DrawLastPixel,DashPos,LinearAntialiasing);
    19872378end;
    19882379
     
    19902381  c: TBGRAPixel; w: single);
    19912382begin
    1992   BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,c,LineCap,JoinStyle,FCustomPenStyle,[],nil,JoinMiterLimit);
     2383  if Assigned(FArrow) then
     2384    BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,c,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,nil,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX)
     2385  else
     2386    BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,c,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,nil,JoinMiterLimit);
    19932387end;
    19942388
     
    19962390  texture: IBGRAScanner; w: single);
    19972391begin
    1998   BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,BGRAPixelTransparent,LineCap,JoinStyle,FCustomPenStyle,[],texture,JoinMiterLimit);
     2392  if Assigned(FArrow) then
     2393    BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,BGRAPixelTransparent,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,texture,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX)
     2394  else
     2395    BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,BGRAPixelTransparent,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,texture,JoinMiterLimit);
    19992396end;
    20002397
    20012398procedure TBGRADefaultBitmap.DrawLineAntialias(x1, y1, x2, y2: single;
    2002   c: TBGRAPixel; w: single; closed: boolean);
     2399  c: TBGRAPixel; w: single; Closed: boolean);
    20032400var
    20042401  options: TBGRAPolyLineOptions;
    20052402begin
    20062403  if not closed then options := [plRoundCapOpen] else options := [];
    2007   BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,c,pecRound,pjsRound,FCustomPenStyle,options,nil,JoinMiterLimit);
     2404  options += GetPolyLineOption;
     2405  if Assigned(FArrow) then
     2406    BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,c,pecRound,pjsRound,FCustomPenStyle,options,nil,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX)
     2407  else
     2408    BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,c,pecRound,pjsRound,FCustomPenStyle,options,nil,JoinMiterLimit)
    20082409end;
    20092410
     
    20232424    c := BGRAPixelTransparent;
    20242425  end;
    2025   BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,c,pecRound,pjsRound,FCustomPenStyle,options,texture,JoinMiterLimit);
     2426  options += GetPolyLineOption;
     2427  if Assigned(FArrow) then
     2428    BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,c,pecRound,pjsRound,FCustomPenStyle,options,texture,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX)
     2429  else
     2430    BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,c,pecRound,pjsRound,FCustomPenStyle,options,texture,JoinMiterLimit);
    20262431end;
    20272432
     
    20292434  c: TBGRAPixel; w: single);
    20302435begin
    2031   BGRAPolyLine(self,points,w,c,LineCap,JoinStyle,FCustomPenStyle,[],nil,JoinMiterLimit);
     2436  if Assigned(FArrow) then
     2437    BGRAPen.BGRAPolyLine(self,points,w,c,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,nil,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX)
     2438  else
     2439    BGRAPen.BGRAPolyLine(self,points,w,c,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,nil,JoinMiterLimit)
    20322440end;
    20332441
     
    20352443  const points: array of TPointF; texture: IBGRAScanner; w: single);
    20362444begin
    2037   BGRAPolyLine(self,points,w,BGRAPixelTransparent,LineCap,JoinStyle,FCustomPenStyle,[],texture,JoinMiterLimit);
     2445  if Assigned(FArrow) then
     2446    BGRAPen.BGRAPolyLine(self,points,w,BGRAPixelTransparent,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,texture,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX)
     2447  else
     2448    BGRAPen.BGRAPolyLine(self,points,w,BGRAPixelTransparent,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,texture,JoinMiterLimit);
    20382449end;
    20392450
     
    20442455begin
    20452456  if not closed then options := [plRoundCapOpen] else options := [];
    2046   BGRAPolyLine(self,points,w,c,pecRound,JoinStyle,FCustomPenStyle,options,nil,JoinMiterLimit);
     2457  options += GetPolyLineOption;
     2458  if Assigned(FArrow) then
     2459    BGRAPen.BGRAPolyLine(self,points,w,c,pecRound,JoinStyle,FCustomPenStyle,options,nil,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX)
     2460  else
     2461    BGRAPen.BGRAPolyLine(self,points,w,c,pecRound,JoinStyle,FCustomPenStyle,options,nil,JoinMiterLimit);
     2462end;
     2463
     2464procedure TBGRADefaultBitmap.DrawPolyLineAntialias(
     2465  const points: array of TPointF; c: TBGRAPixel; w: single;
     2466  fillcolor: TBGRAPixel);
     2467var multi: TBGRAMultishapeFiller;
     2468begin
     2469  multi := TBGRAMultishapeFiller.Create;
     2470  multi.PolygonOrder := poLastOnTop;
     2471  multi.AddPolygon(points,fillcolor);
     2472  multi.AddPolygon(ComputeWidePolyline(points,w),c);
     2473  if LinearAntialiasing then
     2474    multi.Draw(self,dmLinearBlend)
     2475  else
     2476    multi.Draw(self,dmDrawWithTransparency);
     2477  multi.Free;
    20472478end;
    20482479
     
    20502481  c: TBGRAPixel; w: single);
    20512482begin
    2052    BGRAPolyLine(self,points,w,c,LineCap,JoinStyle,FCustomPenStyle,[plCycle],nil,JoinMiterLimit);
     2483  BGRAPolyLine(self,points,w,c,LineCap,JoinStyle,FCustomPenStyle,[plCycle],nil,JoinMiterLimit);
    20532484end;
    20542485
     
    20572488begin
    20582489  BGRAPolyLine(self,points,w,BGRAPixelTransparent,LineCap,JoinStyle,FCustomPenStyle,[plCycle],texture,JoinMiterLimit);
     2490end;
     2491
     2492procedure TBGRADefaultBitmap.DrawPolygonAntialias(
     2493  const points: array of TPointF; c: TBGRAPixel; w: single;
     2494  fillcolor: TBGRAPixel);
     2495var multi: TBGRAMultishapeFiller;
     2496begin
     2497  multi := TBGRAMultishapeFiller.Create;
     2498  multi.PolygonOrder := poLastOnTop;
     2499  multi.AddPolygon(points,fillcolor);
     2500  multi.AddPolygon(ComputeWidePolygon(points,w),c);
     2501  if LinearAntialiasing then
     2502    multi.Draw(self,dmLinearBlend)
     2503  else
     2504    multi.Draw(self,dmDrawWithTransparency);
     2505  multi.Free;
    20592506end;
    20602507
     
    20852532  DrawPolyLineAntialias(points, BGRA(0,0,0,alpha),w);
    20862533  FEraseMode := False;
     2534end;
     2535
     2536procedure TBGRADefaultBitmap.FillPath(APath: IBGRAPath; c: TBGRAPixel);
     2537var tempCanvas: TBGRACanvas2D;
     2538begin
     2539  tempCanvas:= TBGRACanvas2D.Create(self);
     2540  tempCanvas.fillStyle(c);
     2541  tempCanvas.path(APath);
     2542  tempCanvas.fill;
     2543  tempCanvas.Free;
     2544end;
     2545
     2546procedure TBGRADefaultBitmap.FillPath(APath: IBGRAPath; texture: IBGRAScanner);
     2547var tempCanvas: TBGRACanvas2D;
     2548begin
     2549  tempCanvas:= TBGRACanvas2D.Create(self);
     2550  tempCanvas.fillStyle(texture);
     2551  tempCanvas.path(APath);
     2552  tempCanvas.fill;
     2553  tempCanvas.Free;
    20872554end;
    20882555
     
    22152682end;
    22162683
     2684procedure TBGRADefaultBitmap.FillQuadPerspectiveMapping(pt1, pt2, pt3,
     2685  pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF;
     2686  ACleanBorders: TRect);
     2687var
     2688  persp: TBGRAPerspectiveScannerTransform;
     2689  clean: TBGRAExtendedBorderScanner;
     2690begin
     2691  clean := TBGRAExtendedBorderScanner.Create(texture,ACleanBorders);
     2692  persp := TBGRAPerspectiveScannerTransform.Create(clean,[tex1,tex2,tex3,tex4],[pt1,pt2,pt3,pt4]);
     2693  FillPoly([pt1,pt2,pt3,pt4],persp,dmDrawWithTransparency);
     2694  persp.Free;
     2695  clean.Free;
     2696end;
     2697
    22172698procedure TBGRADefaultBitmap.FillQuadPerspectiveMappingAntialias(pt1, pt2, pt3,
    22182699  pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF);
     
    22232704  FillPolyAntialias([pt1,pt2,pt3,pt4],persp);
    22242705  persp.Free;
     2706end;
     2707
     2708procedure TBGRADefaultBitmap.FillQuadPerspectiveMappingAntialias(pt1, pt2, pt3,
     2709  pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF;
     2710  ACleanBorders: TRect);
     2711var
     2712  persp: TBGRAPerspectiveScannerTransform;
     2713  clean: TBGRAExtendedBorderScanner;
     2714begin
     2715  clean := TBGRAExtendedBorderScanner.Create(texture,ACleanBorders);
     2716  persp := TBGRAPerspectiveScannerTransform.Create(clean,[tex1,tex2,tex3,tex4],[pt1,pt2,pt3,pt4]);
     2717  FillPolyAntialias([pt1,pt2,pt3,pt4],persp);
     2718  persp.Free;
     2719  clean.Free;
    22252720end;
    22262721
     
    22842779procedure TBGRADefaultBitmap.FillPolyAntialias(const points: array of TPointF; c: TBGRAPixel);
    22852780begin
    2286   BGRAPolygon.FillPolyAntialias(self, points, c, FEraseMode, FillMode = fmWinding);
     2781  BGRAPolygon.FillPolyAntialias(self, points, c, FEraseMode, FillMode = fmWinding, LinearAntialiasing);
    22872782end;
    22882783
     
    22902785  texture: IBGRAScanner);
    22912786begin
    2292   BGRAPolygon.FillPolyAntialiasWithTexture(self, points, texture, FillMode = fmWinding);
     2787  BGRAPolygon.FillPolyAntialiasWithTexture(self, points, texture, FillMode = fmWinding, LinearAntialiasing);
    22932788end;
    22942789
     
    23062801end;
    23072802
     2803procedure TBGRADefaultBitmap.FillShape(shape: TBGRACustomFillInfo; c: TBGRAPixel;
     2804  drawmode: TDrawMode);
     2805begin
     2806  BGRAPolygon.FillShapeAliased(self, shape, c, FEraseMode, nil, FillMode = fmWinding, drawmode);
     2807end;
     2808
     2809procedure TBGRADefaultBitmap.FillShape(shape: TBGRACustomFillInfo;
     2810  texture: IBGRAScanner; drawmode: TDrawMode);
     2811begin
     2812  BGRAPolygon.FillShapeAliased(self, shape, BGRAPixelTransparent, false, texture, FillMode = fmWinding, drawmode);
     2813end;
     2814
     2815procedure TBGRADefaultBitmap.FillShapeAntialias(shape: TBGRACustomFillInfo;
     2816  c: TBGRAPixel);
     2817begin
     2818  BGRAPolygon.FillShapeAntialias(self, shape, c, FEraseMode, nil, FillMode = fmWinding, LinearAntialiasing);
     2819end;
     2820
     2821procedure TBGRADefaultBitmap.FillShapeAntialias(shape: TBGRACustomFillInfo;
     2822  texture: IBGRAScanner);
     2823begin
     2824  BGRAPolygon.FillShapeAntialiasWithTexture(self, shape, texture, FillMode = fmWinding, LinearAntialiasing);
     2825end;
     2826
     2827procedure TBGRADefaultBitmap.EraseShape(shape: TBGRACustomFillInfo; alpha: byte);
     2828begin
     2829  BGRAPolygon.FillShapeAliased(self, shape, BGRA(0, 0, 0, alpha), True, nil, FillMode = fmWinding, dmDrawWithTransparency);
     2830end;
     2831
     2832procedure TBGRADefaultBitmap.EraseShapeAntialias(shape: TBGRACustomFillInfo;
     2833  alpha: byte);
     2834begin
     2835  FEraseMode := True;
     2836  FillShapeAntialias(shape, BGRA(0, 0, 0, alpha));
     2837  FEraseMode := False;
     2838end;
     2839
    23082840procedure TBGRADefaultBitmap.EllipseAntialias(x, y, rx, ry: single;
    23092841  c: TBGRAPixel; w: single);
     
    23112843  if IsClearPenStyle(FCustomPenStyle) or (c.alpha = 0) then exit;
    23122844  if IsSolidPenStyle(FCustomPenStyle) then
    2313     BGRAPolygon.BorderEllipseAntialias(self, x, y, rx, ry, w, c, FEraseMode)
     2845    BGRAPolygon.BorderEllipseAntialias(self, x, y, rx, ry, w, c, FEraseMode, LinearAntialiasing)
    23142846  else
    23152847    DrawPolygonAntialias(ComputeEllipseContour(x,y,rx,ry),c,w);
     
    23212853  if IsClearPenStyle(FCustomPenStyle) then exit;
    23222854  if IsSolidPenStyle(FCustomPenStyle) then
    2323     BGRAPolygon.BorderEllipseAntialiasWithTexture(self, x, y, rx, ry, w, texture)
     2855    BGRAPolygon.BorderEllipseAntialiasWithTexture(self, x, y, rx, ry, w, texture, LinearAntialiasing)
    23242856  else
    23252857    DrawPolygonAntialias(ComputeEllipseContour(x,y,rx,ry),texture,w);
     
    23622894procedure TBGRADefaultBitmap.FillEllipseAntialias(x, y, rx, ry: single; c: TBGRAPixel);
    23632895begin
    2364   BGRAPolygon.FillEllipseAntialias(self, x, y, rx, ry, c, FEraseMode);
     2896  BGRAPolygon.FillEllipseAntialias(self, x, y, rx, ry, c, FEraseMode, LinearAntialiasing);
    23652897end;
    23662898
     
    23682900  texture: IBGRAScanner);
    23692901begin
    2370   BGRAPolygon.FillEllipseAntialiasWithTexture(self, x, y, rx, ry, texture);
     2902  BGRAPolygon.FillEllipseAntialiasWithTexture(self, x, y, rx, ry, texture, LinearAntialiasing);
    23712903end;
    23722904
     
    24863018  if IsClearPenStyle(FCustomPenStyle) or (c.alpha = 0) then exit;
    24873019  if IsSolidPenStyle(FCustomPenStyle) then
    2488     BGRAPolygon.BorderRoundRectangleAntialias(self,x,y,x2,y2,rx,ry,w,options,c,False)
     3020    BGRAPolygon.BorderRoundRectangleAntialias(self,x,y,x2,y2,rx,ry,w,options,c,False, LinearAntialiasing)
    24893021  else
    24903022    DrawPolygonAntialias(BGRAPath.ComputeRoundRect(x,y,x2,y2,rx,ry,options),c,w);
     
    25443076  if IsClearPenStyle(FCustomPenStyle) then exit;
    25453077  if IsSolidPenStyle(FCustomPenStyle) then
    2546     BGRAPolygon.BorderRoundRectangleAntialiasWithTexture(self,x,y,x2,y2,rx,ry,w,options,texture)
     3078    BGRAPolygon.BorderRoundRectangleAntialiasWithTexture(self,x,y,x2,y2,rx,ry,w,options,texture, LinearAntialiasing)
    25473079  else
    25483080    DrawPolygonAntialias(BGRAPath.ComputeRoundRect(x,y,x2,y2,rx,ry,options),texture,w);
     
    26863218  end else
    26873219  begin
    2688     if (mode <> dmSet) and (c.alpha = 0) then exit;
     3220    if (mode <> dmSet) and (mode <> dmXor) and (c.alpha = 0) then exit;
    26893221
    26903222    p := Scanline[y] + x;
     
    27143246        end;
    27153247      dmXor:
     3248        if DWord(c) = 0 then exit
     3249        else
    27163250        for yb := y2 - y downto 0 do
    27173251        begin
     
    28253359  c: TBGRAPixel; options: TRoundRectangleOptions);
    28263360begin
    2827   BGRAPolygon.FillRoundRectangleAntialias(self,x,y,x2,y2,rx,ry,options,c,False);
     3361  BGRAPolygon.FillRoundRectangleAntialias(self,x,y,x2,y2,rx,ry,options,c,False, LinearAntialiasing);
    28283362end;
    28293363
     
    28313365  ry: single; texture: IBGRAScanner; options: TRoundRectangleOptions);
    28323366begin
    2833   BGRAPolygon.FillRoundRectangleAntialiasWithTexture(self,x,y,x2,y2,rx,ry,options,texture);
     3367  BGRAPolygon.FillRoundRectangleAntialiasWithTexture(self,x,y,x2,y2,rx,ry,options,texture, LinearAntialiasing);
    28343368end;
    28353369
     
    28373371  ry: single; alpha: byte; options: TRoundRectangleOptions);
    28383372begin
    2839   BGRAPolygon.FillRoundRectangleAntialias(self,x,y,x2,y2,rx,ry,options,BGRA(0,0,0,alpha),True);
     3373  BGRAPolygon.FillRoundRectangleAntialias(self,x,y,x2,y2,rx,ry,options,BGRA(0,0,0,alpha),True, LinearAntialiasing);
    28403374end;
    28413375
    28423376procedure TBGRADefaultBitmap.RoundRect(X1, Y1, X2, Y2: integer;
    2843   DX, DY: integer; BorderColor, FillColor: TBGRAPixel);
    2844 begin
    2845   BGRARoundRectAliased(self,X1,Y1,X2,Y2,DX,DY,BorderColor,FillColor);
     3377  DX, DY: integer; BorderColor, FillColor: TBGRAPixel; ADrawMode: TDrawMode = dmDrawWithTransparency);
     3378begin
     3379  BGRARoundRectAliased(self,X1,Y1,X2,Y2,DX,DY,BorderColor,FillColor,nil,ADrawMode);
     3380end;
     3381
     3382procedure TBGRADefaultBitmap.RoundRect(X1, Y1, X2, Y2: integer; DX,
     3383  DY: integer; BorderColor: TBGRAPixel; ADrawMode: TDrawMode);
     3384begin
     3385  BGRARoundRectAliased(self,X1,Y1,X2,Y2,DX,DY,BorderColor,BGRAPixelTransparent,nil,ADrawMode,true);
    28463386end;
    28473387
    28483388{------------------------- Text functions ---------------------------------------}
    28493389
    2850 procedure TBGRADefaultBitmap.TextOutAngle(x, y: single; orientation: integer;
    2851   s: string; c: TBGRAPixel; align: TAlignment);
    2852 begin
    2853   UpdateFont;
    2854   BGRAText.BGRATextOutAngle(self,FFont,FontQuality,x,y,orientation,s,c,nil,align);
    2855 end;
    2856 
    2857 procedure TBGRADefaultBitmap.TextOutAngle(x, y: single; orientation: integer;
    2858   s: string; texture: IBGRAScanner; align: TAlignment);
    2859 begin
    2860   UpdateFont;
    2861   BGRAText.BGRATextOutAngle(self,FFont,FontQuality,x,y,orientation,s,BGRAPixelTransparent,texture,align);
    2862 end;
    2863 
    2864 procedure TBGRADefaultBitmap.TextOut(x, y: single; s: string;
     3390procedure TBGRADefaultBitmap.TextOutAngle(x, y: single; orientationTenthDegCCW: integer;
     3391  sUTF8: string; c: TBGRAPixel; align: TAlignment);
     3392begin
     3393  FontRenderer.TextOutAngle(self,x,y,orientationTenthDegCCW,CleanTextOutString(sUTF8),c,align);
     3394end;
     3395
     3396procedure TBGRADefaultBitmap.TextOutAngle(x, y: single; orientationTenthDegCCW: integer;
     3397  sUTF8: string; texture: IBGRAScanner; align: TAlignment);
     3398begin
     3399  FontRenderer.TextOutAngle(self,x,y,orientationTenthDegCCW,CleanTextOutString(sUTF8),texture,align);
     3400end;
     3401
     3402procedure TBGRADefaultBitmap.TextOut(x, y: single; sUTF8: string;
    28653403  texture: IBGRAScanner; align: TAlignment);
    28663404begin
    2867   UpdateFont;
    2868 
    2869   if (FontQuality in[fqFineAntialiasing,fqFineClearTypeBGR,fqFineClearTypeRGB]) and (FFont.Orientation mod 3600 = 0) then
    2870     BGRATextFX.BGRATextOutImproveReadability(self,FFont,x,y,s,BGRAPixelTransparent,texture,align,
    2871      FontQuality in[fqFineClearTypeRGB,fqFineClearTypeBGR], FontQuality = fqFineClearTypeRGB) else
    2872 
    2873     BGRAText.BGRATextOut(self,FFont,FontQuality,x,y,s,BGRAPixelTransparent,texture,align);
    2874 end;
    2875 
    2876 procedure TBGRADefaultBitmap.TextOut(x, y: single; s: string;
     3405  FontRenderer.TextOut(self,x,y,CleanTextOutString(sUTF8),texture,align);
     3406end;
     3407
     3408procedure TBGRADefaultBitmap.TextOut(x, y: single; sUTF8: string;
    28773409  c: TBGRAPixel; align: TAlignment);
    28783410begin
    2879   UpdateFont;
    2880 
    2881   if (FontQuality in[fqFineAntialiasing,fqFineClearTypeBGR,fqFineClearTypeRGB]) and (FFont.Orientation mod 3600 = 0) then
    2882     BGRATextFX.BGRATextOutImproveReadability(self,FFont,x,y,s,c,nil,align,
    2883     FontQuality in[fqFineClearTypeRGB,fqFineClearTypeBGR], FontQuality = fqFineClearTypeRGB) else
    2884 
    2885     BGRAText.BGRATextOut(self,FFont,FontQuality,x,y,s,c,nil,align);
     3411  FontRenderer.TextOut(self,x,y,CleanTextOutString(sUTF8),c,align);
    28863412end;
    28873413
    28883414procedure TBGRADefaultBitmap.TextRect(ARect: TRect; x, y: integer;
    2889   s: string; style: TTextStyle; c: TBGRAPixel);
    2890 begin
    2891   UpdateFont;
    2892   BGRAText.BGRATextRect(self,FFont,FontQuality,ARect,x,y,s,style,c,nil);
    2893 end;
    2894 
    2895 procedure TBGRADefaultBitmap.TextRect(ARect: TRect; x, y: integer; s: string;
     3415  sUTF8: string; style: TTextStyle; c: TBGRAPixel);
     3416begin
     3417  FontRenderer.TextRect(self,ARect,x,y,sUTF8,style,c);
     3418end;
     3419
     3420procedure TBGRADefaultBitmap.TextRect(ARect: TRect; x, y: integer; sUTF8: string;
    28963421  style: TTextStyle; texture: IBGRAScanner);
    28973422begin
    2898   UpdateFont;
    2899   BGRAText.BGRATextRect(self,FFont,FontQuality,ARect,x,y,s,style,BGRAPixelTransparent,texture);
    2900 end;
    2901 
    2902 function TBGRADefaultBitmap.TextSize(s: string): TSize;
    2903 begin
    2904   UpdateFont;
    2905   result := BGRAText.BGRATextSize(FFont,FontQuality,s,FontAntialiasingLevel);
    2906   if (result.cy >= 24) and FontAntialias then
    2907     result := BGRAText.BGRATextSize(FFont,FontQuality,s,4);
     3423  FontRenderer.TextRect(self,ARect,x,y,sUTF8,style,texture);
     3424end;
     3425
     3426{ Returns the total size of the string provided using the current font.
     3427  Orientation is not taken into account, so that the width is along the text.  }
     3428function TBGRADefaultBitmap.TextSize(sUTF8: string): TSize;
     3429begin
     3430  result := FontRenderer.TextSize(sUTF8);
    29083431end;
    29093432
     
    29473470  w: single): ArrayOfTPointF;
    29483471begin
    2949   Result:= BGRAPen.ComputeWidePolylinePoints(points,w,BGRAWhite,LineCap,JoinStyle,FCustomPenStyle,[],JoinMiterLimit);
     3472  if Assigned(FArrow) then
     3473    Result:= BGRAPen.ComputeWidePolylinePoints(points,w,BGRAWhite,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX)
     3474  else
     3475    Result:= BGRAPen.ComputeWidePolylinePoints(points,w,BGRAWhite,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,JoinMiterLimit)
    29503476end;
    29513477
     
    29563482begin
    29573483  if not closed then options := [plRoundCapOpen] else options := [];
    2958   Result:= BGRAPen.ComputeWidePolylinePoints(points,w,BGRAWhite,pecRound,pjsRound,FCustomPenStyle,options,JoinMiterLimit);
     3484  options += GetPolyLineOption;
     3485  if Assigned(FArrow) then
     3486    Result:= BGRAPen.ComputeWidePolylinePoints(points,w,BGRAWhite,pecRound,pjsRound,FCustomPenStyle,options,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX)
     3487  else
     3488    Result:= BGRAPen.ComputeWidePolylinePoints(points,w,BGRAWhite,pecRound,pjsRound,FCustomPenStyle,options,JoinMiterLimit);
    29593489end;
    29603490
     
    29623492  w: single): ArrayOfTPointF;
    29633493begin
    2964   Result:= BGRAPen.ComputeWidePolylinePoints(points,w,BGRAWhite,LineCap,JoinStyle,FCustomPenStyle,[plCycle],JoinMiterLimit);
     3494  Result:= BGRAPen.ComputeWidePolylinePoints(points,w,BGRAWhite,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption+[plCycle],JoinMiterLimit);
    29653495end;
    29663496
     
    29843514  endRad: single; quality: single): ArrayOfTPointF;
    29853515begin
    2986   result := BGRAPath.ComputeArc65536(x,y,rx,ry,round(startRad*32768/Pi),round(endRad*32768/Pi),quality);
     3516  result := BGRAPath.ComputeArcRad(x,y,rx,ry,startRad,endRad,quality);
    29873517end;
    29883518
     
    30573587
    30583588procedure TBGRADefaultBitmap.FillMask(x, y: integer; AMask: TBGRACustomBitmap;
    3059   color: TBGRAPixel);
     3589  color: TBGRAPixel; ADrawMode: TDrawMode);
    30603590var
    30613591  scan: TBGRACustomScanner;
     
    30633593  if (AMask = nil) or (color.alpha = 0) then exit;
    30643594  scan := TBGRASolidColorMaskScanner.Create(AMask,Point(-X,-Y),color);
    3065   self.FillRect(X,Y,X+AMask.Width,Y+AMask.Height,scan,dmDrawWithTransparency);
     3595  self.FillRect(X,Y,X+AMask.Width,Y+AMask.Height,scan,ADrawMode);
    30663596  scan.Free;
    30673597end;
    30683598
    30693599procedure TBGRADefaultBitmap.FillMask(x, y: integer; AMask: TBGRACustomBitmap;
    3070   texture: IBGRAScanner);
     3600  texture: IBGRAScanner; ADrawMode: TDrawMode);
    30713601var
    30723602  scan: TBGRACustomScanner;
     
    30743604  if AMask = nil then exit;
    30753605  scan := TBGRATextureMaskScanner.Create(AMask,Point(-X,-Y),texture);
    3076   self.FillRect(X,Y,X+AMask.Width,Y+AMask.Height,scan,dmDrawWithTransparency);
     3606  self.FillRect(X,Y,X+AMask.Width,Y+AMask.Height,scan,ADrawMode);
    30773607  scan.Free;
    30783608end;
     
    33513881function TBGRADefaultBitmap.ScanAt(X, Y: Single): TBGRAPixel;
    33523882var
    3353   ix, iy: integer;
    3354   iFactX,iFactY: integer;
     3883  ix, iy: Int32or64;
     3884  iFactX,iFactY: Int32or64;
    33553885begin
    33563886  if FData = nil then
     
    33593889    exit;
    33603890  end;
    3361   iFactX := round(x*256);
    3362   iFactY := round(y*256);
    3363   ix := (iFactX shr 8)+ScanOffset.X;
    3364   iy := (iFactY shr 8)+ScanOffset.Y;
    3365   iFactX := iFactX and 255;
    3366   iFactY := iFactY and 255;
    3367 
     3891  LoadFromBitmapIfNeeded;
     3892  ix := round(x*256);
     3893  iy := round(y*256);
     3894  iFactX := ix and 255;
     3895  iFactY := iy and 255;
     3896  ix := PositiveMod(ix+(ScanOffset.X shl 8), FWidth shl 8) shr 8;
     3897  iy := PositiveMod(iy+(ScanOffset.Y shl 8), FHeight shl 8) shr 8;
    33683898  if (iFactX = 0) and (iFactY = 0) then
    33693899  begin
    3370     result := (GetScanlineFast(PositiveMod(iy, FHeight))+PositiveMod(ix, FWidth))^;
     3900    result := (GetScanlineFast(iy)+ix)^;
    33713901    exit;
    33723902  end;
    3373 
    33743903  if ScanInterpolationFilter <> rfLinear then
    33753904  begin
     
    33773906    iFactY := FineInterpolation256( iFactY, ScanInterpolationFilter );
    33783907  end;
    3379 
    3380   result := GetPixelCycleInline(ix,iy, iFactX,iFactY);
     3908  result := InternalGetPixelCycle256(ix,iy, iFactX,iFactY);
    33813909end;
    33823910
     
    34974025end;
    34984026
    3499 function TBGRADefaultBitmap.CheckPutImageBounds(x,y,tx,ty: integer; out minxb,minyb,maxxb,maxyb,ignoreleft: integer): boolean inline;
    3500 var x2,y2: integer;
    3501 begin
    3502   if (x >= FClipRect.Right) or (y >= FClipRect.Bottom) or (x <= FClipRect.Left-tx) or
    3503     (y <= FClipRect.Top-ty) or (Height = 0) or (ty = 0) or (tx = 0) then
    3504   begin
    3505     result := false;
    3506     exit;
    3507   end;
    3508 
    3509   x2 := x + tx - 1;
    3510   y2 := y + ty - 1;
    3511 
    3512   if y < FClipRect.Top then
    3513     minyb := FClipRect.Top
    3514   else
    3515     minyb := y;
    3516   if y2 >= FClipRect.Bottom then
    3517     maxyb := FClipRect.Bottom - 1
    3518   else
    3519     maxyb := y2;
    3520 
    3521   if x < FClipRect.Left then
    3522   begin
    3523     ignoreleft := FClipRect.Left-x;
    3524     minxb      := FClipRect.Left;
    3525   end
    3526   else
    3527   begin
    3528     ignoreleft := 0;
    3529     minxb      := x;
    3530   end;
    3531   if x2 >= FClipRect.Right then
    3532     maxxb := FClipRect.Right - 1
    3533   else
    3534     maxxb := x2;
    3535 
    3536   result := true;
    3537 end;
    3538 
    35394027function TBGRADefaultBitmap.CheckAntialiasRectBounds(var x, y, x2, y2: single;
    35404028  w: single): boolean;
     
    35844072  sourcewidth := Source.Width;
    35854073
    3586   if not CheckPutImageBounds(x,y,sourcewidth,source.height,minxb,minyb,maxxb,maxyb,ignoreleft) then exit;
     4074  if not CheckPutImageBounds(x,y,sourcewidth,source.height,minxb,minyb,maxxb,maxyb,ignoreleft,FClipRect) then exit;
    35874075
    35884076  copycount := maxxb - minxb + 1;
     
    37494237  sourcewidth := Source.Width;
    37504238
    3751   if not CheckPutImageBounds(x,y,sourcewidth,source.height,minxb,minyb,maxxb,maxyb,ignoreleft) then exit;
     4239  if not CheckPutImageBounds(x,y,sourcewidth,source.height,minxb,minyb,maxxb,maxyb,ignoreleft,FClipRect) then exit;
    37524240
    37534241  copycount := maxxb - minxb + 1;
     
    37834271  sourcewidth := Source.Width;
    37844272
    3785   if not CheckPutImageBounds(x,y,sourcewidth,source.height,minxb,minyb,maxxb,maxyb,ignoreleft) then exit;
     4273  if not CheckPutImageBounds(x,y,sourcewidth,source.height,minxb,minyb,maxxb,maxyb,ignoreleft,FClipRect) then exit;
    37864274
    37874275  copycount := maxxb - minxb + 1;
     
    38084296end;
    38094297
    3810 { Draw an image wih an angle. Use an affine transformation to do this. }
    3811 procedure TBGRADefaultBitmap.PutImageAngle(x, y: single;
    3812   Source: TBGRACustomBitmap; angle: single; imageCenterX: single;
    3813   imageCenterY: single; AOpacity: Byte; ARestoreOffsetAfterRotation: boolean);
    3814 var
    3815   cosa,sina: single;
    3816 
    3817   { Compute rotated coordinates }
    3818   function Coord(relX,relY: single): TPointF;
    3819   begin
    3820     relX -= imageCenterX;
    3821     relY -= imageCenterY;
    3822     result.x := relX*cosa-relY*sina+x;
    3823     result.y := relY*cosa+relX*sina+y;
    3824     if ARestoreOffsetAfterRotation then
    3825     begin
    3826       result.x += imageCenterX;
    3827       result.y += imageCenterY;
    3828     end;
    3829   end;
    3830 
    3831 begin
    3832   cosa := cos(-angle*Pi/180);
    3833   sina := -sin(-angle*Pi/180);
    3834   PutImageAffine(Coord(0,0),Coord(source.Width,0),Coord(0,source.Height),source,AOpacity);
    3835 end;
    3836 
    38374298{ Draw an image with an affine transformation (rotation, scale, translate).
    3838   Parameters are the bitmap origin, the end of the horizontal axis and the end of the vertical axis. }
    3839 procedure TBGRADefaultBitmap.PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AOpacity: Byte);
     4299  Parameters are the bitmap origin, the end of the horizontal axis and the end of the vertical axis.
     4300  The output bounds correspond to the pixels that will be affected in the destination. }
     4301procedure TBGRADefaultBitmap.PutImageAffine(Origin, HAxis, VAxis: TPointF;
     4302  Source: TBGRACustomBitmap; AOutputBounds: TRect; AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte);
    38404303var affine: TBGRAAffineBitmapTransform;
    3841     minx,miny,maxx,maxy: integer;
    3842     pt4: TPointF;
    3843 
    3844   //include specified point in the bounds
    3845   procedure Include(pt: TPointF);
    3846   begin
    3847     if floor(pt.X) < minx then minx := floor(pt.X);
    3848     if floor(pt.Y) < miny then miny := floor(pt.Y);
    3849     if ceil(pt.X) > maxx then maxx := ceil(pt.X);
    3850     if ceil(pt.Y) > maxy then maxy := ceil(pt.Y);
    3851   end;
    3852 
    3853 begin
     4304    SourceBounds: TRect;
     4305begin
     4306  if (Source = nil) or (AOpacity = 0) then exit;
     4307  IntersectRect(AOutputBounds,AOutputBounds,ClipRect);
     4308  if IsRectEmpty(AOutputBounds) then exit;
     4309
    38544310  if (abs(Origin.x-round(Origin.x))<1e-6) and (abs(Origin.y-round(Origin.Y))<1e-6) and
    38554311     (abs(HAxis.x-(Origin.x+Source.Width))<1e-6) and (abs(HAxis.y-origin.y)<1e-6) and
    38564312     (abs(VAxis.x-Origin.x)<1e-6) and (abs(VAxis.y-(Origin.y+Source.Height))<1e-6) then
    38574313  begin
    3858     PutImage(round(origin.x),round(origin.y),Source,dmDrawWithTransparency,AOpacity);
     4314    SourceBounds := AOutputBounds;
     4315    OffsetRect(SourceBounds, -round(origin.x),-round(origin.y));
     4316    IntersectRect(SourceBounds,SourceBounds,rect(0,0,Source.Width,Source.Height));
     4317    PutImagePart(round(origin.x)+SourceBounds.Left,round(origin.y)+SourceBounds.Top,Source,SourceBounds,AMode,AOpacity);
    38594318    exit;
    38604319  end;
    38614320
    38624321  { Create affine transformation }
    3863   affine := TBGRAAffineBitmapTransform.Create(Source);
     4322  affine := TBGRAAffineBitmapTransform.Create(Source, false, AResampleFilter);
    38644323  affine.GlobalOpacity := AOpacity;
    38654324  affine.Fit(Origin,HAxis,VAxis);
    3866 
    3867   { Compute bounds }
    3868   pt4.x := VAxis.x+HAxis.x-Origin.x;
    3869   pt4.y := VAxis.y+HAxis.y-Origin.y;
    3870   minx := floor(Origin.X);
    3871   miny := floor(Origin.Y);
    3872   maxx := ceil(Origin.X);
    3873   maxy := ceil(Origin.Y);
    3874   Include(HAxis);
    3875   Include(VAxis);
    3876   Include(pt4);
    3877 
    3878   { Use the affine transformation as a scanner }
    3879   FillRect(minx,miny,maxx+1,maxy+1,affine,dmDrawWithTransparency);
     4325  FillRect(AOutputBounds,affine,AMode);
    38804326  affine.Free;
     4327end;
     4328
     4329procedure TBGRADefaultBitmap.StretchPutImage(ARect: TRect;
     4330  Source: TBGRACustomBitmap; mode: TDrawMode; AOpacity: byte);
     4331begin
     4332  If (Source = nil) or (AOpacity = 0) then exit;
     4333  if (ARect.Right-ARect.Left = Source.Width) and (ARect.Bottom-ARect.Top = Source.Height) then
     4334     PutImage(ARect.Left,ARect.Top,Source,mode,AOpacity)
     4335  else
     4336     BGRAResample.StretchPutImage(Source, ARect.Right-ARect.Left, ARect.Bottom-ARect.Top, self, ARect.left,ARect.Top, mode, AOpacity);
    38814337end;
    38824338
     
    39914447end;
    39924448
     4449function TBGRADefaultBitmap.FilterTwirl(ABounds: TRect; ACenter: TPoint;
     4450  ARadius: Single; ATurn: Single; AExponent: Single): TBGRACustomBitmap;
     4451begin
     4452  result := BGRAFilters.FilterTwirl(self, ABounds, ACenter, ARadius, ATurn, AExponent);
     4453end;
     4454
    39934455function TBGRADefaultBitmap.FilterCylinder: TBGRACustomBitmap;
    39944456begin
     
    40014463end;
    40024464
    4003 function TBGRADefaultBitmap.FilterSharpen: TBGRACustomBitmap;
    4004 begin
    4005   Result := BGRAFilters.FilterSharpen(self);
     4465function TBGRADefaultBitmap.FilterSharpen(Amount: single = 1): TBGRACustomBitmap;
     4466begin
     4467  Result := BGRAFilters.FilterSharpen(self,round(Amount*256));
     4468end;
     4469
     4470function TBGRADefaultBitmap.FilterSharpen(ABounds: TRect; Amount: single
     4471  ): TBGRACustomBitmap;
     4472begin
     4473  Result := BGRAFilters.FilterSharpen(self,ABounds,round(Amount*256));
    40064474end;
    40074475
     
    40174485end;
    40184486
     4487function TBGRADefaultBitmap.FilterBlurRadial(ABounds: TRect; radius: integer;
     4488  blurType: TRadialBlurType): TBGRACustomBitmap;
     4489var task: TFilterTask;
     4490begin
     4491  task := BGRAFilters.CreateRadialBlurTask(self, ABounds, radius, blurType);
     4492  try
     4493    result := task.Execute;
     4494  finally
     4495    task.Free;
     4496  end;
     4497end;
     4498
    40194499function TBGRADefaultBitmap.FilterPixelate(pixelSize: integer;
    40204500  useResample: boolean; filter: TResampleFilter): TBGRACustomBitmap;
     
    40294509end;
    40304510
     4511function TBGRADefaultBitmap.FilterBlurMotion(ABounds: TRect; distance: integer;
     4512  angle: single; oriented: boolean): TBGRACustomBitmap;
     4513var task: TFilterTask;
     4514begin
     4515  task := BGRAFilters.CreateMotionBlurTask(self,ABounds,distance,angle,oriented);
     4516  try
     4517    Result := task.Execute;
     4518  finally
     4519    task.Free;
     4520  end;
     4521end;
     4522
    40314523function TBGRADefaultBitmap.FilterCustomBlur(mask: TBGRACustomBitmap):
    40324524TBGRACustomBitmap;
     
    40354527end;
    40364528
     4529function TBGRADefaultBitmap.FilterCustomBlur(ABounds: TRect;
     4530  mask: TBGRACustomBitmap): TBGRACustomBitmap;
     4531var task: TFilterTask;
     4532begin
     4533  task := BGRAFilters.CreateBlurTask(self, ABounds, mask);
     4534  try
     4535    result := task.Execute;
     4536  finally
     4537    task.Free;
     4538  end;
     4539end;
     4540
    40374541function TBGRADefaultBitmap.FilterEmboss(angle: single): TBGRACustomBitmap;
    40384542begin
    40394543  Result := BGRAFilters.FilterEmboss(self, angle);
     4544end;
     4545
     4546function TBGRADefaultBitmap.FilterEmboss(angle: single; ABounds: TRect): TBGRACustomBitmap;
     4547begin
     4548  Result := BGRAFilters.FilterEmboss(self, angle, ABounds);
    40404549end;
    40414550
     
    40634572end;
    40644573
     4574function TBGRADefaultBitmap.FilterGrayscale(ABounds: TRect): TBGRACustomBitmap;
     4575begin
     4576  Result := BGRAFilters.FilterGrayscale(self, ABounds);
     4577end;
     4578
    40654579function TBGRADefaultBitmap.FilterNormalize(eachChannel: boolean = True):
    40664580TBGRACustomBitmap;
     
    40694583end;
    40704584
     4585function TBGRADefaultBitmap.FilterNormalize(ABounds: TRect; eachChannel: boolean): TBGRACustomBitmap;
     4586begin
     4587  Result := BGRAFilters.FilterNormalize(self, ABounds, eachChannel);
     4588end;
     4589
    40714590function TBGRADefaultBitmap.FilterRotate(origin: TPointF;
    4072   angle: single): TBGRACustomBitmap;
    4073 begin
    4074   Result := BGRAFilters.FilterRotate(self, origin, angle);
     4591  angle: single; correctBlur: boolean): TBGRACustomBitmap;
     4592begin
     4593  Result := BGRAFilters.FilterRotate(self, origin, angle, correctBlur);
    40754594end;
    40764595
     
    41404659end;
    41414660
    4142 {$hints off}
    4143 function TBGRADefaultBitmap.LoadAsBmp32(Str: TStream): boolean;
    4144 var OldPos: int64;
    4145     fileHeader: TBitmapFileHeader;
    4146     infoHeader: TBitmapInfoHeader;
    4147     dataSize: integer;
    4148 begin
    4149   OldPos := Str.Position;
    4150   result := false;
    4151   try
    4152     if Str.Read(fileHeader,sizeof(fileHeader)) <> sizeof(fileHeader) then
    4153       raise exception.Create('Inuable to read file header');
    4154     if fileHeader.bfType = $4D42 then
    4155     begin
    4156       if Str.Read(infoHeader,sizeof(infoHeader)) <> sizeof(infoHeader) then
    4157         raise exception.Create('Inuable to read info header');
    4158 
    4159       if (infoHeader.biPlanes = 1) and (infoHeader.biBitCount = 32) and (infoHeader.biCompression = 0) then
    4160       begin
    4161         SetSize(infoHeader.biWidth,infoHeader.biHeight);
    4162         Str.Position := OldPos+fileHeader.bfOffBits;
    4163         dataSize := NbPixels*sizeof(TBGRAPixel);
    4164         if Str.Read(Data^, dataSize) <> dataSize then
    4165         Begin
    4166           SetSize(0,0);
    4167           raise exception.Create('Unable to read data');
    4168         end;
    4169         result := true;
    4170       end;
    4171     end;
    4172 
    4173   except
    4174     on ex:exception do
    4175     begin
    4176 
    4177     end;
    4178   end;
    4179   Str.Position := OldPos;
    4180 
    4181 end;
    4182 {$hints on}
    4183 
    41844661procedure TBGRADefaultBitmap.SetCanvasOpacity(AValue: byte);
    41854662begin
     
    42254702
    42264703  It is an involution, i.e it does nothing when applied twice }
    4227 procedure TBGRADefaultBitmap.VerticalFlip;
    4228 var
    4229   yb:     integer;
     4704procedure TBGRADefaultBitmap.VerticalFlip(ARect: TRect);
     4705var
     4706  yb,h2:     integer;
    42304707  line:   PBGRAPixel;
    4231   linesize: integer;
     4708  linesize, delta: integer;
    42324709  PStart: PBGRAPixel;
    42334710  PEnd:   PBGRAPixel;
     
    42364713    exit;
    42374714
     4715  if (ARect.Right <= ARect.Left) or (ARect.Bottom <= ARect.Top) then exit;
     4716  if not IntersectRect(ARect, ARect, rect(0,0,Width,Height)) then exit;
    42384717  LoadFromBitmapIfNeeded;
    4239   linesize := Width * sizeof(TBGRAPixel);
     4718  linesize := (ARect.Right-ARect.Left) * sizeof(TBGRAPixel);
    42404719  line     := nil;
    42414720  getmem(line, linesize);
    4242   PStart := Data;
    4243   PEnd   := Data + (Height - 1) * Width;
    4244   for yb := 0 to (Height div 2) - 1 do
     4721  PStart := GetScanlineFast(ARect.Top)+ARect.Left;
     4722  PEnd   := GetScanlineFast(ARect.Bottom-1)+ARect.Left;
     4723  h2 := (ARect.Bottom-ARect.Top) div 2;
     4724  if LineOrder = riloTopToBottom then delta := +Width else delta := -Width;
     4725  for yb := h2-1 downto 0 do
    42454726  begin
    42464727    move(PStart^, line^, linesize);
    42474728    move(PEnd^, PStart^, linesize);
    42484729    move(line^, PEnd^, linesize);
    4249     Inc(PStart, Width);
    4250     Dec(PEnd, Width);
     4730    Inc(PStart, delta);
     4731    Dec(PEnd, delta);
    42514732  end;
    42524733  freemem(line);
     
    42574738
    42584739  It is an involution, i.e it does nothing when applied twice}
    4259 procedure TBGRADefaultBitmap.HorizontalFlip;
    4260 var
    4261   yb, xb: integer;
     4740procedure TBGRADefaultBitmap.HorizontalFlip(ARect: TRect);
     4741var
     4742  yb, xb, w: integer;
    42624743  PStart: PBGRAPixel;
    42634744  PEnd:   PBGRAPixel;
     
    42674748    exit;
    42684749
     4750  if (ARect.Right <= ARect.Left) or (ARect.Bottom <= ARect.Top) then exit;
     4751  if not IntersectRect(ARect, ARect, rect(0,0,Width,Height)) then exit;
     4752  w := ARect.Right-ARect.Left;
    42694753  LoadFromBitmapIfNeeded;
    4270   for yb := 0 to Height - 1 do
    4271   begin
    4272     PStart := Scanline[yb];
    4273     PEnd   := PStart + Width;
    4274     for xb := 0 to (Width div 2) - 1 do
     4754  for yb := ARect.Top to ARect.Bottom-1 do
     4755  begin
     4756    PStart := GetScanlineFast(yb)+ARect.Left;
     4757    PEnd   := PStart + w;
     4758    for xb := 0 to (w div 2) - 1 do
    42754759    begin
    42764760      Dec(PEnd);
     
    43394823  complentary colors (black becomes white etc.).
    43404824
    4341   It is an involution, i.e it does nothing when applied twice }
     4825  It is NOT EXACTLY an involution, when applied twice, some color information is lost }
    43424826procedure TBGRADefaultBitmap.Negative;
    43434827var
     
    43604844end;
    43614845
     4846procedure TBGRADefaultBitmap.NegativeRect(ABounds: TRect);
     4847var p: PBGRAPixel;
     4848  xb,yb,xcount: integer;
     4849begin
     4850  if not IntersectRect(ABounds,ABounds,ClipRect) then exit;
     4851  xcount := ABounds.Right-ABounds.Left;
     4852  for yb := ABounds.Top to ABounds.Bottom-1 do
     4853  begin
     4854    p := ScanLine[yb]+ABounds.Left;
     4855    for xb := xcount-1 downto 0 do
     4856    begin
     4857      if p^.alpha <> 0 then
     4858      begin
     4859        p^.red   := GammaCompressionTab[not GammaExpansionTab[p^.red]];
     4860        p^.green := GammaCompressionTab[not GammaExpansionTab[p^.green]];
     4861        p^.blue  := GammaCompressionTab[not GammaExpansionTab[p^.blue]];
     4862      end;
     4863      Inc(p);
     4864    end;
     4865  end;
     4866end;
     4867
    43624868{ Compute negative without gamma correction.
    43634869
     
    43814887  end;
    43824888  InvalidateBitmap;
     4889end;
     4890
     4891procedure TBGRADefaultBitmap.LinearNegativeRect(ABounds: TRect);
     4892var p: PBGRAPixel;
     4893  xb,yb,xcount: integer;
     4894begin
     4895  if not IntersectRect(ABounds,ABounds,ClipRect) then exit;
     4896  xcount := ABounds.Right-ABounds.Left;
     4897  for yb := ABounds.Top to ABounds.Bottom-1 do
     4898  begin
     4899    p := ScanLine[yb]+ABounds.Left;
     4900    for xb := xcount-1 downto 0 do
     4901    begin
     4902      if p^.alpha <> 0 then
     4903      begin
     4904        p^.red   := not p^.red;
     4905        p^.green := not p^.green;
     4906        p^.blue  := not p^.blue;
     4907      end;
     4908      Inc(p);
     4909    end;
     4910  end;
     4911end;
     4912
     4913procedure TBGRADefaultBitmap.InplaceGrayscale;
     4914begin
     4915  InplaceGrayscale(rect(0,0,Width,Height));
     4916end;
     4917
     4918procedure TBGRADefaultBitmap.InplaceGrayscale(ABounds: TRect);
     4919var
     4920  task: TFilterTask;
     4921begin
     4922  task := CreateGrayscaleTask(self, ABounds);
     4923  task.Destination := self;
     4924  task.Execute;
     4925  task.Free;
    43834926end;
    43844927
     
    44524995
    44534996  See : http://wiki.lazarus.freepascal.org/BGRABitmap_tutorial_5 }
    4454 procedure TBGRADefaultBitmap.ApplyMask(mask: TBGRACustomBitmap);
     4997procedure TBGRADefaultBitmap.ApplyMask(mask: TBGRACustomBitmap; ARect: TRect; AMaskRectTopLeft: TPoint);
    44554998var
    44564999  p, pmask: PBGRAPixel;
    44575000  yb, xb:   integer;
    4458 begin
    4459   if (Mask.Width <> Width) or (Mask.Height <> Height) then
    4460     exit;
     5001  MaskOffsetX,MaskOffsetY,w: integer;
     5002  opacity: NativeUint;
     5003begin
     5004  if (ARect.Right <= ARect.Left) or (ARect.Bottom <= ARect.Top) then exit;
     5005  IntersectRect(ARect, ARect, rect(0,0,Width,Height));
     5006  MaskOffsetX := AMaskRectTopLeft.x - ARect.Left;
     5007  MaskOffsetY := AMaskRectTopLeft.y - ARect.Top;
     5008  OffsetRect(ARect, MaskOffsetX, MaskOffsetY);
     5009  IntersectRect(ARect, ARect, rect(0,0,mask.Width,mask.Height));
     5010  OffsetRect(ARect, -MaskOffsetX, -MaskOffsetY);
    44615011
    44625012  LoadFromBitmapIfNeeded;
    4463   for yb := 0 to Height - 1 do
    4464   begin
    4465     p     := Scanline[yb];
    4466     pmask := Mask.Scanline[yb];
    4467     for xb := Width - 1 downto 0 do
    4468     begin
    4469       p^.alpha := ApplyOpacity(p^.alpha, pmask^.red);
     5013  w := ARect.Right-ARect.Left-1;
     5014  for yb := ARect.Top to ARect.Bottom - 1 do
     5015  begin
     5016    p     := Scanline[yb]+ARect.Left;
     5017    pmask := Mask.Scanline[yb+MaskOffsetY]+ARect.Left+MaskOffsetX;
     5018    for xb := w downto 0 do
     5019    begin
     5020      opacity := ApplyOpacity(p^.alpha, pmask^.red);
     5021      if opacity = 0 then p^ := BGRAPixelTransparent
     5022      else p^.alpha := opacity;
    44705023      Inc(p);
    44715024      Inc(pmask);
     
    45225075end;
    45235076
     5077procedure TBGRADefaultBitmap.DrawCheckers(ARect: TRect; AColorEven,
     5078  AColorOdd: TBGRAPixel);
     5079const tx = 8; ty = 8; //must be a power of 2
     5080      xMask = tx*2-1;
     5081var xcount,patY,w,n,patY1,patY2m1,patX,patX1: NativeInt;
     5082    pdest: PBGRAPixel;
     5083    delta: PtrInt;
     5084    actualRect: TRect;
     5085begin
     5086  actualRect := ARect;
     5087  IntersectRect(actualRect, ARect, self.ClipRect);
     5088  w := actualRect.Right-actualRect.Left;
     5089  if (w <= 0) or (actualRect.Bottom <= actualRect.Top) then exit;
     5090  delta := self.Width;
     5091  if self.LineOrder = riloBottomToTop then delta := -delta;
     5092  delta := (delta-w)*SizeOf(TBGRAPixel);
     5093  pdest := self.ScanLine[actualRect.Top]+actualRect.left;
     5094  patY1 := actualRect.Top - ARect.Top;
     5095  patY2m1 := actualRect.Bottom - ARect.Top-1;
     5096  patX1 := (actualRect.Left - ARect.Left) and xMask;
     5097  for patY := patY1 to patY2m1 do
     5098  begin
     5099    xcount := w;
     5100    if patY and ty = 0 then
     5101       patX := patX1
     5102    else
     5103       patX := (patX1+tx) and xMask;
     5104    while xcount > 0 do
     5105    begin
     5106      if patX and tx = 0 then
     5107      begin
     5108        n := 8-patX;
     5109        if n > xcount then n := xcount;
     5110        FillDWord(pdest^,n,DWord(AColorEven));
     5111        dec(xcount,n);
     5112        inc(pdest,n);
     5113        patX := tx;
     5114      end else
     5115      begin
     5116        n := 16-patX;
     5117        if n > xcount then n := xcount;
     5118        FillDWord(pdest^,n,DWord(AColorOdd));
     5119        dec(xcount,n);
     5120        inc(pdest,n);
     5121        patX := 0;
     5122      end;
     5123    end;
     5124    inc(pbyte(pdest),delta);
     5125  end;
     5126  self.InvalidateBitmap;
     5127end;
     5128
    45245129{ Get bounds of non zero values of specified channel }
    45255130function TBGRADefaultBitmap.GetImageBounds(Channel: TChannel = cAlpha; ANothingValue: Byte = 0): TRect;
     5131begin
     5132  result := GetImageBounds([Channel], ANothingValue);
     5133end;
     5134
     5135function TBGRADefaultBitmap.GetImageBounds(Channels: TChannels; ANothingValue: Byte = 0): TRect;
    45265136var
    45275137  minx, miny, maxx, maxy: integer;
    4528   xb, yb: integer;
    4529   p:      pbyte;
    4530   offset: integer;
     5138  xb, xb2, yb: integer;
     5139  p:      PDWord;
     5140  colorMask, colorZeros: DWord;
    45315141begin
    45325142  maxx := -1;
     
    45345144  minx := self.Width;
    45355145  miny := self.Height;
    4536   case Channel of
    4537     cBlue: offset  := 0;
    4538     cGreen: offset := 1;
    4539     cRed: offset   := 2;
    4540     else
    4541       offset := 3;
    4542   end;
     5146  colorMask := 0;
     5147  colorZeros := 0;
     5148  if cBlue in Channels then
     5149  begin
     5150    colorMask := colorMask or $ff;
     5151    colorZeros:= colorZeros or ANothingValue;
     5152  end;
     5153  if cGreen in Channels then
     5154  begin
     5155    colorMask := colorMask or $ff00;
     5156    colorZeros:= colorZeros or (ANothingValue shl 8);
     5157  end;
     5158  if cRed in Channels then
     5159  begin
     5160    colorMask := colorMask or $ff0000;
     5161    colorZeros:= colorZeros or (ANothingValue shl 16);
     5162  end;
     5163  if cAlpha in Channels then
     5164  begin
     5165    colorMask := colorMask or $ff000000;
     5166    colorZeros:= colorZeros or (ANothingValue shl 24);
     5167  end;
     5168  colorMask := NtoLE(colorMask);
     5169  colorZeros := NtoLE(colorZeros);
    45435170  for yb := 0 to self.Height - 1 do
    45445171  begin
    4545     p := PByte(self.ScanLine[yb]) + offset;
     5172    p := PDWord(self.ScanLine[yb]);
    45465173    for xb := 0 to self.Width - 1 do
    45475174    begin
    4548       if p^ <> ANothingValue then
     5175      if (p^ and colorMask) <> colorZeros then
    45495176      begin
    45505177        if xb < minx then
     
    45565183        if yb > maxy then
    45575184          maxy := yb;
     5185
     5186        inc(p, self.width-1-xb);
     5187        for xb2 := self.Width-1 downto xb+1 do
     5188        begin
     5189          if (p^ and colorMask) <> colorZeros then
     5190          begin
     5191            if xb2 > maxx then
     5192              maxx := xb2;
     5193            break;
     5194          end;
     5195          dec(p);
     5196        end;
     5197        break;
    45585198      end;
    4559       Inc(p, sizeof(TBGRAPixel));
     5199      Inc(p);
    45605200    end;
    45615201  end;
     
    45745214    Result.bottom := maxy + 1;
    45755215  end;
    4576 end;
    4577 
    4578 function TBGRADefaultBitmap.GetImageBounds(Channels: TChannels): TRect;
    4579 var c: TChannel;
    4580 begin
    4581   result := rect(0,0,0,0);
    4582   for c := low(TChannel) to high(TChannel) do
    4583     if c in Channels then
    4584       UnionRect(result,result,GetImageBounds(c));
    45855216end;
    45865217
Note: See TracChangeset for help on using the changeset viewer.