1// SPDX-License-Identifier: LGPL-3.0-linking-exception 2{$IFDEF INCLUDE_INTERFACE} 3{$UNDEF INCLUDE_INTERFACE} 4type 5{=== TBGRACustomBitmap ===} 6 7 { TBGRACustomBitmap } 8 {* This is the base class for ''TBGRABitmap''. It is the direct parent of 9 ''TBGRADefaultBitmap'' class, which is the parent of the diverse 10 implementations. A bitmap can be used as a scanner using the interface 11 ''IBGRAScanner'' } 12 TBGRACustomBitmap = class(specialize TGenericUniversalBitmap<TBGRAPixel,TBGRAPixelColorspace>,IBGRAScanner) 13 protected 14 FXorMask: TBGRACustomBitmap; 15 16 { accessors to properies } 17 procedure SetXorMask(AValue: TBGRACustomBitmap); 18 19 function GetAverageColor: TColor; virtual; abstract; 20 function GetAveragePixel: TBGRAPixel; virtual; abstract; 21 22 //FreePascal drawing routines 23 {$IFDEF BGRABITMAP_USE_FPCANVAS}function GetCanvasFP: TFPImageCanvas; virtual; abstract;{$ENDIF} 24 function GetCanvasDrawModeFP: TDrawMode; virtual; abstract; 25 procedure SetCanvasDrawModeFP(const AValue: TDrawMode); virtual; abstract; 26 27 //GUI bitmap object 28 function GetBitmap: TBitmap; virtual; abstract; 29 function GetCanvas: TCanvas; virtual; abstract; 30 function GetCanvasOpacity: byte; virtual; abstract; 31 procedure SetCanvasOpacity(AValue: byte); virtual; abstract; 32 function GetCanvasAlphaCorrection: boolean; virtual; abstract; 33 procedure SetCanvasAlphaCorrection(const AValue: boolean); virtual; abstract; 34 35 procedure Init; override; 36 function InternalNew: TBGRACustomBitmap; override; 37 38 procedure InternalArc(cx,cy,rx,ry: single; const StartPoint,EndPoint: TPointF; ABorderColor: TBGRAPixel; w: single; AFillColor: TBGRAPixel; AOptions: TArcOptions; ADrawChord: boolean = false; ATexture: IBGRAScanner = nil); overload; 39 procedure InternalArc(cx,cy,rx,ry: single; StartAngleRad,EndAngleRad: Single; ABorderColor: TBGRAPixel; w: single; AFillColor: TBGRAPixel; AOptions: TArcOptions; ADrawChord: boolean = false; ATexture: IBGRAScanner = nil); overload; virtual; abstract; 40 procedure InternalArcInRect(r: TRect; StartAngleRad,EndAngleRad: Single; ABorderColor : TBGRAPixel; w: single; AFillColor: TBGRAPixel; AOptions: TArcOptions; ADrawChord: boolean = false; ATexture: IBGRAScanner = nil); 41 procedure InternalFillArcInRect(r: TRect; StartAngleRad,EndAngleRad: Single; AFillColor: TBGRAPixel; AOptions: TArcOptions; ATexture: IBGRAScanner = nil); 42 43 public 44 {** Resample filter is used when resizing the bitmap. See [[BGRABitmap Miscellaneous types#Images and resampling|resampling types]] } 45 ResampleFilter : TResampleFilter; 46 47 {** Scan interpolation filter is used when the bitmap is used 48 as a scanner (interface ''IBGRAScanner'') } 49 ScanInterpolationFilter: TResampleFilter; 50 ScanMaskChannel: TChannel; 51 52 {** Cursor position for mouse pointer } 53 HotSpot: TPoint; 54 55 { ** Free reference to xor mask } 56 procedure DiscardXorMask; virtual; 57 { ** Allocate xor mask } 58 procedure NeedXorMask; virtual; 59 {** Xor mask to be applied when image is drawn } 60 property XorMask: TBGRACustomBitmap read FXorMask write SetXorMask; 61 62 {** Average color of the image } 63 property AverageColor: TColor Read GetAverageColor; 64 {** Average color (including alpha) of the image } 65 property AveragePixel: TBGRAPixel Read GetAveragePixel; 66 67 {** Canvas compatible with FreePascal } 68 {$IFDEF BGRABITMAP_USE_FPCANVAS}property CanvasFP: TFPImageCanvas read GetCanvasFP;{$ENDIF} 69 70 {** Draw mode to used when image is access using FreePascal functions 71 and ''Colors'' property } 72 property CanvasDrawModeFP: TDrawMode read GetCanvasDrawModeFP write SetCanvasDrawModeFP; 73 74 {** Bitmap in a format compatible with the current GUI. 75 Don't forget to call ''InvalidateBitmap'' before using it 76 if you changed something with direct pixel access (''Scanline'' 77 and ''Data'') } 78 property Bitmap: TBitmap Read GetBitmap; 79 {** Canvas provided by the GUI } 80 property Canvas: TCanvas Read GetCanvas; 81 {** Opacity to apply to changes made using GUI functions, provided 82 ''CanvasAlphaCorrection'' is set to ''True'' } 83 property CanvasOpacity: byte Read GetCanvasOpacity Write SetCanvasOpacity; 84 {** Specifies if the alpha values must be corrected after GUI access 85 to the bitmap } 86 property CanvasAlphaCorrection: boolean Read GetCanvasAlphaCorrection Write SetCanvasAlphaCorrection; 87 88 protected {----------- pen style accessors ----------------} 89 function GetPenJoinStyle: TPenJoinStyle; virtual; abstract; 90 procedure SetPenJoinStyle(const AValue: TPenJoinStyle); virtual; abstract; 91 function GetPenMiterLimit: single; virtual; abstract; 92 procedure SetPenMiterLimit(const AValue: single); virtual; abstract; 93 function GetPenStyle: TPenStyle; virtual; abstract; 94 procedure SetPenStyle(const AValue: TPenStyle); virtual; abstract; 95 function GetCustomPenStyle: TBGRAPenStyle; virtual; abstract; 96 procedure SetCustomPenStyle(const AValue: TBGRAPenStyle); virtual; abstract; 97 98 function GetArrowEndRepeat: integer; virtual; abstract; 99 function GetArrowStartRepeat: integer; virtual; abstract; 100 procedure SetArrowEndRepeat(AValue: integer); virtual; abstract; 101 procedure SetArrowStartRepeat(AValue: integer); virtual; abstract; 102 function GetArrowEndOffset: single; virtual; abstract; 103 function GetArrowStartOffset: single; virtual; abstract; 104 procedure SetArrowEndOffset(AValue: single); virtual; abstract; 105 procedure SetArrowStartOffset(AValue: single); virtual; abstract; 106 function GetArrowEndSize: TPointF; virtual; abstract; 107 function GetArrowStartSize: TPointF; virtual; abstract; 108 procedure SetArrowEndSize(AValue: TPointF); virtual; abstract; 109 procedure SetArrowStartSize(AValue: TPointF); virtual; abstract; 110 111 public {----------- pen style ----------------} 112 {** How to join segments. See [[BGRABitmap Types imported from Graphics|BGRAGraphics]] } 113 property JoinStyle: TPenJoinStyle read GetPenJoinStyle Write SetPenJoinStyle; 114 {** Limit for the extension of the segments when joining them 115 with ''pjsMiter'' join style, expressed in multiples of the width 116 of the pen } 117 property JoinMiterLimit: single read GetPenMiterLimit Write SetPenMiterLimit; 118 {** Pen style. See [[BGRABitmap Types imported from Graphics|BGRAGraphics]] } 119 property PenStyle: TPenStyle read GetPenStyle Write SetPenStyle; 120 {** Custom pen style. See [[BGRABitmap Geometry types|geometric types]] } 121 property CustomPenStyle: TBGRAPenStyle read GetCustomPenStyle write SetCustomPenStyle; 122 123 {** Size of arrows at the start of the line } 124 property ArrowStartSize: TPointF read GetArrowStartSize write SetArrowStartSize; 125 {** Size of arrows at the end of the line } 126 property ArrowEndSize: TPointF read GetArrowEndSize write SetArrowEndSize; 127 {** Offset of the arrow from the start of the line } 128 property ArrowStartOffset: single read GetArrowStartOffset write SetArrowStartOffset; 129 {** Offset of the arrow from the end of the line } 130 property ArrowEndOffset: single read GetArrowEndOffset write SetArrowEndOffset; 131 {** Number of times to repeat the starting arrow } 132 property ArrowStartRepeat: integer read GetArrowStartRepeat write SetArrowStartRepeat; 133 {** Number of times to repeat the ending arrow } 134 property ArrowEndRepeat: integer read GetArrowEndRepeat write SetArrowEndRepeat; 135 136 procedure ArrowStartAsNone; virtual; abstract; 137 procedure ArrowStartAsClassic(AFlipped: boolean = false; ACut: boolean = false; ARelativePenWidth: single = 1); virtual; abstract; 138 procedure ArrowStartAsTriangle(ABackOffset: single = 0; ARounded: boolean = false; AHollow: boolean = false; AHollowPenWidth: single = 0.5); virtual; abstract; 139 procedure ArrowStartAsTail; virtual; abstract; 140 141 procedure ArrowEndAsNone; virtual; abstract; 142 procedure ArrowEndAsClassic(AFlipped: boolean = false; ACut: boolean = false; ARelativePenWidth: single = 1); virtual; abstract; 143 procedure ArrowEndAsTriangle(ABackOffset: single = 0; ARounded: boolean = false; AHollow: boolean = false; AHollowPenWidth: single = 0.5); virtual; abstract; 144 procedure ArrowEndAsTail; virtual; abstract; 145 146 protected {-------------------font style accessors------------------------} 147 function GetFontAntialias: Boolean; 148 procedure SetFontAntialias(const AValue: Boolean); 149 function GetFontRenderer: TBGRACustomFontRenderer; virtual; abstract; 150 procedure SetFontRenderer(AValue: TBGRACustomFontRenderer); virtual; abstract; 151 function GetFontHeight: integer; virtual; abstract; 152 procedure SetFontHeight(AHeight: integer); virtual; abstract; 153 function GetFontFullHeight: integer; virtual; abstract; 154 procedure SetFontFullHeight(AHeight: integer); virtual; abstract; 155 function GetFontVerticalAnchorOffset: single; virtual; abstract; 156 function GetFontPixelMetric: TFontPixelMetric; virtual; abstract; 157 158 function GetFontRightToLeftFor(AText: string): boolean; 159 160 public {-------------------font style------------------------} 161 {** Specifies the font to use. Unless the font renderer accept otherwise, 162 the name is in human readable form, like 'Arial', 'Times New Roman', ... } 163 FontName: string; 164 {** Specifies the set of styles to be applied to the font. 165 These can be ''fsBold'', ''fsItalic'', ''fsStrikeOut'', ''fsUnderline''. 166 So the value [''fsBold'',''fsItalic''] means that the font must be bold and italic. 167 See [[BGRABitmap Miscellaneous types|miscellaneous types]] } 168 FontStyle: TFontStyles; 169 170 {** Specifies the quality of rendering. Default value is ''fqSystem''. 171 See [[BGRABitmap Miscellaneous types|miscellaneous types]] } 172 FontQuality : TBGRAFontQuality; 173 174 {** Specifies the rotation of the text, for functions that support text rotation. 175 It is expressed in tenth of degrees, positive values going counter-clockwise. } 176 FontOrientation: integer; 177 178 {** Specifies how the font is vertically aligned relative to the start coordinate. 179 See [[BGRABitmap Miscellaneous types|miscellaneous types]]} 180 FontVerticalAnchor: TFontVerticalAnchor; 181 182 {** Specifies the base direction of the text (cf Unicode). By default, it is 183 automatically determined by the first strongly oriented character. 184 You can specify another base direction here however it is not taken 185 into account by the LCL on Linux. } 186 FontBidiMode: TFontBidiMode; 187 188 {** Specifies the height of the font in pixels without taking into account 189 additional line spacing. A negative value means that it is the 190 full height instead (see below) } 191 property FontHeight: integer Read GetFontHeight Write SetFontHeight; 192 193 {** Specifies the height of the font in pixels, taking into account the 194 additional line spacing defined for the font } 195 property FontFullHeight: integer read GetFontFullHeight write SetFontFullHeight; 196 197 {** Simplified property to specify the quality (see ''FontQuality'') } 198 property FontAntialias: Boolean read GetFontAntialias write SetFontAntialias; 199 200 property FontVerticalAnchorOffset: single read GetFontVerticalAnchorOffset; 201 202 {** Returns measurement for the current font in pixels } 203 property FontPixelMetric: TFontPixelMetric read GetFontPixelMetric; 204 205 {** Specifies the font renderer. When working with the LCL, 206 by default it is an instance of ''TLCLFontRenderer'' of 207 unit ''BGRAText''. Other renderers are provided in ''BGRATextFX'' 208 unit and ''BGRAVectorize'' unit. Additionally, ''BGRAFreeType'' 209 provides a renderer independent from the LCL. 210 * 211 * Once you assign a renderer, it will automatically be freed when 212 the bitmap is freed. The renderers may provide additional styling 213 for the font, not accessible with the properties in this class 214 * 215 * See [[BGRABitmap tutorial Font rendering|font rendering]]} 216 property FontRenderer: TBGRACustomFontRenderer read GetFontRenderer write SetFontRenderer; 217 218 public 219 constructor Create(AFPImage: TFPCustomImage); overload; virtual; abstract; 220 constructor Create(ABitmap: TBitmap; AUseTransparent: boolean = true); overload; virtual; abstract; 221 constructor Create(AFilename: string); overload; virtual; abstract; 222 constructor Create(AFilename: string; AIsUtf8Filename: boolean); overload; virtual; abstract; 223 constructor Create(AFilename: string; AIsUtf8Filename: boolean; AOptions: TBGRALoadingOptions); overload; virtual; abstract; 224 constructor Create(AStream: TStream); overload; virtual; abstract; 225 226 function NewBitmap: TBGRACustomBitmap; overload; override; 227 function NewBitmap(AWidth, AHeight: integer): TBGRACustomBitmap; overload; override; 228 function NewBitmap(AWidth, AHeight: integer; const Color: TBGRAPixel): TBGRACustomBitmap; overload; override; 229 function NewBitmap(AWidth, AHeight: integer; AColor: Pointer): TBGRACustomBitmap; overload; override; 230 function NewBitmap(Filename: string): TBGRACustomBitmap; overload; virtual; abstract; 231 function NewBitmap(Filename: string; AIsUtf8: boolean): TBGRACustomBitmap; overload; virtual; abstract; 232 function NewBitmap(Filename: string; AIsUtf8: boolean; AOptions: TBGRALoadingOptions): TBGRACustomBitmap; overload; virtual; abstract; 233 function NewBitmap(AFPImage: TFPCustomImage): TBGRACustomBitmap; overload; virtual; abstract; 234 235 procedure LoadFromStream(AStream: TStream; AHandler: TFPCustomImageReader; AOptions: TBGRALoadingOptions); override; 236 237 {==== Reference counting ====} 238 239 {** Adds a reference (this reference count is not the same as 240 the reference count of an interface, it changes only by 241 explicit calls) } 242 function NewReference: TBGRACustomBitmap; override; 243 {** Returns an object with a reference count equal to 1. Duplicate 244 this bitmap if necessary } 245 function GetUnique: TBGRACustomBitmap; override; 246 function Duplicate(DuplicateProperties: Boolean = False): TBGRACustomBitmap; overload; override; 247 function Duplicate(DuplicateProperties, DuplicateXorMask: Boolean): TBGRACustomBitmap; overload; virtual; 248 procedure CopyPropertiesTo(ABitmap: TCustomUniversalBitmap); override; 249 function GetPart(const ARect: TRect): TBGRACustomBitmap; override; 250 251 function CreateBrushTexture(ABrushStyle: TBrushStyle; APatternColor, ABackgroundColor: TBGRAPixel; 252 AWidth: integer = 8; AHeight: integer = 8; APenWidth: single = 1): TBGRACustomBitmap; override; 253 254 {** Can only be called with an existing instance of ''TBGRACustomBitmap''. 255 Sets the dimensions of an existing ''TBGRACustomBitmap'' instance. } 256 procedure SetSize(AWidth, AHeight: integer); override; 257 258 {==== Retrieve image from system ====} 259 260 {** Gets the content of the specified device context } 261 procedure LoadFromDevice(DC: HDC); overload; virtual; abstract; 262 {** Gets the content from the specified rectangular area of a device context } 263 procedure LoadFromDevice(DC: HDC; ARect: TRect); overload; virtual; abstract; 264 {** Fills the content with a screenshot of the primary monitor } 265 procedure TakeScreenshotOfPrimaryMonitor; virtual; abstract; 266 {** Fills the content with a screenshot of the specified rectangular area of the desktop 267 (it can be from any screen) } 268 procedure TakeScreenshot(ARect: TRect); virtual; abstract; 269 {** For more methods, see derived class [[TBGRABitmap class|TBGRABitmap]] } 270 271 {==== Drawing functions ====} 272 273 {Pixel functions} 274 procedure SetPixel(x, y: int32or64; c: TColor); overload; virtual; abstract; 275 procedure XorPixel(x, y: int32or64; const c: TBGRAPixel); overload; virtual; abstract; 276 procedure DrawPixel(x, y: int32or64; const c: TBGRAPixel; ADrawMode: TDrawMode); overload; override; 277 procedure FastBlendPixel(x, y: int32or64; const c: TBGRAPixel); virtual; abstract; 278 function GetPixel256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter = rfLinear; smoothBorder: boolean = true): TBGRAPixel; virtual; abstract; 279 function GetPixel(x, y: single; AResampleFilter: TResampleFilter = rfLinear; smoothBorder: boolean = true): TBGRAPixel; overload; virtual; abstract; 280 function GetPixelCycle(x, y: single; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel; overload; virtual; abstract; 281 function GetPixelCycle(x, y: single; AResampleFilter: TResampleFilter; repeatX: boolean; repeatY: boolean): TBGRAPixel; overload; virtual; abstract; 282 function GetPixelCycle256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel; overload; virtual; abstract; 283 function GetPixelCycle256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter; repeatX: boolean; repeatY: boolean): TBGRAPixel; overload; virtual; abstract; 284 285 {Line primitives} 286 procedure XorHorizLine(x, y, x2: int32or64; c: TBGRAPixel); virtual; abstract; 287 procedure DrawHorizLine(x, y, x2: int32or64; ec: TExpandedPixel); overload; virtual; abstract; 288 procedure DrawHorizLine(x, y, x2: int32or64; texture: IBGRAScanner); overload; 289 procedure FastBlendHorizLine(x, y, x2: int32or64; c: TBGRAPixel); virtual; abstract; 290 procedure DrawHorizLineDiff(x, y, x2: int32or64; c, compare: TBGRAPixel; maxDiff: byte); virtual; abstract; 291 procedure HorizLineDiff(x, y, x2: int32or64; const ABrush: TUniversalBrush; ACompare: TBGRAPixel; AMaxDiffW: word); virtual; abstract; 292 293 procedure XorVertLine(x, y, y2: int32or64; c: TBGRAPixel); virtual; abstract; 294 procedure DrawVertLine(x, y, y2: int32or64; c: TBGRAPixel); virtual; abstract; 295 procedure FastBlendVertLine(x, y, y2: int32or64; c: TBGRAPixel); virtual; abstract; 296 297 {==== Rectangles, ellipses and path (floating point coordinates) ====} 298 {* These functions use the current pen style/cap/join. The parameter ''w'' 299 specifies the width of the line and the base unit for dashes 300 * The coordinates are pixel-centered, so that when filling a rectangle, 301 if the supplied values are integers, the border will be half transparent. 302 If you want the border to be completely filled, you can subtract/add 303 0.5 to the coordinates to include the remaining thin border. 304 See [[BGRABitmap tutorial 13|coordinate system]]. } 305 306 {==== Multi-shape fill ====} 307 308 {** Draws and fill a polyline using current pen style/cap/join in one go. 309 The stroke is stricly over the fill even if partially transparent. 310 ''fillcolor'' specifies a color to fill the polygon formed by the points } 311 procedure DrawPolyLineAntialias(const points: array of TPointF; c: TBGRAPixel; w: single; fillcolor: TBGRAPixel); overload; virtual; abstract; 312 {** Draws a filled polygon using current pen style/cap/join in one go. 313 The stroke is stricly over the fill even if partially transparent. 314 The polygon is always closed. You don't need to set the last point 315 to be the same as the first point. } 316 procedure DrawPolygonAntialias(const points: array of TPointF; c: TBGRAPixel; w: single; fillcolor: TBGRAPixel); overload; virtual; abstract; 317 318 procedure EllipseAntialias(x, y, rx, ry: single; c: TBGRAPixel; w: single; back: TBGRAPixel); overload; virtual; abstract; 319 procedure EllipseAntialias(AOrigin, AXAxis, AYAxis: TPointF; c: TBGRAPixel; w: single; back: TBGRAPixel); overload; virtual; abstract; 320 321 procedure DrawPath(APath: IBGRAPath; AStrokeColor: TBGRAPixel; AWidth: single; AFillColor: TBGRAPixel); overload; virtual; abstract; 322 procedure DrawPath(APath: IBGRAPath; AStrokeTexture: IBGRAScanner; AWidth: single; AFillColor: TBGRAPixel); overload; virtual; abstract; 323 procedure DrawPath(APath: IBGRAPath; AStrokeColor: TBGRAPixel; AWidth: single; AFillTexture: IBGRAScanner); overload; virtual; abstract; 324 procedure DrawPath(APath: IBGRAPath; AStrokeTexture: IBGRAScanner; AWidth: single; AFillTexture: IBGRAScanner); overload; virtual; abstract; 325 326 procedure DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; AStrokeColor: TBGRAPixel; AWidth: single; AFillColor: TBGRAPixel); overload; virtual; abstract; 327 procedure DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; AStrokeTexture: IBGRAScanner; AWidth: single; AFillColor: TBGRAPixel); overload; virtual; abstract; 328 procedure DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; AStrokeColor: TBGRAPixel; AWidth: single; AFillTexture: IBGRAScanner); overload; virtual; abstract; 329 procedure DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; AStrokeTexture: IBGRAScanner; AWidth: single; AFillTexture: IBGRAScanner); overload; virtual; abstract; 330 331 {==== Gradient/textured polygons ====} 332 333 procedure FillTriangleLinearColor(pt1,pt2,pt3: TPointF; c1,c2,c3: TBGRAPixel); overload; virtual; abstract; 334 procedure FillTriangleLinearColorAntialias(pt1,pt2,pt3: TPointF; c1,c2,c3: TBGRAPixel); overload; virtual; abstract; 335 procedure FillTriangleLinearMapping(pt1,pt2,pt3: TPointF; texture: IBGRAScanner; tex1, tex2, tex3: TPointF; TextureInterpolation: Boolean= True); overload; virtual; abstract; 336 procedure FillTriangleLinearMappingLightness(pt1,pt2,pt3: TPointF; texture: IBGRAScanner; tex1, tex2, tex3: TPointF; light1,light2,light3: word; TextureInterpolation: Boolean= True); overload; virtual; abstract; 337 procedure FillTriangleLinearMappingAntialias(pt1,pt2,pt3: TPointF; texture: IBGRAScanner; tex1, tex2, tex3: TPointF); overload; virtual; abstract; 338 339 procedure FillQuadLinearColor(pt1,pt2,pt3,pt4: TPointF; c1,c2,c3,c4: TBGRAPixel); overload; virtual; abstract; 340 procedure FillQuadLinearColorAntialias(pt1,pt2,pt3,pt4: TPointF; c1,c2,c3,c4: TBGRAPixel); overload; virtual; abstract; 341 procedure FillQuadLinearMapping(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; TextureInterpolation: Boolean= True; ACulling: TFaceCulling = fcNone; ACropToPolygon: boolean = true); overload; virtual; abstract; 342 procedure FillQuadLinearMappingLightness(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; light1,light2,light3,light4: word; TextureInterpolation: Boolean= True); overload; virtual; abstract; 343 procedure FillQuadLinearMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; ACulling: TFaceCulling = fcNone); overload; virtual; abstract; 344 procedure FillQuadPerspectiveMapping(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; ADrawMode: TDrawMode = dmDrawWithTransparency); overload; virtual; abstract; 345 procedure FillQuadPerspectiveMapping(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; ACleanBorders: TRect; ADrawMode: TDrawMode = dmDrawWithTransparency); overload; virtual; abstract; 346 procedure FillQuadPerspectiveMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); overload; virtual; abstract; 347 procedure FillQuadPerspectiveMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; ACleanBorders: TRect); overload; virtual; abstract; 348 procedure FillQuadAffineMapping(Orig,HAxis,VAxis: TPointF; AImage: TBGRACustomBitmap; APixelCenteredCoordinates: boolean = true; ADrawMode: TDrawMode = dmDrawWithTransparency; AOpacity: byte = 255); virtual; abstract; 349 procedure FillQuadAffineMappingAntialias(Orig,HAxis,VAxis: TPointF; AImage: TBGRACustomBitmap; APixelCenteredCoordinates: boolean = true; AOpacity: byte = 255); virtual; abstract; 350 351 procedure FillEllipseLinearColorAntialias(x, y, rx, ry: single; outercolor, innercolor: TBGRAPixel); overload; virtual; abstract; 352 procedure FillEllipseLinearColorAntialias(AOrigin, AXAxis, AYAxis: TPointF; outercolor, innercolor: TBGRAPixel); overload; virtual; abstract; 353 354 procedure FillPolyLinearColor(const points: array of TPointF; AColors: array of TBGRAPixel); overload; virtual; abstract; 355 procedure FillPolyLinearMapping(const points: array of TPointF; texture: IBGRAScanner; texCoords: array of TPointF; TextureInterpolation: Boolean); overload; virtual; abstract; 356 procedure FillPolyLinearMappingLightness(const points: array of TPointF; texture: IBGRAScanner; texCoords: array of TPointF; lightnesses: array of word; TextureInterpolation: Boolean); overload; virtual; abstract; 357 procedure FillPolyPerspectiveMapping(const points: array of TPointF; const pointsZ: array of single; texture: IBGRAScanner; texCoords: array of TPointF; TextureInterpolation: Boolean; zbuffer: psingle = nil); overload; virtual; abstract; 358 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); overload; virtual; abstract; 359 360 procedure Arc(cx,cy,rx,ry: single; const StartPoint,EndPoint: TPointF; AColor: TBGRAPixel; w: single; ADrawChord: boolean; AFillColor: TBGRAPixel); overload; 361 procedure Arc(cx,cy,rx,ry: single; StartAngleRad,EndAngleRad: Single; AColor: TBGRAPixel; w: single; ADrawChord: boolean; AFillColor: TBGRAPixel); overload; 362 procedure FillChord(cx,cy,rx,ry: single; const StartPoint,EndPoint: TPointF; AFillColor: TBGRAPixel); overload; 363 procedure FillChord(cx,cy,rx,ry: single; StartAngleRad,EndAngleRad: Single; AFillColor: TBGRAPixel); overload; 364 procedure FillChord(cx,cy,rx,ry: single; const StartPoint,EndPoint: TPointF; texture: IBGRAScanner); overload; 365 procedure FillChord(cx,cy,rx,ry: single; StartAngleRad,EndAngleRad: Single; texture: IBGRAScanner); overload; 366 procedure FillChordInRect(const ARect: TRect; StartAngleRad,EndAngleRad: Single; AFillColor: TBGRAPixel); overload; 367 procedure FillChordInRect(const ARect: TRect; StartAngleRad,EndAngleRad: Single; texture: IBGRAScanner); overload; 368 369 procedure Pie(cx,cy,rx,ry: single; const StartPoint,EndPoint: TPointF; AColor: TBGRAPixel; w: single; AFillColor: TBGRAPixel); overload; 370 procedure Pie(cx,cy,rx,ry: single; StartAngleRad,EndAngleRad: Single; AColor: TBGRAPixel; w: single; AFillColor: TBGRAPixel); overload; 371 procedure FillPie(cx,cy,rx,ry: single; const StartPoint,EndPoint: TPointF; AFillColor: TBGRAPixel); overload; 372 procedure FillPie(cx,cy,rx,ry: single; StartAngleRad,EndAngleRad: Single; AFillColor: TBGRAPixel); overload; 373 procedure FillPie(cx,cy,rx,ry: single; const StartPoint,EndPoint: TPointF; texture: IBGRAScanner); overload; 374 procedure FillPie(cx,cy,rx,ry: single; StartAngleRad,EndAngleRad: Single; texture: IBGRAScanner); overload; 375 procedure FillPieInRect(const ARect: TRect; StartAngleRad,EndAngleRad: Single; AFillColor: TBGRAPixel); overload; 376 procedure FillPieInRect(const ARect: TRect; StartAngleRad,EndAngleRad: Single; texture: IBGRAScanner); overload; 377 378 procedure RectangleAntialias(x, y, x2, y2: single; c: TBGRAPixel; w: single; back: TBGRAPixel); overload; virtual; abstract; 379 procedure RectangleWithin(x1,y1,x2,y2: single; ABorderColor: TBGRAPixel; w: single; AFillColor: TBGRAPixel; APixelCenteredCoordinates: boolean = true); overload; 380 procedure RectangleWithin(r: TRect; ABorderColor: TBGRAPixel; w: single; AFillColor: TBGRAPixel); overload; 381 382 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; c: TBGRAPixel; w: single; options: TRoundRectangleOptions = []); overload; virtual; abstract; 383 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; pencolor: TBGRAPixel; w: single; fillcolor: TBGRAPixel; options: TRoundRectangleOptions = []); overload; virtual; abstract; 384 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; penTexture: IBGRAScanner; w: single; fillTexture: IBGRAScanner; options: TRoundRectangleOptions = []); overload; virtual; abstract; 385 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; texture: IBGRAScanner; w: single; options: TRoundRectangleOptions = []); overload; virtual; abstract; 386 387 procedure FillRect(r: TRect; texture: IBGRAScanner; mode: TDrawMode; ditheringAlgorithm: TDitheringAlgorithm); overload; virtual; 388 procedure FillRect(r: TRect; texture: IBGRAScanner; mode: TDrawMode; AScanOffset: TPoint; ditheringAlgorithm: TDitheringAlgorithm); overload; virtual; 389 procedure FillRect(x, y, x2, y2: integer; texture: IBGRAScanner; mode: TDrawMode; ditheringAlgorithm: TDitheringAlgorithm); overload; virtual; 390 procedure FillRect(x, y, x2, y2: integer; texture: IBGRAScanner; mode: TDrawMode; AScanOffset: TPoint; ditheringAlgorithm: TDitheringAlgorithm); overload; virtual; abstract; 391 392 procedure TextOutCurved(ACursor: TBGRACustomPathCursor; const sUTF8: string; AColor: TBGRAPixel; AAlign: TAlignment; ALetterSpacing: single); overload; virtual; abstract; 393 procedure TextOutCurved(ACursor: TBGRACustomPathCursor; const sUTF8: string; ATexture: IBGRAScanner; AAlign: TAlignment; ALetterSpacing: single); overload; virtual; abstract; 394 procedure TextOutCurved(APath: IBGRAPath; const sUTF8: string; AColor: TBGRAPixel; AAlign: TAlignment; ALetterSpacing: single); overload; virtual; 395 procedure TextOutCurved(APath: IBGRAPath; const sUTF8: string; ATexture: IBGRAScanner; AAlign: TAlignment; ALetterSpacing: single); overload; virtual; 396 procedure TextRect(ARect: TRect; x, y: integer; const sUTF8: string; style: TTextStyle; c: TBGRAPixel); overload; virtual; abstract; 397 procedure TextRect(ARect: TRect; x, y: integer; const sUTF8: string; style: TTextStyle; texture: IBGRAScanner); overload; virtual; abstract; 398 procedure TextMultiline(x,y: single; const sUTF8: string; c: TBGRAPixel; AAlign: TBidiTextAlignment = btaLeftJustify; AVertAlign: TTextLayout = tlTop; AParagraphSpacing: single = 0); overload; 399 procedure TextMultiline(x,y: single; const sUTF8: string; ATexture: IBGRAScanner; AAlign: TBidiTextAlignment = btaLeftJustify; AVertAlign: TTextLayout = tlTop; AParagraphSpacing: single = 0); overload; 400 procedure TextMultiline(ALeft,ATop,AWidth: single; const sUTF8: string; c: TBGRAPixel; AAlign: TBidiTextAlignment = btaNatural; AVertAlign: TTextLayout = tlTop; AParagraphSpacing: single = 0); overload; virtual; abstract; 401 procedure TextMultiline(ALeft,ATop,AWidth: single; const sUTF8: string; ATexture: IBGRAScanner; AAlign: TBidiTextAlignment = btaNatural; AVertAlign: TTextLayout = tlTop; AParagraphSpacing: single = 0); overload; virtual; abstract; 402 function TextSize(const sUTF8: string): TSize; overload; virtual; abstract; 403 function TextAffineBox(const sUTF8: string): TAffineBox; virtual; abstract; 404 function TextSize(const sUTF8: string; AMaxWidth: integer): TSize; overload; virtual; abstract; 405 function TextSize(const sUTF8: string; AMaxWidth: integer; ARightToLeft: boolean): TSize; overload; virtual; abstract; 406 function TextFitInfo(const sUTF8: string; AMaxWidth: integer): integer; virtual; abstract; 407 function TextSizeMultiline(const sUTF8: string; AMaxWidth: single = EmptySingle; AParagraphSpacing: single = 0): TSize; virtual; abstract; 408 409 { Draw the UTF8 encoded string, (x,y) being the top-left corner by default. The color c or texture is used to fill the text. 410 The value of FontOrientation is taken into account, so that the text may be rotated. } 411 procedure TextOut(x, y: single; const sUTF8: string; c: TBGRAPixel; align: TAlignment); overload; virtual; 412 procedure TextOut(x, y: single; const sUTF8: string; texture: IBGRAScanner; align: TAlignment); overload; virtual; 413 procedure TextOut(x, y: single; const sUTF8: string; c: TBGRAPixel); overload; virtual; 414 procedure TextOut(x, y: single; const sUTF8: string; c: TBGRAPixel; ARightToLeft: boolean); overload; virtual; 415 procedure TextOut(x, y: single; const sUTF8: string; c: TColor); overload; virtual; 416 procedure TextOut(x, y: single; const sUTF8: string; c: TColor; ARightToLeft: boolean); overload; virtual; 417 procedure TextOut(x, y: single; const sUTF8: string; texture: IBGRAScanner); overload; virtual; 418 procedure TextOut(x, y: single; const sUTF8: string; texture: IBGRAScanner; ARightToLeft: boolean); overload; virtual; 419 procedure TextOut(x, y: single; const sUTF8: string; c: TBGRAPixel; align: TAlignment; ARightToLeft: boolean); overload; virtual; abstract; 420 procedure TextOut(x, y: single; const sUTF8: string; texture: IBGRAScanner; align: TAlignment; ARightToLeft: boolean); overload; virtual; abstract; 421 procedure TextOut(x, y: single; const sUTF8: string; AColor: TBGRAPixel; AAlign: TAlignment; ALetterSpacing: single); overload; virtual; abstract; 422 procedure TextOut(x, y: single; const sUTF8: string; ATexture: IBGRAScanner; AAlign: TAlignment; ALetterSpacing: single); overload; virtual; abstract; 423 424 { Overrides the font orientation with the parameter orientationTenthDegCCW } 425 procedure TextOutAngle(x, y: single; orientationTenthDegCCW: integer; const sUTF8: string; c: TBGRAPixel); overload; virtual; 426 procedure TextOutAngle(x, y: single; orientationTenthDegCCW: integer; const sUTF8: string; c: TBGRAPixel; align: TAlignment); overload; virtual; 427 procedure TextOutAngle(x, y: single; orientationTenthDegCCW: integer; const sUTF8: string; c: TBGRAPixel; align: TAlignment; ARightToLeft: boolean); overload; virtual; abstract; 428 procedure TextOutAngle(x, y: single; orientationTenthDegCCW: integer; const sUTF8: string; texture: IBGRAScanner); overload; virtual; 429 procedure TextOutAngle(x, y: single; orientationTenthDegCCW: integer; const sUTF8: string; texture: IBGRAScanner; align: TAlignment); overload; virtual; 430 procedure TextOutAngle(x, y: single; orientationTenthDegCCW: integer; const sUTF8: string; texture: IBGRAScanner; align: TAlignment; ARightToLeft: boolean); overload; virtual; abstract; 431 432 { Draw the UTF8 encoded string in the rectangle ARect. Text is wrapped if necessary. 433 The position depends on the specified horizontal alignment halign and vertical alignement valign. 434 The color c or texture is used to fill the text. No rotation is applied. } 435 procedure TextRect(ARect: TRect; const sUTF8: string; halign: TAlignment; valign: TTextLayout; c: TBGRAPixel); overload; virtual; 436 procedure TextRect(ARect: TRect; const sUTF8: string; halign: TAlignment; valign: TTextLayout; texture: IBGRAScanner); overload; virtual; 437 438 //-------------------------- computing path ------------------------------------ 439 440 {Spline} 441 function ComputeClosedSpline(const APoints: array of TPointF; AStyle: TSplineStyle): ArrayOfTPointF; virtual; abstract; 442 function ComputeOpenedSpline(const APoints: array of TPointF; AStyle: TSplineStyle): ArrayOfTPointF; virtual; abstract; 443 function ComputeBezierCurve(const curve: TCubicBezierCurve): ArrayOfTPointF; overload; virtual; abstract; 444 function ComputeBezierCurve(const curve: TQuadraticBezierCurve): ArrayOfTPointF; overload; virtual; abstract; 445 function ComputeBezierSpline(const spline: array of TCubicBezierCurve): ArrayOfTPointF; overload; virtual; abstract; 446 function ComputeBezierSpline(const spline: array of TQuadraticBezierCurve): ArrayOfTPointF; overload; virtual; abstract; 447 448 {can be accessed via Pen property} 449 function ComputeWidePolyline(const points: array of TPointF; w: single): ArrayOfTPointF; overload; virtual; abstract; 450 function ComputeWidePolyline(const points: array of TPointF; w: single; ClosedCap: boolean): ArrayOfTPointF; overload; virtual; abstract; 451 function ComputeWidePolygon(const points: array of TPointF; w: single): ArrayOfTPointF; virtual; abstract; 452 453 function ComputeEllipse(x,y,rx,ry: single): ArrayOfTPointF; overload; deprecated; 454 function ComputeEllipse(x,y,rx,ry,w: single): ArrayOfTPointF; overload; deprecated; 455 function ComputeEllipseContour(x,y,rx,ry: single; quality: single = 1): ArrayOfTPointF; overload; virtual; abstract; 456 function ComputeEllipseContour(AOrigin, AXAxis, AYAxis: TPointF; quality: single = 1): ArrayOfTPointF; overload; virtual; abstract; 457 function ComputeEllipseBorder(x,y,rx,ry,w: single; quality: single = 1): ArrayOfTPointF; overload; virtual; abstract; 458 function ComputeEllipseBorder(AOrigin, AXAxis, AYAxis: TPointF; w: single; quality: single = 1): ArrayOfTPointF; overload; virtual; abstract; 459 function ComputeArc65536(x,y,rx,ry: single; start65536,end65536: word; quality: single = 1): ArrayOfTPointF; virtual; abstract; 460 function ComputeArcRad(x,y,rx,ry: single; startRad,endRad: single; quality: single = 1): ArrayOfTPointF; virtual; abstract; 461 function ComputeRoundRect(x1,y1,x2,y2,rx,ry: single; quality: single = 1): ArrayOfTPointF; overload; virtual; abstract; 462 function ComputeRoundRect(x1,y1,x2,y2,rx,ry: single; options: TRoundRectangleOptions; quality: single = 1): ArrayOfTPointF; overload; virtual; abstract; 463 function ComputePie65536(x,y,rx,ry: single; start65536,end65536: word; quality: single = 1): ArrayOfTPointF; virtual; abstract; 464 function ComputePieRad(x,y,rx,ry: single; startRad,endRad: single; quality: single = 1): ArrayOfTPointF; virtual; abstract; 465 466 {Filling} 467 468 // compatibility: take into account ClipRect 469 procedure Fill(texture: IBGRAScanner); overload; virtual; 470 procedure Fill(texture: IBGRAScanner; mode: TDrawMode); overload; override; 471 472 procedure Fill(c: TBGRAPixel; start, Count: integer); overload; virtual; abstract; 473 procedure DrawPixels(c: TBGRAPixel; start, Count: integer); virtual; abstract; 474 procedure AlphaFill(alpha: byte; start, Count: integer); overload; virtual; abstract; 475 procedure ReplaceColor(before, after: TColor); overload; virtual; abstract; 476 procedure ReplaceColor(ARect: TRect; before, after: TColor); overload; virtual; abstract; 477 procedure FloodFill(X, Y: integer; Color: TBGRAPixel; 478 mode: TFloodfillMode; Tolerance: byte = 0); overload; virtual; 479 procedure FloodFill(X, Y: integer; const Brush: TUniversalBrush; 480 Progressive: boolean; ToleranceW: Word = $00ff); overload; virtual; 481 procedure ParallelFloodFill(X, Y: integer; Dest: TCustomUniversalBitmap; Color: TBGRAPixel; 482 mode: TFloodfillMode; Tolerance: byte = 0; DestOfsX: integer = 0; DestOfsY: integer = 0); overload; virtual; abstract; 483 procedure ParallelFloodFill(X, Y: integer; Dest: TCustomUniversalBitmap; const Brush: TUniversalBrush; 484 Progressive: boolean; ToleranceW: Word = $00ff; DestOfsX: integer = 0; DestOfsY: integer = 0); overload; virtual; abstract; 485 procedure GradientFill(x, y, x2, y2: integer; c1, c2: TBGRAPixel; 486 gtype: TGradientType; o1, o2: TPointF; mode: TDrawMode; 487 gammaColorCorrection: boolean = True; Sinus: Boolean=False; 488 ditherAlgo: TDitheringAlgorithm = daNearestNeighbor); overload; virtual; abstract; 489 procedure GradientFill(x, y, x2, y2: integer; gradient: TBGRACustomGradient; 490 gtype: TGradientType; o1, o2: TPointF; mode: TDrawMode; 491 Sinus: Boolean=False; 492 ditherAlgo: TDitheringAlgorithm = daNearestNeighbor); overload; virtual; abstract; 493 494 {Canvas drawing functions} 495 procedure DataDrawTransparent(ACanvas: TCanvas; Rect: TRect; 496 AData: Pointer; ALineOrder: TRawImageLineOrder; AWidth, AHeight: integer); virtual; abstract; 497 procedure DataDrawOpaque(ACanvas: TCanvas; ARect: TRect; AData: Pointer; 498 ALineOrder: TRawImageLineOrder; AWidth, AHeight: integer); virtual; abstract; 499 procedure GetImageFromCanvas(CanvasSource: TCanvas; x, y: integer); virtual; abstract; 500 procedure Draw(ACanvas: TCanvas; x, y: integer; Opaque: boolean = True); overload; virtual; abstract; 501 procedure Draw(ACanvas: TCanvas; Rect: TRect; Opaque: boolean = True); overload; virtual; abstract; 502 procedure DrawPart(ARect: TRect; ACanvas: TCanvas; x, y: integer; Opaque: boolean); overload; virtual; 503 procedure DrawPart(ARect: TRect; ACanvas: TCanvas; ATargetRect: TRect; Opaque: boolean); overload; virtual; 504 function GetPtrBitmap(Top,Bottom: Integer): TBGRACustomBitmap; virtual; abstract; 505 function MakeBitmapCopy(BackgroundColor: TColor): TBitmap; virtual; abstract; 506 507 {BGRA bitmap functions} 508 procedure CrossFade(ARect: TRect; Source1, Source2: IBGRAScanner; AFadePosition: byte; mode: TDrawMode = dmDrawWithTransparency); overload; virtual; abstract; 509 procedure CrossFade(ARect: TRect; Source1, Source2: IBGRAScanner; AFadeMask: IBGRAScanner; mode: TDrawMode = dmDrawWithTransparency); overload; virtual; abstract; 510 procedure PutImage(x, y: integer; Source: TBitmap; mode: TDrawMode; AOpacity: byte = 255); overload; 511 procedure StretchPutImage(ARect: TRect; Source: TBitmap; mode: TDrawMode; AOpacity: byte = 255); overload; 512 procedure StretchPutImage(ARect: TRect; Source: TBGRACustomBitmap; mode: TDrawMode; AOpacity: byte = 255); overload; virtual; abstract; 513 procedure StretchPutImageProportionally(ARect: TRect; AHorizAlign: TAlignment; AVertAlign: TTextLayout; Source: TBGRACustomBitmap; mode: TDrawMode; AOpacity: byte = 255); 514 procedure PutImageSubpixel(x, y: single; Source: TBGRACustomBitmap; AOpacity: byte = 255); 515 procedure PutImagePart(x,y: integer; Source: TBGRACustomBitmap; SourceRect: TRect; mode: TDrawMode; AOpacity: byte = 255); 516 procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AOpacity: Byte=255; ACorrectBlur: Boolean = false); overload; 517 procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AResampleFilter: TResampleFilter; AOpacity: Byte=255); overload; 518 procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte=255); overload; 519 procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AOutputBounds: TRect; AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte=255); overload; 520 procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AOutputBounds: TRect; AOpacity: Byte=255; ACorrectBlur: Boolean = false); overload; 521 procedure PutImageAffine(AMatrix: TAffineMatrix; Source: TBGRACustomBitmap; AOpacity: Byte=255; ACorrectBlur: Boolean = false; APixelCenteredCoords: boolean = true); overload; 522 procedure PutImageAffine(AMatrix: TAffineMatrix; Source: TBGRACustomBitmap; AResampleFilter: TResampleFilter; AOpacity: Byte=255; APixelCenteredCoords: boolean = true); overload; 523 procedure PutImageAffine(AMatrix: TAffineMatrix; Source: TBGRACustomBitmap; AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte=255; APixelCenteredCoords: boolean = true); overload; 524 procedure PutImageAffine(AMatrix: TAffineMatrix; Source: TBGRACustomBitmap; AOutputBounds: TRect; AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte=255; APixelCenteredCoords: boolean = true); overload; virtual; abstract; 525 procedure PutImageAffine(AMatrix: TAffineMatrix; Source: TBGRACustomBitmap; AOutputBounds: TRect; AOpacity: Byte=255; ACorrectBlur: Boolean = false; APixelCenteredCoords: boolean = true); overload; 526 function GetImageAffineBounds(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap): TRect; overload; 527 function GetImageAffineBounds(Origin,HAxis,VAxis: TPointF; ASourceWidth, ASourceHeight: integer; const ASourceBounds: TRect; AClipOutput: boolean = true): TRect; overload; 528 function GetImageAffineBounds(AMatrix: TAffineMatrix; Source: TBGRACustomBitmap; APixelCenteredCoords: boolean = true): TRect; overload; 529 function GetImageAffineBounds(AMatrix: TAffineMatrix; ASourceBounds: TRect; AClipOutput: boolean = true; APixelCenteredCoords: boolean = true): TRect; overload; virtual; abstract; 530 class function IsAffineRoughlyTranslation(AMatrix: TAffineMatrix; ASourceBounds: TRect): boolean; virtual; abstract; 531 procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; AOutputBounds: TRect; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255; ARestoreOffsetAfterRotation: boolean = false; ACorrectBlur: Boolean = false); overload; 532 procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255; ARestoreOffsetAfterRotation: boolean = false; ACorrectBlur: Boolean = false); overload; 533 procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; AOutputBounds: TRect; AResampleFilter: TResampleFilter; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255; ARestoreOffsetAfterRotation: boolean = false); overload; 534 procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; AResampleFilter: TResampleFilter; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255; ARestoreOffsetAfterRotation: boolean = false); overload; 535 procedure ComputeImageAngleAxes(x,y,w,h,angle: single; imageCenterX,imageCenterY: single; ARestoreOffsetAfterRotation: boolean; 536 out Origin,HAxis,VAxis: TPointF); 537 function GetImageAngleBounds(x,y: single; Source: TBGRACustomBitmap; angle: single; imageCenterX: single = 0; imageCenterY: single = 0; ARestoreOffsetAfterRotation: boolean = false): TRect; 538 procedure Blend(AColor: TBGRAPixel; AOperation: TBlendOperation; AIgnoreDestAlpha: boolean = false); virtual; 539 procedure BlendOver(AColor: TBGRAPixel; AOperation: TBlendOperation; AOpacity: byte = 255; ALinearBlend: boolean = false; AIgnoreDestAlpha: boolean = false); virtual; 540 procedure BlendRect(ADest: TRect; AColor: TBGRAPixel; AOperation: TBlendOperation; AIgnoreDestAlpha: boolean = false); overload; 541 procedure BlendRect(ADest: TRect; AColor: TBGRAPixel; AOperation: TBlendOperation; AExcludeChannels: TChannels); overload; virtual; abstract; 542 procedure BlendRectOver(ADest: TRect; AColor: TBGRAPixel; AOperation: TBlendOperation; AOpacity: byte = 255; ALinearBlend: boolean = false; AIgnoreDestAlpha: boolean = false); overload; 543 procedure BlendRectOver(ADest: TRect; AColor: TBGRAPixel; AOperation: TBlendOperation; AOpacity: byte; ALinearBlend: boolean; AExcludeChannels: TChannels); overload; virtual; abstract; 544 procedure BlendImage(x, y: integer; ASource: TBGRACustomBitmap; AOperation: TBlendOperation); overload; virtual; abstract; 545 procedure BlendImage(ADest: TRect; ASource: IBGRAScanner; AOffsetX, AOffsetY: integer; AOperation: TBlendOperation); overload; virtual; abstract; 546 procedure BlendImageOver(x, y: integer; ASource: TBGRACustomBitmap; AOperation: TBlendOperation; AOpacity: byte = 255; ALinearBlend: boolean = false); overload; virtual; abstract; 547 procedure BlendImageOver(ADest: TRect; ASource: IBGRAScanner; AOffsetX, AOffsetY: integer; AOperation: TBlendOperation; AOpacity: byte = 255; ALinearBlend: boolean = false); overload; virtual; abstract; 548 function Resample(newWidth, newHeight: integer; 549 mode: TResampleMode = rmFineResample): TBGRACustomBitmap; virtual; abstract; 550 551 //masks 552 procedure FillMask(x,y: integer; AMask: TCustomUniversalBitmap; ATexture: IBGRAScanner; ADrawMode: TDrawMode); overload; override; 553 procedure FillMask(x,y: integer; AMask: TCustomUniversalBitmap; ATexture: IBGRAScanner; ADrawMode: TDrawMode; AOpacity: byte); overload; virtual; abstract; 554 procedure EraseMask(x,y: integer; AMask: TBGRACustomBitmap; alpha: byte=255); virtual; abstract; 555 procedure FillClearTypeMask(x,y: integer; xThird: integer; AMask: TBGRACustomBitmap; color: TBGRAPixel; ARGBOrder: boolean = true); overload; virtual; abstract; 556 procedure FillClearTypeMask(x,y: integer; xThird: integer; AMask: TBGRACustomBitmap; texture: IBGRAScanner; ARGBOrder: boolean = true); overload; virtual; abstract; 557 function GetMaskFromAlpha: TBGRACustomBitmap; virtual; abstract; 558 function GetImageBoundsWithin(const ARect: TRect; Channel: TChannel = cAlpha; ANothingValue: Byte = 0): TRect; overload; override; 559 function GetImageBoundsWithin(const ARect: TRect; Channels: TChannels; ANothingValue: Byte = 0): TRect; overload; override; 560 561 {inplace filters} 562 procedure Negative; virtual; abstract; 563 procedure NegativeRect(ABounds: TRect); virtual; abstract; 564 procedure LinearNegative; virtual; abstract; 565 procedure LinearNegativeRect(ABounds: TRect); virtual; abstract; 566 procedure InplaceGrayscale(AGammaCorrection: boolean = true); overload; virtual; abstract; 567 procedure InplaceGrayscale(ABounds: TRect; AGammaCorrection: boolean = true); overload; virtual; abstract; 568 procedure InplaceNormalize(AEachChannel: boolean = True); overload; virtual; abstract; 569 procedure InplaceNormalize(ABounds: TRect; AEachChannel: boolean = True); overload; virtual; abstract; 570 procedure ConvertToLinearRGB; virtual; abstract; 571 procedure ConvertFromLinearRGB; virtual; abstract; 572 procedure SwapRedBlue; overload; virtual; abstract; 573 procedure SwapRedBlue(ARect: TRect); overload; virtual; abstract; 574 procedure GrayscaleToAlpha; virtual; abstract; 575 procedure AlphaToGrayscale; virtual; abstract; 576 procedure VerticalFlip(ARect: TRect); overload; override; 577 procedure HorizontalFlip(ARect: TRect); overload; override; 578 procedure RotateUDInplace(ARect: TRect); overload; override; 579 580 {Filters} 581 function RotateCW: TBGRACustomBitmap; override; 582 function RotateCCW: TBGRACustomBitmap; override; 583 function RotateUD: TBGRACustomBitmap; override; 584 function FilterSmartZoom3(Option: TMedianOption): TBGRACustomBitmap; virtual; abstract; 585 function FilterMedian(Option: TMedianOption): TBGRACustomBitmap; virtual; abstract; 586 function FilterSmooth: TBGRACustomBitmap; virtual; abstract; 587 function FilterSharpen(Amount: single = 1): TBGRACustomBitmap; overload; virtual; abstract; 588 function FilterSharpen(ABounds: TRect; Amount: single = 1): TBGRACustomBitmap; overload; virtual; abstract; 589 function FilterContour(AGammaCorrection: boolean = false): TBGRACustomBitmap; virtual; abstract; 590 function FilterPixelate(pixelSize: integer; useResample: boolean; filter: TResampleFilter = rfLinear): TBGRACustomBitmap; virtual; abstract; 591 function FilterBlurRadial(radius: single; blurType: TRadialBlurType): TBGRACustomBitmap; overload; override; 592 function FilterBlurRadial(const ABounds: TRect; radius: single; blurType: TRadialBlurType): TBGRACustomBitmap; overload; override; 593 function FilterBlurRadial(radiusX, radiusY: single; blurType: TRadialBlurType): TBGRACustomBitmap; overload; override; 594 function FilterBlurRadial(const ABounds: TRect; radiusX, radiusY: single; blurType: TRadialBlurType): TBGRACustomBitmap; overload; override; 595 function FilterBlurMotion(distance: single; angle: single; oriented: boolean): TBGRACustomBitmap; overload; override; 596 function FilterBlurMotion(const ABounds: TRect; distance: single; angle: single; oriented: boolean): TBGRACustomBitmap; overload; override; 597 function FilterCustomBlur(mask: TCustomUniversalBitmap): TBGRACustomBitmap; overload; override; 598 function FilterCustomBlur(const ABounds: TRect; mask: TCustomUniversalBitmap): TBGRACustomBitmap; overload; override; 599 function FilterEmboss(angle: single; AStrength: integer= 64; AOptions: TEmbossOptions = []): TBGRACustomBitmap; overload; virtual; abstract; 600 function FilterEmboss(angle: single; ABounds: TRect; AStrength: integer= 64; AOptions: TEmbossOptions = []): TBGRACustomBitmap; overload; virtual; abstract; 601 function FilterEmbossHighlight(FillSelection: boolean): TBGRACustomBitmap; overload; virtual; abstract; 602 function FilterEmbossHighlight(FillSelection: boolean; BorderColor: TBGRAPixel): TBGRACustomBitmap; overload; virtual; abstract; 603 function FilterEmbossHighlight(FillSelection: boolean; BorderColor: TBGRAPixel; var Offset: TPoint): TBGRACustomBitmap; overload; virtual; abstract; 604 function FilterGrayscale: TBGRACustomBitmap; overload; virtual; abstract; 605 function FilterGrayscale(ABounds: TRect): TBGRACustomBitmap; overload; virtual; abstract; 606 function FilterNormalize(eachChannel: boolean = True): TBGRACustomBitmap; overload; virtual; abstract; 607 function FilterNormalize(ABounds: TRect; eachChannel: boolean = True): TBGRACustomBitmap; overload; virtual; abstract; 608 function FilterRotate(origin: TPointF; angle: single; correctBlur: boolean = false): TBGRACustomBitmap; virtual; abstract; 609 function FilterAffine(AMatrix: TAffineMatrix; correctBlur: boolean = false): TBGRACustomBitmap; virtual; abstract; 610 function FilterSphere: TBGRACustomBitmap; virtual; abstract; 611 function FilterTwirl(ACenter: TPoint; ARadius: Single; ATurn: Single=1; AExponent: Single=3): TBGRACustomBitmap; overload; virtual; abstract; 612 function FilterTwirl(ABounds: TRect; ACenter: TPoint; ARadius: Single; ATurn: Single=1; AExponent: Single=3): TBGRACustomBitmap; overload; virtual; abstract; 613 function FilterCylinder: TBGRACustomBitmap; virtual; abstract; 614 function FilterPlane: TBGRACustomBitmap; virtual; abstract; 615 616 //IBGRAScanner 617 function ScanAtIntegerExpanded(X,Y: integer): TExpandedPixel; override; 618 function ScanNextExpandedPixel: TExpandedPixel; override; 619 function ScanAtExpanded(X,Y: Single): TExpandedPixel; override; 620 function ProvidesScanline(ARect: TRect): boolean; override; 621 function GetScanlineAt(X, Y: integer): PBGRAPixel; override; 622 procedure ScanNextMaskChunk(var ACount: integer; out AMask: PByteMask; out AStride: integer); override; 623 function ScanAtIntegerMask(X,Y: integer): TByteMask; override; 624 function ScanAtMask(X,Y: Single): TByteMask; override; 625 end; 626 627type 628 TBGRABitmapAny = class of TBGRACustomBitmap; //used to create instances of the same type (see NewBitmap) 629 630var 631 BGRABitmapFactory : TBGRABitmapAny; 632{$ENDIF} 633 634{$IFDEF INCLUDE_IMPLEMENTATION} 635{$UNDEF INCLUDE_IMPLEMENTATION} 636function InternalGetImageBoundsWithin(ASourceBitmap: TBGRACustomBitmap; ASourceTexture: IBGRAScanner; 637 const ARect: TRect; Channels: TChannels; ANothingValue: Byte): TRect; 638var 639 minx, miny, maxx, maxy: integer; 640 xb, xb2, yb: integer; 641 p: PLongWord; 642 colorMask, colorZeros: LongWord; 643 actualRect: TRect; 644 pixelBuffer: TBGRAPixelBuffer; 645begin 646 pixelBuffer := nil; 647 if ASourceBitmap <> nil then 648 begin 649 actualRect := TRect.Intersect(ARect, rect(0,0,ASourceBitmap.Width,ASourceBitmap.Height)); 650 end 651 else if ASourceTexture <> nil then 652 begin 653 actualRect := ARect; 654 AllocateBGRAPixelBuffer(pixelBuffer, ARect.Right-ARect.Left) 655 end 656 else 657 begin 658 result := EmptyRect; 659 exit; 660 end; 661 maxx := actualRect.Left-1; 662 maxy := actualRect.Top-1; 663 minx := actualRect.Right; 664 miny := actualRect.Bottom; 665 colorMask := 0; 666 colorZeros := 0; 667 if cBlue in Channels then 668 begin 669 colorMask := colorMask or LongWord(BGRA(0,0,255,0)); 670 colorZeros:= colorZeros or LongWord(BGRA(0,0,ANothingValue,0)); 671 end; 672 if cGreen in Channels then 673 begin 674 colorMask := colorMask or LongWord(BGRA(0,255,0,0)); 675 colorZeros:= colorZeros or LongWord(BGRA(0,ANothingValue,0,0)); 676 end; 677 if cRed in Channels then 678 begin 679 colorMask := colorMask or LongWord(BGRA(255,0,0,0)); 680 colorZeros:= colorZeros or LongWord(BGRA(ANothingValue,0,0,0)); 681 end; 682 if cAlpha in Channels then 683 begin 684 colorMask := colorMask or LongWord(BGRA(0,0,0,255)); 685 colorZeros:= colorZeros or LongWord(BGRA(0,0,0,ANothingValue)); 686 end; 687 colorMask := NtoLE(colorMask); 688 colorZeros := NtoLE(colorZeros); 689 for yb := actualRect.Top to actualRect.Bottom-1 do 690 begin 691 if ASourceBitmap <> nil then 692 p := PLongWord(ASourceBitmap.ScanLine[yb])+actualRect.Left 693 else 694 begin 695 p := @pixelBuffer[0]; 696 ASourceTexture.ScanMoveTo(actualRect.Left,actualRect.Top); 697 ASourceTexture.ScanPutPixels(PBGRAPixel(p),ARect.Right-ARect.Left, dmSet); 698 end; 699 for xb := actualRect.Left to actualRect.Right - 1 do 700 begin 701 if (p^ and colorMask) <> colorZeros then 702 begin 703 if xb < minx then 704 minx := xb; 705 if yb < miny then 706 miny := yb; 707 if xb > maxx then 708 maxx := xb; 709 if yb > maxy then 710 maxy := yb; 711 712 inc(p, actualRect.Right-1-xb); 713 for xb2 := actualRect.Right-1 downto xb+1 do 714 begin 715 if (p^ and colorMask) <> colorZeros then 716 begin 717 if xb2 > maxx then 718 maxx := xb2; 719 break; 720 end; 721 dec(p); 722 end; 723 break; 724 end; 725 Inc(p); 726 end; 727 end; 728 if minx > maxx then 729 begin 730 Result.left := 0; 731 Result.top := 0; 732 Result.right := 0; 733 Result.bottom := 0; 734 end 735 else 736 begin 737 Result.left := minx; 738 Result.top := miny; 739 Result.right := maxx + 1; 740 Result.bottom := maxy + 1; 741 end; 742end; 743 744{ TBGRACustomBitmap } 745 746function TBGRACustomBitmap.GetFontAntialias: Boolean; 747begin 748 result := FontQuality <> fqSystem; 749end; 750 751procedure TBGRACustomBitmap.SetFontAntialias(const AValue: Boolean); 752begin 753 if AValue and not FontAntialias then 754 FontQuality := fqFineAntialiasing 755 else if not AValue and (FontQuality <> fqSystem) then 756 FontQuality := fqSystem; 757end; 758 759procedure TBGRACustomBitmap.SetXorMask(AValue: TBGRACustomBitmap); 760begin 761 if FXorMask=AValue then Exit; 762 if (AValue.Width <> Width) or (AValue.Height <> Height) then 763 raise exception.Create('Dimension mismatch'); 764 DiscardXorMask; 765 FXorMask:=AValue; 766end; 767 768procedure TBGRACustomBitmap.Init; 769begin 770 inherited Init; 771 ScanMaskChannel:= cGreen; 772end; 773 774function TBGRACustomBitmap.GetFontRightToLeftFor(AText: string): boolean; 775begin 776 case FontBidiMode of 777 fbmAuto: result := IsRightToLeftUTF8(AText); 778 fbmRightToLeft: result := true; 779 else 780 {fbmLeftToRight} 781 result := false; 782 end; 783end; 784 785function TBGRACustomBitmap.NewBitmap: TBGRACustomBitmap; 786begin 787 Result:=inherited NewBitmap as TBGRACustomBitmap; 788end; 789 790function TBGRACustomBitmap.NewBitmap(AWidth, AHeight: integer): TBGRACustomBitmap; 791begin 792 Result:=inherited NewBitmap(AWidth, AHeight) as TBGRACustomBitmap; 793end; 794 795function TBGRACustomBitmap.NewBitmap(AWidth, AHeight: integer; 796 const Color: TBGRAPixel): TBGRACustomBitmap; 797begin 798 Result:=inherited NewBitmap(AWidth, AHeight, Color) as TBGRACustomBitmap; 799end; 800 801function TBGRACustomBitmap.NewBitmap(AWidth, AHeight: integer; AColor: Pointer 802 ): TBGRACustomBitmap; 803begin 804 Result:=inherited NewBitmap(AWidth, AHeight, AColor) as TBGRACustomBitmap; 805end; 806 807function TBGRACustomBitmap.InternalNew: TBGRACustomBitmap; 808begin 809 Result:= BGRABitmapFactory.Create; 810end; 811 812procedure TBGRACustomBitmap.DiscardXorMask; 813begin 814 if Assigned(FXorMask) then 815 begin 816 if FXorMask is TBGRACustomBitmap then 817 begin 818 TBGRACustomBitmap(FXorMask).FreeReference; 819 FXorMask := nil; 820 end else 821 FreeAndNil(FXorMask); 822 end; 823end; 824 825procedure TBGRACustomBitmap.NeedXorMask; 826begin 827 if FXorMask = nil then 828 FXorMask := BGRABitmapFactory.Create(Width,Height); 829end; 830 831function TBGRACustomBitmap.NewReference: TBGRACustomBitmap; 832begin 833 result := TBGRACustomBitmap(inherited NewReference); 834end; 835 836function TBGRACustomBitmap.GetUnique: TBGRACustomBitmap; 837begin 838 result := TBGRACustomBitmap(inherited GetUnique); 839end; 840 841function TBGRACustomBitmap.Duplicate(DuplicateProperties: Boolean): TBGRACustomBitmap; 842begin 843 result := TBGRACustomBitmap(inherited Duplicate(DuplicateProperties)); 844end; 845 846function TBGRACustomBitmap.Duplicate(DuplicateProperties, 847 DuplicateXorMask: Boolean): TBGRACustomBitmap; 848begin 849 result := Duplicate(DuplicateProperties); 850 if DuplicateXorMask and Assigned(XorMask) then 851 result.XorMask := FXorMask.Duplicate(True); 852end; 853 854procedure TBGRACustomBitmap.CopyPropertiesTo(ABitmap: TCustomUniversalBitmap); 855var 856 other: TBGRACustomBitmap; 857begin 858 inherited CopyPropertiesTo(ABitmap); 859 if ABitmap is TBGRACustomBitmap then 860 begin 861 other := TBGRACustomBitmap(ABitmap); 862 other.CanvasOpacity := CanvasOpacity; 863 other.CanvasDrawModeFP := CanvasDrawModeFP; 864 other.PenStyle := PenStyle; 865 other.CustomPenStyle := CustomPenStyle; 866 other.FontName := FontName; 867 other.FontHeight := FontHeight; 868 other.FontStyle := FontStyle; 869 other.FontQuality := FontQuality; 870 other.FontOrientation := FontOrientation; 871 other.FontVerticalAnchor:= FontVerticalAnchor; 872 other.FontBidiMode:= FontBidiMode; 873 other.LineCap := LineCap; 874 other.JoinStyle := JoinStyle; 875 other.ResampleFilter := ResampleFilter; 876 other.ScanInterpolationFilter:= ScanInterpolationFilter; 877 other.HotSpot := HotSpot; 878 end; 879end; 880 881function TBGRACustomBitmap.GetPart(const ARect: TRect): TBGRACustomBitmap; 882begin 883 result := TBGRACustomBitmap(inherited GetPart(ARect)); 884end; 885 886function TBGRACustomBitmap.CreateBrushTexture(ABrushStyle: TBrushStyle; 887 APatternColor, ABackgroundColor: TBGRAPixel; AWidth: integer; 888 AHeight: integer; APenWidth: single): TBGRACustomBitmap; 889begin 890 result := TBGRACustomBitmap(inherited CreateBrushTexture(ABrushStyle, APatternColor, ABackgroundColor, AWidth,AHeight,APenWidth)); 891end; 892 893procedure TBGRACustomBitmap.SetSize(AWidth, AHeight: integer); 894begin 895 if (AWidth <> Width) or (AHeight <> Height) then 896 begin 897 inherited SetSize(AWidth, AHeight); 898 DiscardXorMask; 899 end; 900end; 901 902procedure TBGRACustomBitmap.InternalArc(cx, cy, rx, ry: single; 903 const StartPoint, EndPoint: TPointF; ABorderColor: TBGRAPixel; w: single; AFillColor: TBGRAPixel; AOptions: TArcOptions; 904 ADrawChord: boolean; ATexture: IBGRAScanner); 905var angle1,angle2: single; 906begin 907 if (rx = 0) or (ry = 0) then exit; 908 angle1 := arctan2(-(StartPoint.y-cy)/ry,(StartPoint.x-cx)/rx); 909 angle2 := arctan2(-(EndPoint.y-cy)/ry,(EndPoint.x-cx)/rx); 910 if angle1 = angle2 then angle2 := angle1+2*Pi; 911 InternalArc(cx,cy,rx,ry, angle1,angle2, 912 ABorderColor,w,AFillColor, AOptions, ADrawChord, ATexture); 913end; 914 915procedure TBGRACustomBitmap.InternalArcInRect(r: TRect; StartAngleRad, 916 EndAngleRad: Single; ABorderColor: TBGRAPixel; w: single; AFillColor: TBGRAPixel; AOptions: TArcOptions; 917 ADrawChord: boolean; ATexture: IBGRAScanner); 918var 919 temp: LongInt; 920begin 921 if r.right = r.left then exit; 922 if r.bottom = r.top then exit; 923 if r.right < r.left then 924 begin 925 temp := r.left; 926 r.left := r.right; 927 r.right := temp; 928 end; 929 if r.Bottom < r.Top then 930 begin 931 temp := r.Top; 932 r.Top := r.Bottom; 933 r.Bottom := temp; 934 end; 935 InternalArc((r.left+r.right-1)/2,(r.top+r.bottom-1)/2, 936 (r.right-r.left-1)/2,(r.bottom-r.top-1)/2, 937 StartAngleRad,EndAngleRad, 938 ABorderColor,w,AFillColor, 939 AOptions, ADrawChord, ATexture); 940end; 941 942procedure TBGRACustomBitmap.InternalFillArcInRect(r: TRect; StartAngleRad, 943 EndAngleRad: Single; AFillColor: TBGRAPixel; AOptions: TArcOptions; 944 ATexture: IBGRAScanner); 945var 946 temp: LongInt; 947begin 948 if r.right = r.left then exit; 949 if r.bottom = r.top then exit; 950 if r.right < r.left then 951 begin 952 temp := r.left; 953 r.left := r.right; 954 r.right := temp; 955 end; 956 if r.Bottom < r.Top then 957 begin 958 temp := r.Top; 959 r.Top := r.Bottom; 960 r.Bottom := temp; 961 end; 962 InternalArc((r.left+r.right-1)/2,(r.top+r.bottom-1)/2, 963 (r.right-r.left)/2,(r.bottom-r.top)/2, 964 StartAngleRad,EndAngleRad, 965 BGRAPixelTransparent,0,AFillColor, 966 AOptions, False, ATexture); 967end; 968 969procedure TBGRACustomBitmap.DrawPixel(x, y: int32or64; const c: TBGRAPixel; 970 ADrawMode: TDrawMode); 971begin 972 case ADrawMode of 973 dmSet: SetPixel(x,y,c); 974 dmSetExceptTransparent: if c.alpha = 255 then SetPixel(x,y,c); 975 dmLinearBlend: FastBlendPixel(x,y,c); 976 dmDrawWithTransparency: DrawPixel(x,y,c); 977 dmXor: XorPixel(x,y,c); 978 end; 979end; 980 981procedure TBGRACustomBitmap.LoadFromStream(AStream: TStream; 982 AHandler: TFPCustomImageReader; AOptions: TBGRALoadingOptions); 983var 984 OldDrawMode: TDrawMode; 985begin 986 { LoadFromStream uses TFPCustomImage routine, which uses 987 Colors property to access pixels. That's why the 988 FP drawing mode is temporarily changed to load 989 bitmaps properly } 990 OldDrawMode := CanvasDrawModeFP; 991 CanvasDrawModeFP := dmSet; 992 DiscardXorMask; 993 try 994 inherited LoadFromStream(AStream, AHandler, AOptions); 995 finally 996 CanvasDrawModeFP := OldDrawMode; 997 end; 998end; 999 1000{ Look for a pixel considering the bitmap is repeated in both directions } 1001procedure TBGRACustomBitmap.DrawHorizLine(x, y, x2: int32or64; 1002 texture: IBGRAScanner); 1003begin 1004 HorizLine(x,y,x2,texture,dmDrawWithTransparency); 1005end; 1006 1007procedure TBGRACustomBitmap.Arc(cx, cy, rx, ry: single; const StartPoint, 1008 EndPoint: TPointF; AColor: TBGRAPixel; w: single; ADrawChord: boolean; 1009 AFillColor: TBGRAPixel); 1010begin 1011 InternalArc(cx,cy,rx,ry,StartPoint,EndPoint,AColor,w,AFillColor,[aoFillPath],ADrawChord); 1012end; 1013 1014procedure TBGRACustomBitmap.Arc(cx, cy, rx, ry: single; StartAngleRad, 1015 EndAngleRad: Single; AColor: TBGRAPixel; w: single; ADrawChord: boolean; 1016 AFillColor: TBGRAPixel); 1017begin 1018 InternalArc(cx,cy,rx,ry,StartAngleRad,EndAngleRad,AColor,w,AFillColor,[aoFillPath],ADrawChord); 1019end; 1020 1021procedure TBGRACustomBitmap.FillChord(cx, cy, rx, ry: single; const StartPoint, 1022 EndPoint: TPointF; AFillColor: TBGRAPixel); 1023begin 1024 InternalArc(cx,cy,rx,ry,StartPoint,EndPoint,BGRAPixelTransparent,0,AFillColor,[aoFillPath]); 1025end; 1026 1027procedure TBGRACustomBitmap.FillChord(cx, cy, rx, ry: single; StartAngleRad, 1028 EndAngleRad: Single; AFillColor: TBGRAPixel); 1029begin 1030 InternalArc(cx,cy,rx,ry,StartAngleRad,EndAngleRad,BGRAPixelTransparent,0,AFillColor,[aoFillPath]); 1031end; 1032 1033procedure TBGRACustomBitmap.FillChord(cx, cy, rx, ry: single; const StartPoint, 1034 EndPoint: TPointF; texture: IBGRAScanner); 1035begin 1036 InternalArc(cx,cy,rx,ry,StartPoint,EndPoint,BGRAPixelTransparent,0,BGRAWhite,[aoFillPath],False,texture); 1037end; 1038 1039procedure TBGRACustomBitmap.FillChord(cx, cy, rx, ry: single; StartAngleRad, 1040 EndAngleRad: Single; texture: IBGRAScanner); 1041begin 1042 InternalArc(cx,cy,rx,ry,StartAngleRad,EndAngleRad,BGRAPixelTransparent,0,BGRAWhite,[aoFillPath],False,texture); 1043end; 1044 1045procedure TBGRACustomBitmap.FillChordInRect(const ARect: TRect; StartAngleRad, 1046 EndAngleRad: Single; AFillColor: TBGRAPixel); 1047begin 1048 InternalFillArcInRect(ARect,StartAngleRad,EndAngleRad,AFillColor,[aoFillPath]); 1049end; 1050 1051procedure TBGRACustomBitmap.FillChordInRect(const ARect: TRect; StartAngleRad, 1052 EndAngleRad: Single; texture: IBGRAScanner); 1053begin 1054 InternalFillArcInRect(ARect,StartAngleRad,EndAngleRad,BGRAWhite,[aoFillPath],texture); 1055end; 1056 1057procedure TBGRACustomBitmap.Pie(cx, cy, rx, ry: single; const StartPoint, 1058 EndPoint: TPointF; AColor: TBGRAPixel; w: single; AFillColor: TBGRAPixel); 1059begin 1060 InternalArc(cx,cy,rx,ry,StartPoint,EndPoint,AColor,w,AFillColor,[aoFillPath,aoPie]); 1061end; 1062 1063procedure TBGRACustomBitmap.Pie(cx, cy, rx, ry: single; StartAngleRad, 1064 EndAngleRad: Single; AColor: TBGRAPixel; w: single; AFillColor: TBGRAPixel); 1065begin 1066 InternalArc(cx,cy,rx,ry,StartAngleRad,EndAngleRad,AColor,w,AFillColor,[aoFillPath,aoPie]); 1067end; 1068 1069procedure TBGRACustomBitmap.FillPie(cx, cy, rx, ry: single; const StartPoint, 1070 EndPoint: TPointF; AFillColor: TBGRAPixel); 1071begin 1072 InternalArc(cx,cy,rx,ry,StartPoint,EndPoint,BGRAPixelTransparent,0,AFillColor,[aoFillPath,aoPie]); 1073end; 1074 1075procedure TBGRACustomBitmap.FillPie(cx, cy, rx, ry: single; StartAngleRad, 1076 EndAngleRad: Single; AFillColor: TBGRAPixel); 1077begin 1078 InternalArc(cx,cy,rx,ry,StartAngleRad,EndAngleRad,BGRAPixelTransparent,0,AFillColor,[aoFillPath,aoPie]); 1079end; 1080 1081procedure TBGRACustomBitmap.FillPie(cx, cy, rx, ry: single; const StartPoint, 1082 EndPoint: TPointF; texture: IBGRAScanner); 1083begin 1084 InternalArc(cx,cy,rx,ry,StartPoint,EndPoint,BGRAPixelTransparent,0,BGRAWhite,[aoFillPath,aoPie],False,texture); 1085end; 1086 1087procedure TBGRACustomBitmap.FillPie(cx, cy, rx, ry: single; StartAngleRad, 1088 EndAngleRad: Single; texture: IBGRAScanner); 1089begin 1090 InternalArc(cx,cy,rx,ry,StartAngleRad,EndAngleRad,BGRAPixelTransparent,0,BGRAWhite,[aoFillPath,aoPie],False,texture); 1091end; 1092 1093procedure TBGRACustomBitmap.FillPieInRect(const ARect: TRect; StartAngleRad, 1094 EndAngleRad: Single; AFillColor: TBGRAPixel); 1095begin 1096 InternalFillArcInRect(ARect,StartAngleRad,EndAngleRad,AFillColor,[aoFillPath,aoPie]); 1097end; 1098 1099procedure TBGRACustomBitmap.FillPieInRect(const ARect: TRect; StartAngleRad, 1100 EndAngleRad: Single; texture: IBGRAScanner); 1101begin 1102 InternalFillArcInRect(ARect,StartAngleRad,EndAngleRad,BGRAWhite,[aoFillPath,aoPie],texture); 1103end; 1104 1105{ Following functions are defined for convenience } 1106procedure TBGRACustomBitmap.RectangleWithin(x1, y1, x2, y2: single; 1107 ABorderColor: TBGRAPixel; w: single; AFillColor: TBGRAPixel; 1108 APixelCenteredCoordinates: boolean); 1109begin 1110 if not APixelCenteredCoordinates then 1111 begin 1112 DecF(x1, 0.5); 1113 DecF(y1, 0.5); 1114 DecF(x2, 0.5); 1115 DecF(y2, 0.5); 1116 end; 1117 RectangleAntialias(x1+w*0.5,y1+w*0.5,x2-w*0.5,y2-w*0.5, ABorderColor, w, AFillColor); 1118end; 1119 1120procedure TBGRACustomBitmap.RectangleWithin(r: TRect; ABorderColor: TBGRAPixel; 1121 w: single; AFillColor: TBGRAPixel); 1122begin 1123 RectangleWithin(r.left,r.top,r.right,r.bottom,ABorderColor,w,AFillColor,false); 1124end; 1125 1126procedure TBGRACustomBitmap.FillRect(r: TRect; texture: IBGRAScanner; 1127 mode: TDrawMode; ditheringAlgorithm: TDitheringAlgorithm); 1128begin 1129 FillRect(r.Left,r.Top,r.Right,r.Bottom, texture, mode, ditheringAlgorithm); 1130end; 1131 1132procedure TBGRACustomBitmap.FillRect(r: TRect; texture: IBGRAScanner; 1133 mode: TDrawMode; AScanOffset: TPoint; ditheringAlgorithm: TDitheringAlgorithm); 1134begin 1135 FillRect(r.Left,r.Top,r.Right,r.Bottom, texture, mode, AScanOffset, ditheringAlgorithm); 1136end; 1137 1138procedure TBGRACustomBitmap.FillRect(x, y, x2, y2: integer; 1139 texture: IBGRAScanner; mode: TDrawMode; 1140 ditheringAlgorithm: TDitheringAlgorithm); 1141begin 1142 FillRect(x,y,x2,y2,texture,mode,Point(0,0),ditheringAlgorithm); 1143end; 1144 1145procedure TBGRACustomBitmap.TextOutCurved(APath: IBGRAPath; const sUTF8: string; 1146 AColor: TBGRAPixel; AAlign: TAlignment; ALetterSpacing: single); 1147var cursor: TBGRACustomPathCursor; 1148begin 1149 cursor := APath.getCursor; 1150 if cursor = nil then exit; 1151 case AAlign of 1152 taCenter: cursor.Position := cursor.PathLength*0.5; 1153 taRightJustify: cursor.Position:= cursor.PathLength; 1154 end; 1155 TextOutCurved(cursor, sUTF8, AColor, AAlign, ALetterSpacing); 1156 cursor.free; 1157end; 1158 1159procedure TBGRACustomBitmap.TextOutCurved(APath: IBGRAPath; const sUTF8: string; 1160 ATexture: IBGRAScanner; AAlign: TAlignment; ALetterSpacing: single); 1161var cursor: TBGRACustomPathCursor; 1162begin 1163 cursor := APath.getCursor; 1164 if cursor = nil then exit; 1165 case AAlign of 1166 taCenter: cursor.Position := cursor.PathLength*0.5; 1167 taRightJustify: cursor.Position:= cursor.PathLength; 1168 end; 1169 TextOutCurved(cursor, sUTF8, ATexture, AAlign, ALetterSpacing); 1170 cursor.free; 1171end; 1172 1173procedure TBGRACustomBitmap.TextMultiline(x, y: single; const sUTF8: string; 1174 c: TBGRAPixel; AAlign: TBidiTextAlignment; AVertAlign: TTextLayout; AParagraphSpacing: single); 1175begin 1176 TextMultiline(x, y, EmptySingle, sUTF8, c, AAlign, AVertAlign, AParagraphSpacing); 1177end; 1178 1179procedure TBGRACustomBitmap.TextMultiline(x, y: single; const sUTF8: string; 1180 ATexture: IBGRAScanner; AAlign: TBidiTextAlignment; AVertAlign: TTextLayout; AParagraphSpacing: single); 1181begin 1182 TextMultiline(x, y, EmptySingle, sUTF8, ATexture, AAlign, AVertAlign, AParagraphSpacing); 1183end; 1184 1185procedure TBGRACustomBitmap.TextOut(x, y: single; const sUTF8: string; c: TBGRAPixel; 1186 align: TAlignment); 1187begin 1188 TextOut(x,y,sUTF8,c,align, GetFontRightToLeftFor(sUTF8)); 1189end; 1190 1191procedure TBGRACustomBitmap.TextOut(x, y: single; const sUTF8: string; 1192 texture: IBGRAScanner; align: TAlignment); 1193begin 1194 TextOut(x,y,sUTF8,texture,align, GetFontRightToLeftFor(sUTF8)); 1195end; 1196 1197{ Draw the UTF8 encoded string, (x,y) being the top-left corner. The color c is used to fill the text. 1198 The value of FontOrientation is taken into account, so that the text may be rotated. } 1199procedure TBGRACustomBitmap.TextOut(x, y: single; const sUTF8: string; c: TBGRAPixel); 1200begin 1201 TextOut(x, y, sUTF8, c, taLeftJustify); 1202end; 1203 1204procedure TBGRACustomBitmap.TextOut(x, y: single; const sUTF8: string; c: TBGRAPixel; 1205 ARightToLeft: boolean); 1206begin 1207 TextOut(x, y, sUTF8, c, taLeftJustify, ARightToLeft); 1208end; 1209 1210{ Draw the UTF8 encoded string, (x,y) being the top-left corner. The color c is used to fill the text. 1211 The value of FontOrientation is taken into account, so that the text may be rotated. } 1212procedure TBGRACustomBitmap.TextOut(x, y: single; const sUTF8: string; c: TColor); 1213begin 1214 TextOut(x, y, sUTF8, ColorToBGRA(c)); 1215end; 1216 1217procedure TBGRACustomBitmap.TextOut(x, y: single; const sUTF8: string; c: TColor; 1218 ARightToLeft: boolean); 1219begin 1220 TextOut(x, y, sUTF8, ColorToBGRA(c), ARightToLeft); 1221end; 1222 1223{ Draw the UTF8 encoded string, (x,y) being the top-left corner. The texture is used to fill the text. 1224 The value of FontOrientation is taken into account, so that the text may be rotated. } 1225procedure TBGRACustomBitmap.TextOut(x, y: single; const sUTF8: string; 1226 texture: IBGRAScanner); 1227begin 1228 TextOut(x, y, sUTF8, texture, taLeftJustify); 1229end; 1230 1231procedure TBGRACustomBitmap.TextOut(x, y: single; const sUTF8: string; 1232 texture: IBGRAScanner; ARightToLeft: boolean); 1233begin 1234 TextOut(x, y, sUTF8, texture, taLeftJustify, ARightToLeft); 1235end; 1236 1237procedure TBGRACustomBitmap.TextOutAngle(x, y: single; 1238 orientationTenthDegCCW: integer; const sUTF8: string; c: TBGRAPixel); 1239begin 1240 TextOutAngle(x,y, orientationTenthDegCCW, sUTF8,c,taLeftJustify); 1241end; 1242 1243procedure TBGRACustomBitmap.TextOutAngle(x, y: single; 1244 orientationTenthDegCCW: integer; const sUTF8: string; c: TBGRAPixel; 1245 align: TAlignment); 1246begin 1247 TextOutAngle(x,y, orientationTenthDegCCW, sUTF8,c,align, GetFontRightToLeftFor(sUTF8)); 1248end; 1249 1250procedure TBGRACustomBitmap.TextOutAngle(x, y: single; 1251 orientationTenthDegCCW: integer; const sUTF8: string; texture: IBGRAScanner); 1252begin 1253 TextOutAngle(x,y, orientationTenthDegCCW, sUTF8,texture,taLeftJustify); 1254end; 1255 1256procedure TBGRACustomBitmap.TextOutAngle(x, y: single; 1257 orientationTenthDegCCW: integer; const sUTF8: string; texture: IBGRAScanner; 1258 align: TAlignment); 1259begin 1260 TextOutAngle(x,y, orientationTenthDegCCW, sUTF8,texture,align, GetFontRightToLeftFor(sUTF8)); 1261end; 1262 1263{ Draw the UTF8 encoded string in the rectangle ARect. Text is wrapped if necessary. 1264 The position depends on the specified horizontal alignment halign and vertical alignement valign. 1265 The color c is used to fill the text. No rotation is applied. } 1266procedure TBGRACustomBitmap.TextRect(ARect: TRect; const sUTF8: string; 1267 halign: TAlignment; valign: TTextLayout; c: TBGRAPixel); 1268var 1269 style: TTextStyle; 1270 sUTF8bidi: String; 1271begin 1272 {$hints off} 1273 FillChar(style,sizeof(style),0); 1274 {$hints on} 1275 style.Alignment := halign; 1276 style.Layout := valign; 1277 style.Wordbreak := true; 1278 style.ShowPrefix := false; 1279 style.Clipping := false; 1280 style.RightToLeft := GetFontRightToLeftFor(sUTF8); 1281 if FontBidiMode = fbmAuto then 1282 sUTF8bidi := AddParagraphBidiUTF8(sUTF8, style.RightToLeft) 1283 else sUTF8bidi := sUTF8; 1284 TextRect(ARect, ARect.Left, ARect.Top, sUTF8bidi, style, c); 1285end; 1286 1287{ Draw the UTF8 encoded string in the rectangle ARect. Text is wrapped if necessary. 1288 The position depends on the specified horizontal alignment halign and vertical alignement valign. 1289 The texture is used to fill the text. No rotation is applied. } 1290procedure TBGRACustomBitmap.TextRect(ARect: TRect; const sUTF8: string; 1291 halign: TAlignment; valign: TTextLayout; texture: IBGRAScanner); 1292var 1293 style: TTextStyle; 1294 sUTF8bidi: String; 1295begin 1296 {$hints off} 1297 FillChar(style,sizeof(style),0); 1298 {$hints on} 1299 style.Alignment := halign; 1300 style.Layout := valign; 1301 style.Wordbreak := true; 1302 style.ShowPrefix := false; 1303 style.Clipping := false; 1304 style.RightToLeft := GetFontRightToLeftFor(sUTF8); 1305 if FontBidiMode = fbmAuto then 1306 sUTF8bidi := AddParagraphBidiUTF8(sUTF8, style.RightToLeft) 1307 else sUTF8bidi := sUTF8; 1308 TextRect(ARect,ARect.Left,ARect.Top,sUTF8bidi,style,texture); 1309end; 1310 1311function TBGRACustomBitmap.ComputeEllipse(x, y, rx, ry: single): ArrayOfTPointF; 1312begin 1313 result := ComputeEllipseContour(x,y,rx,ry); 1314end; 1315 1316function TBGRACustomBitmap.ComputeEllipse(x, y, rx, ry, w: single 1317 ): ArrayOfTPointF; 1318begin 1319 result := ComputeEllipseBorder(x,y,rx,ry,w); 1320end; 1321 1322procedure TBGRACustomBitmap.Fill(texture: IBGRAScanner); 1323begin 1324 FillRect(ClipRect, texture, dmSet); 1325end; 1326 1327procedure TBGRACustomBitmap.Fill(texture: IBGRAScanner; mode: TDrawMode); 1328begin 1329 FillRect(ClipRect, texture, mode); 1330end; 1331 1332procedure TBGRACustomBitmap.FloodFill(X, Y: integer; Color: TBGRAPixel; 1333 mode: TFloodfillMode; Tolerance: byte); 1334begin 1335 ParallelFloodFill(X,Y, Self, Color, mode, Tolerance); 1336end; 1337 1338procedure TBGRACustomBitmap.FloodFill(X, Y: integer; 1339 const Brush: TUniversalBrush; Progressive: boolean; ToleranceW: Word); 1340begin 1341 ParallelFloodFill(X,Y, Self, Brush, Progressive, ToleranceW); 1342end; 1343 1344procedure TBGRACustomBitmap.DrawPart(ARect: TRect; ACanvas: TCanvas; x, 1345 y: integer; Opaque: boolean); 1346var 1347 partial: TBGRACustomBitmap; 1348begin 1349 if (ARect.Left = 0) and (ARect.Top = 0) and (ARect.Right = Width) and (ARect.Bottom = Height) then 1350 Draw(ACanvas, x,y, Opaque) 1351 else 1352 begin 1353 partial := GetPart(ARect); 1354 if partial <> nil then 1355 begin 1356 partial.Draw(ACanvas, x, y, Opaque); 1357 partial.Free; 1358 end; 1359 end; 1360end; 1361 1362procedure TBGRACustomBitmap.DrawPart(ARect: TRect; ACanvas: TCanvas; 1363 ATargetRect: TRect; Opaque: boolean); 1364var 1365 partial: TBGRACustomBitmap; 1366begin 1367 if (ARect.Left = 0) and (ARect.Top = 0) and (ARect.Right = Width) and (ARect.Bottom = Height) then 1368 Draw(ACanvas, ATargetRect, Opaque) 1369 else 1370 begin 1371 partial := GetPart(ARect); 1372 if partial <> nil then 1373 begin 1374 partial.Draw(ACanvas, ATargetRect, Opaque); 1375 partial.Free; 1376 end; 1377 end; 1378end; 1379 1380procedure TBGRACustomBitmap.PutImage(x, y: integer; Source: TBitmap; 1381 mode: TDrawMode; AOpacity: byte); 1382var bgra: TBGRACustomBitmap; 1383begin 1384 bgra := BGRABitmapFactory.create(Source); 1385 PutImage(x,y, bgra, mode, AOpacity); 1386 bgra.free; 1387end; 1388 1389procedure TBGRACustomBitmap.StretchPutImage(ARect: TRect; Source: TBitmap; 1390 mode: TDrawMode; AOpacity: byte); 1391var bgra: TBGRACustomBitmap; 1392begin 1393 bgra := BGRABitmapFactory.create(Source); 1394 StretchPutImage(ARect, bgra, mode, AOpacity); 1395 bgra.free; 1396end; 1397 1398procedure TBGRACustomBitmap.StretchPutImageProportionally(ARect: TRect; 1399 AHorizAlign: TAlignment; AVertAlign: TTextLayout; Source: TBGRACustomBitmap; 1400 mode: TDrawMode; AOpacity: byte); 1401var 1402 ratio: single; 1403 imgRect: TRect; 1404begin 1405 if (Source.Width = 0) or (Source.Height = 0) then exit; 1406 if (ARect.Width <= 0) or (ARect.Height <= 0) then exit; 1407 1408 ratio := min(ARect.Width/Source.Width, ARect.Height/Source.Height); 1409 imgRect := RectWithSize(ARect.Left,ARect.Top, round(Source.Width*ratio), round(Source.Height*ratio)); 1410 case AHorizAlign of 1411 taCenter: imgRect.Offset((ARect.Width-imgRect.Width) div 2, 0); 1412 taRightJustify: imgRect.Offset(ARect.Width-imgRect.Width, 0); 1413 end; 1414 case AVertAlign of 1415 tlCenter: imgRect.Offset(0,(ARect.Height-imgRect.Height) div 2); 1416 tlBottom: imgRect.Offset(0,ARect.Height-imgRect.Height); 1417 end; 1418 StretchPutImage(imgRect, Source, mode, AOpacity); 1419end; 1420 1421procedure TBGRACustomBitmap.PutImageSubpixel(x, y: single; Source: TBGRACustomBitmap; AOpacity: byte); 1422begin 1423 PutImageAngle(x,y,source,0,0,0,AOpacity); 1424end; 1425 1426procedure TBGRACustomBitmap.PutImagePart(x, y: integer; 1427 Source: TBGRACustomBitmap; SourceRect: TRect; mode: TDrawMode; AOpacity: byte); 1428var w,h,sourcex,sourcey,nx,ny,xb,yb,destx,desty: integer; 1429 oldClip,newClip: TRect; 1430begin 1431 if (Source = nil) or (AOpacity = 0) then exit; 1432 w := SourceRect.Right-SourceRect.Left; 1433 h := SourceRect.Bottom-SourceRect.Top; 1434 if (w <= 0) or (h <= 0) or (Source.Width = 0) or (Source.Height = 0) then exit; 1435 sourcex := PositiveMod(SourceRect.Left, Source.Width); 1436 sourcey := PositiveMod(SourceRect.Top, Source.Height); 1437 nx := (sourceX+w + Source.Width-1) div Source.Width; 1438 ny := (sourceY+h + Source.Height-1) div Source.Height; 1439 1440 oldClip := ClipRect; 1441 newClip := rect(x,y,x+w,y+h); 1442 newClip.Intersect(oldClip); 1443 if newClip.IsEmpty then exit; 1444 1445 ClipRect := newClip; 1446 1447 desty := y-sourcey; 1448 for yb := 0 to ny-1 do 1449 begin 1450 destx := x-sourcex; 1451 for xb := 0 to nx-1 do 1452 begin 1453 self.PutImage(destx,desty,Source,mode,AOpacity); 1454 inc(destx,Source.Width); 1455 end; 1456 inc(desty,Source.Height); 1457 end; 1458 1459 ClipRect := oldClip; 1460end; 1461 1462procedure TBGRACustomBitmap.PutImageAffine(Origin, HAxis, VAxis: TPointF; 1463 Source: TBGRACustomBitmap; AOpacity: Byte; ACorrectBlur: Boolean); 1464begin 1465 if ACorrectBlur then 1466 PutImageAffine(Origin,HAxis,VAxis,Source,rfCosine,AOpacity) 1467 else 1468 PutImageAffine(Origin,HAxis,VAxis,Source,rfLinear,AOpacity); 1469end; 1470 1471procedure TBGRACustomBitmap.PutImageAffine(Origin, HAxis, VAxis: TPointF; 1472 Source: TBGRACustomBitmap; AResampleFilter: TResampleFilter; AOpacity: Byte); 1473begin 1474 if (Source = nil) or (Source.Width = 0) or (Source.Height = 0) or (AOpacity = 0) then exit; 1475 PutImageAffine(Origin,HAxis,VAxis,Source,GetImageAffineBounds(Origin,HAxis,VAxis,Source),AResampleFilter,dmDrawWithTransparency,AOpacity); 1476end; 1477 1478procedure TBGRACustomBitmap.PutImageAffine(Origin, HAxis, VAxis: TPointF; 1479 Source: TBGRACustomBitmap; AResampleFilter: TResampleFilter; 1480 AMode: TDrawMode; AOpacity: Byte); 1481begin 1482 if (Source = nil) or (Source.Width = 0) or (Source.Height = 0) or (AOpacity = 0) then exit; 1483 PutImageAffine(Origin,HAxis,VAxis,Source,GetImageAffineBounds(Origin,HAxis,VAxis,Source),AResampleFilter,AMode,AOpacity); 1484end; 1485 1486procedure TBGRACustomBitmap.PutImageAffine(Origin, HAxis, VAxis: TPointF; 1487 Source: TBGRACustomBitmap; AOutputBounds: TRect; 1488 AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte); 1489var m: TAffineMatrix; w,h: integer; 1490begin 1491 if (Source = nil) or (Source.Width = 0) or (Source.Height = 0) or (AOpacity = 0) then exit; 1492 if Source.Width < 2 then w := 2 else w := Source.Width; //avoid actual size of zero 1493 if Source.Height < 2 then h := 2 else h := Source.Height; 1494 m[1,1] := (HAxis.x-Origin.x)/(w-1); m[1,2] := (VAxis.x-Origin.x)/(h-1); m[1,3] := Origin.x; 1495 m[2,1] := (HAxis.y-Origin.y)/(w-1); m[2,2] := (VAxis.y-Origin.y)/(h-1); m[2,3] := Origin.y; 1496 PutImageAffine(m,Source,AOutputBounds,AResampleFilter,AMode,AOpacity); 1497end; 1498 1499procedure TBGRACustomBitmap.PutImageAffine(Origin, HAxis, VAxis: TPointF; 1500 Source: TBGRACustomBitmap; AOutputBounds: TRect; AOpacity: Byte; 1501 ACorrectBlur: Boolean); 1502begin 1503 if ACorrectBlur then 1504 PutImageAffine(Origin,HAxis,VAxis,Source,AOutputBounds,rfCosine,dmDrawWithTransparency,AOpacity) 1505 else 1506 PutImageAffine(Origin,HAxis,VAxis,Source,AOutputBounds,rfLinear,dmDrawWithTransparency,AOpacity); 1507end; 1508 1509procedure TBGRACustomBitmap.PutImageAffine(AMatrix: TAffineMatrix; 1510 Source: TBGRACustomBitmap; AOpacity: Byte; ACorrectBlur: Boolean; APixelCenteredCoords: boolean); 1511begin 1512 if ACorrectBlur then 1513 PutImageAffine(AMatrix,Source,rfCosine,AOpacity,APixelCenteredCoords) 1514 else 1515 PutImageAffine(AMatrix,Source,rfLinear,AOpacity,APixelCenteredCoords); 1516end; 1517 1518procedure TBGRACustomBitmap.PutImageAffine(AMatrix: TAffineMatrix; 1519 Source: TBGRACustomBitmap; AResampleFilter: TResampleFilter; AOpacity: Byte; APixelCenteredCoords: boolean); 1520begin 1521 PutImageAffine(AMatrix, Source, AResampleFilter, dmDrawWithTransparency, AOpacity, APixelCenteredCoords); 1522end; 1523 1524procedure TBGRACustomBitmap.PutImageAffine(AMatrix: TAffineMatrix; 1525 Source: TBGRACustomBitmap; AResampleFilter: TResampleFilter; 1526 AMode: TDrawMode; AOpacity: Byte; APixelCenteredCoords: boolean); 1527begin 1528 if (Source = nil) or (Source.Width = 0) or (Source.Height = 0) or (AOpacity = 0) then exit; 1529 PutImageAffine(AMatrix, Source, GetImageAffineBounds(AMatrix,Source), 1530 AResampleFilter,AMode,AOpacity,APixelCenteredCoords); 1531end; 1532 1533procedure TBGRACustomBitmap.PutImageAffine(AMatrix: TAffineMatrix; 1534 Source: TBGRACustomBitmap; AOutputBounds: TRect; AOpacity: Byte; 1535 ACorrectBlur: Boolean; APixelCenteredCoords: boolean); 1536begin 1537 if ACorrectBlur then 1538 PutImageAffine(AMatrix,Source,AOutputBounds,rfCosine,dmDrawWithTransparency,AOpacity,APixelCenteredCoords) 1539 else 1540 PutImageAffine(AMatrix,Source,AOutputBounds,rfLinear,dmDrawWithTransparency,AOpacity,APixelCenteredCoords); 1541end; 1542 1543{ Returns the area that contains the affine transformed image } 1544function TBGRACustomBitmap.GetImageAffineBounds(Origin, HAxis, VAxis: TPointF; 1545 Source: TBGRACustomBitmap): TRect; 1546begin 1547 if Source = nil then 1548 result := EmptyRect 1549 else 1550 result := GetImageAffineBounds(Origin,HAxis,VAxis,Source.Width,Source.Height,Source.GetImageBounds); 1551end; 1552 1553function TBGRACustomBitmap.GetImageAffineBounds(Origin, HAxis, VAxis: TPointF; 1554 ASourceWidth, ASourceHeight: integer; const ASourceBounds: TRect; AClipOutput: boolean): TRect; 1555var m: TAffineMatrix; 1556begin 1557 if (ASourceWidth = 0) or (ASourceHeight = 0) then 1558 result := EmptyRect 1559 else 1560 begin 1561 if ASourceWidth < 2 then ASourceWidth := 2; //avoid division by zero by supposing a pixel size of 2 1562 if ASourceHeight < 2 then ASourceHeight := 2; //i.e. an actual size of 1 (cf pixel centered coordinates) 1563 m[1,1] := (HAxis.x-Origin.x)/(ASourceWidth-1); m[1,2] := (VAxis.x-Origin.x)/(ASourceHeight-1); m[1,3] := Origin.x; 1564 m[2,1] := (HAxis.y-Origin.y)/(ASourceWidth-1); m[2,2] := (VAxis.y-Origin.y)/(ASourceHeight-1); m[2,3] := Origin.y; 1565 result := GetImageAffineBounds(m, ASourceBounds, AClipOutput); 1566 end; 1567end; 1568 1569function TBGRACustomBitmap.GetImageAffineBounds(AMatrix: TAffineMatrix; 1570 Source: TBGRACustomBitmap; APixelCenteredCoords: boolean): TRect; 1571begin 1572 result := GetImageAffineBounds(AMatrix, Source.GetImageBounds, true, APixelCenteredCoords); 1573end; 1574 1575procedure TBGRACustomBitmap.PutImageAngle(x, y: single; 1576 Source: TBGRACustomBitmap; angle: single; AOutputBounds: TRect; 1577 imageCenterX: single; imageCenterY: single; AOpacity: Byte; 1578 ARestoreOffsetAfterRotation: boolean; ACorrectBlur: Boolean); 1579begin 1580 if ACorrectBlur then 1581 PutImageAngle(x,y,Source,angle,AOutputBounds,rfCosine,imageCenterX,imageCenterY,AOpacity,ARestoreOffsetAfterRotation) 1582 else 1583 PutImageAngle(x,y,Source,angle,AOutputBounds,rfLinear,imageCenterX,imageCenterY,AOpacity,ARestoreOffsetAfterRotation); 1584end; 1585 1586procedure TBGRACustomBitmap.PutImageAngle(x, y: single; 1587 Source: TBGRACustomBitmap; angle: single; imageCenterX: single; 1588 imageCenterY: single; AOpacity: Byte; ARestoreOffsetAfterRotation: boolean; ACorrectBlur: Boolean); 1589begin 1590 if ACorrectBlur then 1591 PutImageAngle(x,y,Source,angle,rfCosine,imageCenterX,imageCenterY,AOpacity,ARestoreOffsetAfterRotation) 1592 else 1593 PutImageAngle(x,y,Source,angle,rfLinear,imageCenterX,imageCenterY,AOpacity,ARestoreOffsetAfterRotation); 1594end; 1595 1596procedure TBGRACustomBitmap.PutImageAngle(x, y: single; 1597 Source: TBGRACustomBitmap; angle: single; AOutputBounds: TRect; 1598 AResampleFilter: TResampleFilter; imageCenterX: single; imageCenterY: single; AOpacity: Byte; 1599 ARestoreOffsetAfterRotation: boolean); 1600var 1601 Origin,HAxis,VAxis: TPointF; 1602begin 1603 if (source = nil) or (AOpacity=0) then exit; 1604 ComputeImageAngleAxes(x,y,source.Width,source.Height,angle,imageCenterX,imageCenterY,ARestoreOffsetAfterRotation, 1605 Origin,HAxis,VAxis); 1606 PutImageAffine(Origin,HAxis,VAxis,source,AOutputBounds,AResampleFilter,dmDrawWithTransparency,AOpacity); 1607end; 1608 1609procedure TBGRACustomBitmap.PutImageAngle(x, y: single; 1610 Source: TBGRACustomBitmap; angle: single; AResampleFilter: TResampleFilter; 1611 imageCenterX: single; imageCenterY: single; AOpacity: Byte; 1612 ARestoreOffsetAfterRotation: boolean); 1613var 1614 Origin,HAxis,VAxis: TPointF; 1615begin 1616 if (source = nil) or (AOpacity=0) then exit; 1617 ComputeImageAngleAxes(x,y,source.Width,source.Height,angle,imageCenterX,imageCenterY,ARestoreOffsetAfterRotation, 1618 Origin,HAxis,VAxis); 1619 PutImageAffine(Origin,HAxis,VAxis,source,AResampleFilter,AOpacity); 1620end; 1621 1622procedure TBGRACustomBitmap.ComputeImageAngleAxes(x, y, w, h, 1623 angle: single; imageCenterX, imageCenterY: single; 1624 ARestoreOffsetAfterRotation: boolean; out Origin, HAxis, VAxis: TPointF); 1625var 1626 cosa,sina: single; 1627 1628 { Compute rotated coordinates } 1629 function Coord(relX,relY: single): TPointF; 1630 begin 1631 DecF(relX, imageCenterX); 1632 DecF(relY, imageCenterY); 1633 result.x := relX*cosa - relY*sina+ x; 1634 result.y := relY*cosa + relX*sina+ y; 1635 if ARestoreOffsetAfterRotation then 1636 result.Offset(imageCenterX,imageCenterY); 1637 end; 1638 1639begin 1640 cosa := cos(-angle*Pi/180); 1641 sina := -sin(-angle*Pi/180); 1642 Origin := Coord(0,0); 1643 if w < 2 then w := 2; //when pixel size is 1, actual size is zero, so avoid that 1644 if h < 2 then h := 2; 1645 HAxis := Coord(w-1,0); 1646 VAxis := Coord(0,h-1); 1647end; 1648 1649function TBGRACustomBitmap.GetImageAngleBounds(x, y: single; 1650 Source: TBGRACustomBitmap; angle: single; imageCenterX: single; 1651 imageCenterY: single; ARestoreOffsetAfterRotation: boolean): TRect; 1652var 1653 cosa,sina: single; 1654 1655 { Compute rotated coordinates } 1656 function Coord(relX,relY: single): TPointF; 1657 begin 1658 DecF(relX, imageCenterX); 1659 DecF(relY, imageCenterY); 1660 result.x := relX*cosa - relY*sina + x; 1661 result.y := relY*cosa + relX*sina + y; 1662 if ARestoreOffsetAfterRotation then 1663 result.Offset(imageCenterX,imageCenterY); 1664 end; 1665 1666begin 1667 if (source = nil) then 1668 begin 1669 result := EmptyRect; 1670 exit; 1671 end; 1672 cosa := cos(-angle*Pi/180); 1673 sina := -sin(-angle*Pi/180); 1674 result := GetImageAffineBounds(Coord(0,0),Coord(source.Width,0),Coord(0,source.Height),source); 1675end; 1676 1677procedure TBGRACustomBitmap.Blend(AColor: TBGRAPixel; 1678 AOperation: TBlendOperation; AIgnoreDestAlpha: boolean); 1679begin 1680 BlendRect(ClipRect, AColor, AOperation, AIgnoreDestAlpha); 1681end; 1682 1683procedure TBGRACustomBitmap.BlendOver(AColor: TBGRAPixel; 1684 AOperation: TBlendOperation; AOpacity: byte; ALinearBlend: boolean; AIgnoreDestAlpha: boolean); 1685begin 1686 BlendRectOver(ClipRect, AColor, AOperation, AOpacity, ALinearBlend, AIgnoreDestAlpha); 1687end; 1688 1689procedure TBGRACustomBitmap.BlendRect(ADest: TRect; AColor: TBGRAPixel; 1690 AOperation: TBlendOperation; AIgnoreDestAlpha: boolean); 1691begin 1692 if AIgnoreDestAlpha then 1693 BlendRect(ADest, AColor, AOperation, [cAlpha]) 1694 else BlendRect(ADest, AColor, AOperation, []); 1695end; 1696 1697procedure TBGRACustomBitmap.BlendRectOver(ADest: TRect; AColor: TBGRAPixel; 1698 AOperation: TBlendOperation; AOpacity: byte; ALinearBlend: boolean; 1699 AIgnoreDestAlpha: boolean); 1700begin 1701 if AIgnoreDestAlpha then 1702 BlendRectOver(ADest, AColor, AOperation, AOpacity, ALinearBlend,[cAlpha]) 1703 else BlendRectOver(ADest, AColor, AOperation, AOpacity, ALinearBlend, []); 1704end; 1705 1706procedure TBGRACustomBitmap.FillMask(x, y: integer; 1707 AMask: TCustomUniversalBitmap; ATexture: IBGRAScanner; ADrawMode: TDrawMode); 1708begin 1709 FillMask(x, y, AMask, ATexture, ADrawMode, 255); 1710end; 1711 1712procedure TBGRACustomBitmap.VerticalFlip(ARect: TRect); 1713begin 1714 inherited VerticalFlip(ARect); 1715 if Assigned(XorMask) then XorMask.VerticalFlip(ARect); 1716end; 1717 1718procedure TBGRACustomBitmap.HorizontalFlip(ARect: TRect); 1719begin 1720 inherited HorizontalFlip(ARect); 1721 if Assigned(XorMask) then XorMask.HorizontalFlip(ARect); 1722end; 1723 1724procedure TBGRACustomBitmap.RotateUDInplace(ARect: TRect); 1725begin 1726 inherited RotateUDInplace(ARect); 1727 if Assigned(XorMask) then XorMask.RotateUDInplace(ARect); 1728end; 1729 1730function TBGRACustomBitmap.RotateCW: TBGRACustomBitmap; 1731begin 1732 result := TBGRACustomBitmap(Inherited RotateCW); 1733 if Assigned(XorMask) then result.FXorMask := self.XorMask.RotateCW; 1734end; 1735 1736function TBGRACustomBitmap.RotateCCW: TBGRACustomBitmap; 1737begin 1738 result := TBGRACustomBitmap(Inherited RotateCCW); 1739 if Assigned(XorMask) then result.FXorMask := self.XorMask.RotateCCW; 1740end; 1741 1742function TBGRACustomBitmap.RotateUD: TBGRACustomBitmap; 1743begin 1744 result := TBGRACustomBitmap(Inherited RotateUD); 1745 if Assigned(XorMask) then result.FXorMask := self.XorMask.RotateUD; 1746end; 1747 1748function TBGRACustomBitmap.FilterBlurRadial(radius: single; 1749 blurType: TRadialBlurType): TBGRACustomBitmap; 1750begin 1751 result := TBGRACustomBitmap(inherited FilterBlurRadial(radius, blurType)); 1752end; 1753 1754function TBGRACustomBitmap.FilterBlurRadial(const ABounds: TRect; radius: single; 1755 blurType: TRadialBlurType): TBGRACustomBitmap; 1756begin 1757 result := TBGRACustomBitmap(inherited FilterBlurRadial(ABounds, radius, blurType)); 1758end; 1759 1760function TBGRACustomBitmap.FilterBlurRadial(radiusX, radiusY: single; 1761 blurType: TRadialBlurType): TBGRACustomBitmap; 1762begin 1763 result := TBGRACustomBitmap(inherited FilterBlurRadial(radiusX,radiusY, blurType)); 1764end; 1765 1766function TBGRACustomBitmap.FilterBlurRadial(const ABounds: TRect; radiusX, 1767 radiusY: single; blurType: TRadialBlurType): TBGRACustomBitmap; 1768begin 1769 result := TBGRACustomBitmap(inherited FilterBlurRadial(ABounds, radiusX,radiusY, blurType)); 1770end; 1771 1772function TBGRACustomBitmap.FilterBlurMotion(distance: single; angle: single; 1773 oriented: boolean): TBGRACustomBitmap; 1774begin 1775 result := TBGRACustomBitmap(inherited FilterBlurMotion(distance, angle, oriented)); 1776end; 1777 1778function TBGRACustomBitmap.FilterBlurMotion(const ABounds: TRect; distance: single; 1779 angle: single; oriented: boolean): TBGRACustomBitmap; 1780begin 1781 result := TBGRACustomBitmap(inherited FilterBlurMotion(ABounds, distance, angle, oriented)); 1782end; 1783 1784function TBGRACustomBitmap.FilterCustomBlur(mask: TCustomUniversalBitmap 1785 ): TBGRACustomBitmap; 1786begin 1787 result := TBGRACustomBitmap(inherited FilterCustomBlur(mask)); 1788end; 1789 1790function TBGRACustomBitmap.FilterCustomBlur(const ABounds: TRect; 1791 mask: TCustomUniversalBitmap): TBGRACustomBitmap; 1792begin 1793 result := TBGRACustomBitmap(inherited FilterCustomBlur(ABounds,mask)); 1794end; 1795 1796function TBGRACustomBitmap.GetImageBoundsWithin(const ARect: TRect; 1797 Channel: TChannel; ANothingValue: Byte): TRect; 1798begin 1799 result := InternalGetImageBoundsWithin(self,nil,ARect,[Channel],ANothingValue); 1800end; 1801 1802function TBGRACustomBitmap.GetImageBoundsWithin(const ARect: TRect; 1803 Channels: TChannels; ANothingValue: Byte): TRect; 1804begin 1805 result := InternalGetImageBoundsWithin(self,nil,ARect,Channels,ANothingValue); 1806end; 1807 1808function TBGRACustomBitmap.ScanAtIntegerExpanded(X, Y: integer): TExpandedPixel; 1809begin 1810 result := GammaExpansion(ScanAtInteger(X,Y)); 1811end; 1812 1813function TBGRACustomBitmap.ScanNextExpandedPixel: TExpandedPixel; 1814begin 1815 result := GammaExpansion(ScanNextPixel); 1816end; 1817 1818function TBGRACustomBitmap.ScanAtExpanded(X, Y: Single): TExpandedPixel; 1819begin 1820 result := GammaExpansion(ScanAt(X,Y)); 1821end; 1822 1823function TBGRACustomBitmap.ProvidesScanline(ARect: TRect): boolean; 1824begin 1825 result := (ARect.Left+ScanOffset.x >= 0) and (ARect.Top+ScanOffset.y >= 0) and 1826 (ARect.Right+ScanOffset.x <= Width) and (ARect.Bottom+ScanOffset.y <= Height); 1827end; 1828 1829function TBGRACustomBitmap.GetScanlineAt(X, Y: integer): PBGRAPixel; 1830begin 1831 result := ScanLine[y+ScanOffset.y]+x+ScanOffset.x; 1832end; 1833 1834procedure TBGRACustomBitmap.ScanNextMaskChunk(var ACount: integer; out AMask: PByteMask; out AStride: integer); 1835var 1836 PPixels: Pointer; 1837begin 1838 ScanNextCustomChunk(ACount, PPixels); 1839 AMask := (PByteMask(PPixels)+TBGRAPixel_ChannelByteOffset[ScanMaskChannel]); 1840 AStride := sizeof(TBGRAPixel); 1841end; 1842 1843function TBGRACustomBitmap.ScanAtIntegerMask(X,Y: integer): TByteMask; 1844var 1845 c: TBGRAPixel; 1846begin 1847 c := ScanAtInteger(X,Y); 1848 result := (PByte(@c)+TBGRAPixel_ChannelByteOffset[ScanMaskChannel])^; 1849end; 1850 1851function TBGRACustomBitmap.ScanAtMask(X,Y: Single): TByteMask; 1852var 1853 c: TBGRAPixel; 1854begin 1855 c := ScanAt(X,Y); 1856 result := (PByte(@c)+TBGRAPixel_ChannelByteOffset[ScanMaskChannel])^; 1857end; 1858 1859{$ENDIF} 1860