Changeset 494 for GraphicTest/Packages/bgrabitmap/bgradefaultbitmap.pas
- Timestamp:
- Dec 22, 2016, 8:49:19 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
GraphicTest/Packages/bgrabitmap/bgradefaultbitmap.pas
r472 r494 33 33 34 34 uses 35 Classes, SysUtils, Types, FPImage, Graphics, BGRABitmapTypes, GraphType, FPImgCanv,36 BGRACanvas, BGRACanvas2D, FPWritePng, BGRAArrow, BGRAPen;35 SysUtils, Classes, Types, FPImage, BGRAGraphics, BGRABitmapTypes, FPImgCanv, 36 BGRACanvas, BGRACanvas2D, BGRAArrow, BGRAPen, BGRATransform; 37 37 38 38 type 39 TBGRAPtrBitmap = class; 40 {=== TBGRABitmap reference ===} 39 41 { TBGRADefaultBitmap } 40 42 {* This class is the base for all ''TBGRABitmap'' classes. It implements most 43 function to the exception from implementations specific to the 44 widgetset }{ in the doc, it is presented as 45 TBGRABitmap = class(TBGRACustomBitmap) 46 } 41 47 TBGRADefaultBitmap = class(TBGRACustomBitmap) 42 48 private … … 47 53 function CheckVertLineBounds(var x, y, y2: int32or64; out delta: int32or64): boolean; inline; 48 54 function CheckRectBounds(var x,y,x2,y2: integer; minsize: integer): boolean; inline; 49 function CheckClippedRectBounds(var x,y,x2,y2: integer): boolean; inline;50 55 function CheckAntialiasRectBounds(var x,y,x2,y2: single; w: single): boolean; 51 56 function GetCanvasBGRA: TBGRACanvas; 52 57 function GetCanvas2D: TBGRACanvas2D; 58 procedure GradientFillDithered(x, y, x2, y2: integer; c1, c2: TBGRAPixel; 59 gtype: TGradientType; o1, o2: TPointF; mode: TDrawMode; 60 gammaColorCorrection: boolean = True; Sinus: Boolean=False; 61 ditherAlgo: TDitheringAlgorithm = daFloydSteinberg); 62 procedure GradientFillDithered(x, y, x2, y2: integer; gradient: TBGRACustomGradient; 63 gtype: TGradientType; o1, o2: TPointF; mode: TDrawMode; 64 Sinus: Boolean=False; 65 ditherAlgo: TDitheringAlgorithm = daFloydSteinberg); 53 66 protected 54 67 FRefCount: integer; //reference counter (not related to interface reference counter) … … 57 70 FData: PBGRAPixel; //pointer to pixels 58 71 FWidth, FHeight, FNbPixels: integer; //dimensions 72 FScanWidth, FScanHeight: integer; //possibility to reduce the zone being scanned 59 73 FDataModified: boolean; //if data image has changed so TBitmap should be updated 60 74 FLineOrder: TRawImageLineOrder; … … 65 79 FScanCurX,FScanCurY: integer; //current scan coordinates 66 80 67 // LCLbitmap object81 //GUI bitmap object 68 82 FBitmap: TBitmap; 69 83 FBitmapModified: boolean; //if TBitmap has changed so pixel data should be updated … … 86 100 FFontRenderer: TBGRACustomFontRenderer; 87 101 88 { Pen style can be defined by PenStyle property of by CustomPenStyle property. 89 When PenStyle property is assigned, CustomPenStyle property is assigned the actual 90 pen pattern. } 91 FCustomPenStyle: TBGRAPenStyle; 92 FPenStyle: TPenStyle; 93 FArrow: TBGRAArrow; 94 FLineCap: TPenEndCap; 102 FPenStroker: TBGRAPenStroker; 95 103 96 104 //Pixel data … … 98 106 function GetScanLine(y: integer): PBGRAPixel; override; //don't forget to call InvalidateBitmap after modifications 99 107 function LoadFromRawImage(ARawImage: TRawImage; DefaultOpacity: byte; 100 AlwaysReplaceAlpha: boolean = False; RaiseErrorOnInvalidPixelFormat: boolean = True): boolean; 108 AlwaysReplaceAlpha: boolean = False; RaiseErrorOnInvalidPixelFormat: boolean = True): boolean; virtual; abstract; 101 109 function GetDataPtr: PBGRAPixel; override; 102 110 procedure ClearTransparentPixels; override; 103 111 function GetScanlineFast(y: integer): PBGRAPixel; inline; 104 112 function GetLineOrder: TRawImageLineOrder; override; 113 procedure SetLineOrder(AValue: TRawImageLineOrder); virtual; 105 114 function GetNbPixels: integer; override; 106 115 function GetWidth: integer; override; 107 116 function GetHeight: integer; override; 108 117 109 // LCLbitmap object118 //GUI bitmap object 110 119 function GetBitmap: TBitmap; override; 111 120 function GetCanvas: TCanvas; override; … … 116 125 function GetCanvasAlphaCorrection: boolean; override; 117 126 procedure SetCanvasAlphaCorrection(const AValue: boolean); override; 127 procedure DoLoadFromBitmap; virtual; 118 128 119 129 //FreePascal drawing routines … … 125 135 procedure ReallocData; virtual; 126 136 procedure FreeData; virtual; 127 128 procedure RebuildBitmap; virtual; 137 function CreatePtrBitmap(AWidth,AHeight: integer; AData: PBGRAPixel): TBGRAPtrBitmap; virtual; 138 139 procedure RebuildBitmap; virtual; abstract; 129 140 procedure FreeBitmap; virtual; 130 141 … … 144 155 function GetAverageColor: TColor; override; 145 156 function GetAveragePixel: TBGRAPixel; override; 146 function CreateAdaptedPngWriter: TFPWriterPNG;147 157 148 158 //drawing 159 function GetPenJoinStyle: TPenJoinStyle; override; 160 procedure SetPenJoinStyle(const AValue: TPenJoinStyle); override; 161 function GetPenMiterLimit: single; override; 162 procedure SetPenMiterLimit(const AValue: single); override; 149 163 function GetCustomPenStyle: TBGRAPenStyle; override; 150 164 procedure SetCustomPenStyle(const AValue: TBGRAPenStyle); override; … … 153 167 function GetLineCap: TPenEndCap; override; 154 168 procedure SetLineCap(AValue: TPenEndCap); override; 169 function GetPenStroker: TBGRACustomPenStroker; override; 170 155 171 function GetArrowEndSize: TPointF; override; 156 172 function GetArrowStartSize: TPointF; override; … … 173 189 function GetFontRenderer: TBGRACustomFontRenderer; override; 174 190 procedure SetFontRenderer(AValue: TBGRACustomFontRenderer); override; 191 function CreateDefaultFontRenderer: TBGRACustomFontRenderer; virtual; abstract; 192 function GetFontAnchorVerticalOffset: single; 193 function GetFontAnchorRotatedOffset: TPointF; 194 function GetFontAnchorRotatedOffset(ACustomOrientation: integer): TPointF; 175 195 176 196 function GetClipRect: TRect; override; … … 179 199 function InternalGetPixelCycle256(ix,iy: int32or64; iFactX,iFactY: int32or64): TBGRAPixel; 180 200 function InternalGetPixel256(ix,iy: int32or64; iFactX,iFactY: int32or64; smoothBorder: boolean): TBGRAPixel; 181 function GetPolyLineOption: TBGRAPolyLineOptions;182 201 function GetArrow: TBGRAArrow; 183 procedure SetArrowStart(AStyle: TBGRAArrowStyle; ATipStyle: TPenJoinStyle = pjsMiter; ARelativePenWidth: single = 1; ATriangleBackOffset: single = 0); override; 184 procedure SetArrowEnd(AStyle: TBGRAArrowStyle; ATipStyle: TPenJoinStyle = pjsMiter; ARelativePenWidth: single = 1; ATriangleBackOffset: single = 0); override; 202 procedure InternalTextOutCurved(ACursor: TBGRACustomPathCursor; sUTF8: string; AColor: TBGRAPixel; ATexture: IBGRAScanner; AAlign: TAlignment; ALetterSpacing: single); 203 204 function CheckClippedRectBounds(var x,y,x2,y2: integer): boolean; 205 procedure InternalArc(cx,cy,rx,ry: single; StartAngleRad,EndAngleRad: Single; ABorderColor: TBGRAPixel; w: single; 206 AFillColor: TBGRAPixel; AOptions: TArcOptions; ADrawChord: boolean = false; ATexture: IBGRAScanner = nil); override; 185 207 186 208 public 187 {Reference counter functions} 209 {** Provides a canvas with opacity and antialiasing } 210 property CanvasBGRA: TBGRACanvas read GetCanvasBGRA; 211 {** Provides a canvas with 2d transformation and similar to HTML5. } 212 property Canvas2D: TBGRACanvas2D read GetCanvas2D; 213 {** For more properties, see parent class [[TBGRACustomBitmap and IBGRAScanner#TBGRACustomBitmap|TBGRACustomBitmap]] } 214 215 {==== Reference counting ====} 216 217 {** Adds a reference (this reference count is not the same as 218 the reference count of an interface, it changes only by 219 explicit calls } 188 220 function NewReference: TBGRACustomBitmap; 221 {** Free a reference. When the resulting reference count gets 222 to zero, the image is freed. The initial reference count 223 is equal to 1 } 189 224 procedure FreeReference; 225 {** Returns an object with a reference count equal to 1. Duplicate 226 this bitmap if necessary } 190 227 function GetUnique: TBGRACustomBitmap; 191 228 229 {==== Constructors ====} 230 192 231 {------------------------- Constructors from TFPCustomImage----------------} 193 constructor Create(AWidth, AHeight: integer); override; //Creates a new bitmap, initialize properties and bitmap data 194 procedure SetSize(AWidth, AHeight: integer); override; //Can only be called with an existing instance of TBGRABitmap. 195 //Sets the dimensions of an existing TBGRABitmap instance. 232 {** Creates a new bitmap, initialize properties and bitmap data } 233 constructor Create(AWidth, AHeight: integer); override; 234 {** Can only be called with an existing instance of ''TBGRABitmap''. 235 Sets the dimensions of an existing ''TBGRABitmap'' instance. } 236 procedure SetSize(AWidth, AHeight: integer); override; 196 237 197 238 {------------------------- Constructors from TBGRACustomBitmap-------------} 198 constructor Create; override; //Creates an image of width and height equal to zero. 199 constructor Create(ABitmap: TBitmap); override; //Creates an image of dimensions AWidth and AHeight and filled with transparent pixels. 200 constructor Create(AWidth, AHeight: integer; Color: TColor); override; //Creates an image of dimensions AWidth and AHeight and fills it with the opaque color Color. 201 constructor Create(AWidth, AHeight: integer; Color: TBGRAPixel); override; //Creates an image of dimensions AWidth and AHeight and fills it with Color. 202 203 constructor Create(AFilename: string); override; // Creates an image by loading its content from the file AFilename. 204 // The encoding of the string is the default one for the operating system. 205 // It is recommended to use the next constructor and UTF8 encoding. 206 207 constructor Create(AFilename: string; AIsUtf8: boolean); override; //Creates an image by loading its content from the file AFilename. 208 //The boolean AIsUtf8Filename specifies if UTF8 encoding is assumed for the filename. 209 210 constructor Create(AStream: TStream); override; // Creates an image by loading its content from the stream AStream. 211 destructor Destroy; override; // Free the object and all its resources 239 {** Creates an image of width and height equal to zero. In this case, 240 ''Data'' = '''nil''' } 241 constructor Create; override; 242 {** Creates an image by copying the content of a ''TFPCustomImage'' } 243 constructor Create(AFPImage: TFPCustomImage); override; 244 {** Creates an image by copying the content of a ''TBitmap'' } 245 constructor Create(ABitmap: TBitmap; AUseTransparent: boolean = true); override; 246 {** Creates an image of dimensions ''AWidth'' and ''AHeight'' and fills it with the opaque color ''Color'' } 247 constructor Create(AWidth, AHeight: integer; Color: TColor); override; 248 {** Creates an image of dimensions ''AWidth'' and ''AHeight'' and fills it with ''Color'' } 249 constructor Create(AWidth, AHeight: integer; Color: TBGRAPixel); override; 250 251 {** Creates an image by loading its content from the file ''AFilename''. 252 The encoding of the string is the default one for the operating system. 253 It is recommended to use the next constructor and UTF8 encoding } 254 constructor Create(AFilename: string); override; 255 256 {** Creates an image by loading its content from the file ''AFilename''. 257 The boolean ''AIsUtf8Filename'' specifies if UTF8 encoding is assumed 258 for the filename } 259 constructor Create(AFilename: string; AIsUtf8: boolean); override; 260 constructor Create(AFilename: string; AIsUtf8: boolean; AOptions: TBGRALoadingOptions); override; 261 262 {** Creates an image by loading its content from the stream ''AStream'' } 263 constructor Create(AStream: TStream); override; 264 {** Free the object and all its resources } 265 destructor Destroy; override; 212 266 213 267 {------------------------- Quasi-constructors -----------------------------} 214 function NewBitmap(AWidth, AHeight: integer): TBGRACustomBitmap; override; //Can only be called from an existing instance of TBGRABitmap. 215 //Creates a new instance with dimensions AWidth and AHeight, 216 //containing transparent pixels. 217 218 function NewBitmap(AWidth, AHeight: integer; Color: TBGRAPixel): TBGRACustomBitmap; override; //Can only be called from an existing instance of TBGRABitmap. 219 //Creates a new instance with dimensions AWidth and AHeight, 220 //and fills it with Color. 221 222 function NewBitmap(Filename: string): TBGRACustomBitmap; override; //Can only be called from an existing instance of TBGRABitmap. 223 //Creates a new instance with by loading its content 224 //from the file Filename. The encoding of the string 225 //is the default one for the operating system. 226 227 function NewBitmap(Filename: string; AIsUtf8: boolean): TBGRACustomBitmap; override; //Can only be called from an existing instance of TBGRABitmap. 228 //Creates a new instance with by loading its content 229 //from the file Filename. 230 231 procedure SaveToFile(const filename: string); override; 232 procedure SaveToStreamAsPng(Str: TStream); override; 233 procedure Assign(ARaster: TRasterImage); override; overload; 234 procedure Assign(MemBitmap: TBGRACustomBitmap);override; overload; 268 {** Can only be called from an existing instance of ''TBGRABitmap''. 269 Creates a new instance with dimensions ''AWidth'' and ''AHeight'', 270 containing transparent pixels. } 271 function NewBitmap(AWidth, AHeight: integer): TBGRACustomBitmap; override; 272 273 {** Can only be called from an existing instance of ''TBGRABitmap''. 274 Creates a new instance with dimensions ''AWidth'' and ''AHeight'', 275 and fills it with Color } 276 function NewBitmap(AWidth, AHeight: integer; Color: TBGRAPixel): TBGRACustomBitmap; override; 277 278 {** Can only be called from an existing instance of ''TBGRABitmap''. 279 Creates a new instance with by loading its content 280 from the file ''Filename''. The encoding of the string 281 is the default one for the operating system } 282 function NewBitmap(Filename: string): TBGRACustomBitmap; override; 283 284 {** Can only be called from an existing instance of ''TBGRABitmap''. 285 Creates a new instance with by loading its content 286 from the file ''Filename'' } 287 function NewBitmap(Filename: string; AIsUtf8: boolean): TBGRACustomBitmap; override; 288 function NewBitmap(Filename: string; AIsUtf8: boolean; AOptions: TBGRALoadingOptions): TBGRACustomBitmap; override; 289 290 {** Can only be called from an existing instance of ''TBGRABitmap''. 291 Creates an image by copying the content of a ''TFPCustomImage'' } 292 function NewBitmap(AFPImage: TFPCustomImage): TBGRACustomBitmap; override; 293 294 {** Load image from a stream. The specified image reader is used } 295 procedure LoadFromStream(Str: TStream; Handler: TFPCustomImageReader; AOptions: TBGRALoadingOptions); override; 296 297 {** Assign the content of the specified ''Source''. It can be a ''TBGRACustomBitmap'' or 298 a ''TFPCustomImage'' } 299 procedure Assign(Source: TPersistent); override; 300 procedure Assign(Source: TBitmap; AUseTransparent: boolean); overload; 301 {** Stores the image in the stream without compression nor header } 235 302 procedure Serialize(AStream: TStream); override; 303 {** Reads the image in a stream that was previously serialized } 236 304 procedure Deserialize(AStream: TStream); override; 305 {** Stores an empty image (of size zero) } 237 306 class procedure SerializeEmpty(AStream: TStream); 238 307 239 {Pixel functions} 308 {* Example: 309 <syntaxhighlight> 310 * var bmp1, bmp2: TBGRABitmap; 311 * begin 312 * bmp1 := TBGRABitmap.Create(100,100); 313 * bmp2 := bmp1.NewBitmap(100,100) as TBGRABitmap; 314 * ... 315 * end;</syntaxhighlight> 316 See tutorial 2 on [[BGRABitmap_tutorial_2|how to load and display an image]]. 317 * See reference on [[TBGRACustomBitmap_and_IBGRAScanner#Load_and_save_files|loading and saving files]] } 318 319 {==== Pixel functions ====} 320 {** Checks if the specified point is in the clipping rectangle ''ClipRect'' } 240 321 function PtInClipRect(x, y: int32or64): boolean; inline; 322 {** Sets the pixel by replacing the content at (''x'',''y'') with the specified color. 323 Alpha value is set to 255 (opaque) } 241 324 procedure SetPixel(x, y: int32or64; c: TColor); override; 325 {** Sets the pixel at (''x'',''y'') with the specified content } 242 326 procedure SetPixel(x, y: int32or64; c: TBGRAPixel); override; 327 {** Applies a logical '''xor''' to the content of the pixel with the specified value. 328 This includes the alpha channel, so if you want to preserve the opacity, provide 329 a color ''c'' with alpha channel equal to zero } 243 330 procedure XorPixel(x, y: int32or64; c: TBGRAPixel); override; 331 {** Draws a pixel with gamma correction at (''x'',''y''). Pixel is supplied 332 in sRGB colorspace } 244 333 procedure DrawPixel(x, y: int32or64; c: TBGRAPixel); override; 334 {** Draws a pixel with the specified ''ADrawMode'' at (''x'',''y''). 335 Pixel is supplied in sRGB colorspace. Gamma correction may be applied 336 depending on the draw mode }{inherited 337 procedure DrawPixel(x, y: int32or64; c: TBGRAPixel; ADrawMode: TDrawMode); overload; 338 }{** Draws a pixel with gamma correction at (''x'',''y''). Pixel is supplied 339 in gamma expanded colorspace } 245 340 procedure DrawPixel(x, y: int32or64; ec: TExpandedPixel); override; 341 {** Draws a pixel without gamma correction at (''x'',''y''). Pixel is supplied 342 in sRGB colorspace } 246 343 procedure FastBlendPixel(x, y: int32or64; c: TBGRAPixel); override; 344 {** Erase the content of the pixel by reducing the value of the 345 alpha channel. ''alpha'' specifies how much to decrease. 346 If the resulting alpha reaches zero, the content 347 is replaced by ''BGRAPixelTransparent'' } 247 348 procedure ErasePixel(x, y: int32or64; alpha: byte); override; 349 {** Sets the alpha value at (''x'',''y''). If ''alpha'' = 0, the 350 pixel is replaced by ''BGRAPixelTransparent'' } 248 351 procedure AlphaPixel(x, y: int32or64; alpha: byte); override; 352 {** Returns the content of the specified pixel. If it is out of the 353 bounds of the picture, the result is ''BGRAPixelTransparent'' } 249 354 function GetPixel(x, y: int32or64): TBGRAPixel; override; 355 {** Computes the value of the pixel at a floating point coordiante 356 by interpolating the values of the pixels around it. 357 * There is a one pixel wide margin around the pixel where the pixels are 358 still considered inside. If ''smoothBorder'' is set to true, pixel fade 359 to transparent. 360 * If it is more out of the bounds, the result is ''BGRAPixelTransparent''. 361 * ''AResampleFilter'' specifies how pixels must be interpolated. Accepted 362 values are ''rfBox'', ''rfLinear'', ''rfHalfCosine'' and ''rfCosine'' } 363 function GetPixel(x, y: single; AResampleFilter: TResampleFilter = rfLinear; smoothBorder: boolean = true): TBGRAPixel; override; 364 {** Similar to previous ''GetPixel'' function, but the fractional part of 365 the coordinate is supplied with a number from 0 to 255. The actual 366 coordinate is (''x'' + ''fracX256''/256, ''y'' + ''fracY256''/256) } 250 367 function GetPixel256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter = rfLinear; smoothBorder: boolean = true): TBGRAPixel; override; 251 function GetPixel(x, y: single; AResampleFilter: TResampleFilter = rfLinear; smoothBorder: boolean = true): TBGRAPixel; override; 368 {** Computes the value of the pixel at a floating point coordiante 369 by interpolating the values of the pixels around it. If the pixel 370 is out of bounds, the image is repeated. 371 * ''AResampleFilter'' specifies how pixels must be interpolated. Accepted 372 values are ''rfBox'', ''rfLinear'', ''rfHalfCosine'' and ''rfCosine'' } 252 373 function GetPixelCycle(x, y: single; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel; override; 374 {** Similar to previous ''GetPixel'' function, but the fractional part of 375 the coordinate is supplied with a number from 0 to 255. The actual 376 coordinate is (''x'' + ''fracX256''/256, ''y'' + ''fracY256''/256) } 377 function GetPixelCycle256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel; override; 378 {** Computes the value of the pixel at a floating point coordiante 379 by interpolating the values of the pixels around it. ''repeatX'' and 380 ''repeatY'' specifies if the image is to be repeated or not. 381 * ''AResampleFilter'' specifies how pixels must be interpolated. Accepted 382 values are ''rfBox'', ''rfLinear'', ''rfHalfCosine'' and ''rfCosine'' } 253 383 function GetPixelCycle(x, y: single; AResampleFilter: TResampleFilter; repeatX: boolean; repeatY: boolean): TBGRAPixel; override; 254 function GetPixelCycle256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel; override; 384 {** Similar to previous ''GetPixel'' function, but the fractional part of 385 the coordinate is supplied with a number from 0 to 255. The actual 386 coordinate is (''x'' + ''fracX256''/256, ''y'' + ''fracY256''/256) } 255 387 function GetPixelCycle256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter; repeatX: boolean; repeatY: boolean): TBGRAPixel; override; 256 388 257 {Line primitives} 389 {==== Drawing lines and polylines (integer coordinates) ====} 390 {* These functions do not take into account current pen style/cap/join. 391 See [[BGRABitmap tutorial 13|coordinate system]]. } 392 393 {** Replaces the content of the pixels at line ''y'' and 394 at columns ''x'' to ''x2'' included, using specified color } 258 395 procedure SetHorizLine(x, y, x2: int32or64; c: TBGRAPixel); override; 396 {** Applies xor to the pixels at line ''y'' and 397 at columns ''x'' to ''x2'' included, using specified color. 398 This includes the alpha channel, so if you want to preserve the 399 opacity, provide a color ''c'' with alpha channel equal to zero } 259 400 procedure XorHorizLine(x, y, x2: int32or64; c: TBGRAPixel); override; 401 {** Draws an horizontal line with gamma correction at line ''y'' and 402 at columns ''x'' to ''x2'' included, using specified color } 260 403 procedure DrawHorizLine(x, y, x2: int32or64; c: TBGRAPixel); override; 404 {** Draws an horizontal line with gamma correction at line ''y'' and 405 at columns ''x'' to ''x2'' included, using specified color } 261 406 procedure DrawHorizLine(x, y, x2: int32or64; ec: TExpandedPixel); override; 407 {** Draws an horizontal line with gamma correction at line ''y'' and 408 at columns ''x'' to ''x2'' included, using specified scanner 409 to get the source colors }{inherited 410 procedure DrawHorizLine(x, y, x2: int32or64; texture: IBGRAScanner); overload; 411 }{** Draws an horizontal line without gamma correction at line ''y'' and 412 at columns ''x'' to ''x2'' included, using specified color } 413 procedure FastBlendHorizLine(x, y, x2: int32or64; c: TBGRAPixel); override; 414 {** Draws an horizontal line at line ''y'' and 415 at columns ''x'' to ''x2'' included, using specified scanner 416 and the specified ''ADrawMode'' } 262 417 procedure HorizLine(x, y, x2: int32or64; texture: IBGRAScanner; ADrawMode : TDrawMode); override; 263 264 procedure FastBlendHorizLine(x, y, x2: int32or64; c: TBGRAPixel); override; 418 {** Draws an horizontal line at line ''y'' and 419 at columns ''x'' to ''x2'' included, using specified color 420 and the specified ''ADrawMode'' }{inherited 421 procedure HorizLine(x,y,x2: Int32or64; c: TBGRAPixel; ADrawMode: TDrawMode); overload; 422 } 423 {** Replaces the alpha value of the pixels at line ''y'' and 424 at columns ''x'' to ''x2'' included } 265 425 procedure AlphaHorizLine(x, y, x2: int32or64; alpha: byte); override; 266 procedure SetVertLine(x, y, y2: int32or64; c: TBGRAPixel); override;267 procedure XorVertLine(x, y, y2: int32or64; c: TBGRAPixel); override;268 procedure DrawVertLine(x, y, y2: int32or64; c: TBGRAPixel); override;269 procedure AlphaVertLine(x, y, y2: int32or64; alpha: byte); override;270 procedure FastBlendVertLine(x, y, y2: int32or64; c: TBGRAPixel); override;426 {** Draws an horizontal line with gamma correction at line ''y'' and 427 at columns ''x'' to ''x2'' included, using specified color, 428 and with a transparency that increases with the color difference 429 with ''compare''. If the difference is greater than ''maxDiff'', 430 pixels are not changed } 271 431 procedure DrawHorizLineDiff(x, y, x2: int32or64; c, compare: TBGRAPixel; 272 432 maxDiff: byte); override; 273 433 274 {Shapes} 275 procedure DrawPath(APath: IBGRAPath; c: TBGRAPixel; w: single); override; 276 procedure DrawPath(APath: IBGRAPath; texture: IBGRAScanner; w: single); override; 277 434 {** Replaces a vertical line at column ''x'' and at row ''y'' to ''y2'' } 435 procedure SetVertLine(x, y, y2: int32or64; c: TBGRAPixel); override; 436 {** Xors a vertical line at column ''x'' and at row ''y'' to ''y2'' } 437 procedure XorVertLine(x, y, y2: int32or64; c: TBGRAPixel); override; 438 {** Draws a vertical line with gamma correction at column ''x'' and at row ''y'' to ''y2'' } 439 procedure DrawVertLine(x, y, y2: int32or64; c: TBGRAPixel); override; 440 {** Draws a vertical line without gamma correction at column ''x'' and at row ''y'' to ''y2'' } 441 procedure FastBlendVertLine(x, y, y2: int32or64; c: TBGRAPixel); override; 442 {** Replace alpha values in a vertical line at column ''x'' and at row ''y'' to ''y2'' } 443 procedure AlphaVertLine(x, y, y2: int32or64; alpha: byte); override; 444 {** Draws a vertical line with the specified draw mode at column ''x'' and at row ''y'' to ''y2'' }{inherited 445 procedure VertLine(x,y,y2: Int32or64; c: TBGRAPixel; ADrawMode: TDrawMode); 446 } 447 448 {** Draws an aliased line from (x1,y1) to (x2,y2) using Bresenham's algorithm 449 ''c'' specifies the color. ''DrawLastPixel'' specifies if (x2,y2) must be drawn. 450 ''ADrawMode'' specifies the mode to use when drawing the pixels } 278 451 procedure DrawLine(x1, y1, x2, y2: integer; c: TBGRAPixel; DrawLastPixel: boolean; ADrawMode: TDrawMode = dmDrawWithTransparency); override; 452 {** Draws an antialiased line from (x1,y1) to (x2,y2) using an improved version of Bresenham's algorithm 453 ''c'' specifies the color. ''DrawLastPixel'' specifies if (x2,y2) must be drawn } 279 454 procedure DrawLineAntialias(x1, y1, x2, y2: integer; c: TBGRAPixel; DrawLastPixel: boolean); override; 455 {** Draws an antialiased line with two colors ''c1'' and ''c2'' as dashes of lenght ''dashLen'' } 280 456 procedure DrawLineAntialias(x1, y1, x2, y2: integer; c1, c2: TBGRAPixel; dashLen: integer; DrawLastPixel: boolean); override; 457 {** Draws an antialiased line with two colors ''c1'' and ''c2'' as dashes of lenght ''dashLen''. 458 ''DashPos'' can be used to specify the start dash position and to retrieve the dash position at the end 459 of the line, in order to draw a polyline with consistent dashes } 281 460 procedure DrawLineAntialias(x1, y1, x2, y2: integer; c1, c2: TBGRAPixel; dashLen: integer; DrawLastPixel: boolean; var DashPos: integer); override; 461 462 {** Erases the line from (x1,y1) to (x2,y2) using Bresenham's algorithm. 463 ''alpha'' specifies how much to decrease. If ''alpha'' = 0, nothing 464 is changed and if ''alpha'' = 255, all pixels become transparent. 465 ''DrawListPixel'' specifies if (x2,y2) must be changed } 466 procedure EraseLine(x1, y1, x2, y2: integer; alpha: byte; DrawLastPixel: boolean); override; 467 {** Erases the line from (x1,y1) to (x2,y2) width antialiasing. 468 ''alpha'' specifies how much to decrease. If ''alpha'' = 0, nothing 469 is changed and if ''alpha'' = 255, all pixels become transparent. 470 ''DrawListPixel'' specifies if (x2,y2) must be changed } 471 procedure EraseLineAntialias(x1, y1, x2, y2: integer; alpha: byte; DrawLastPixel: boolean); override; 472 473 {==== Drawing lines and polylines (floating point coordinates) ====} 474 {* These functions use the current pen style/cap/join. The parameter ''w'' 475 specifies the width of the line and the base unit for dashes. 476 See [[BGRABitmap tutorial 13|coordinate system]]. } 477 478 {** Draws a line from (x1,y1) to (x2,y2) using current pen style/cap/join } 282 479 procedure DrawLineAntialias(x1, y1, x2, y2: single; c: TBGRAPixel; w: single); override; 480 {** Draws a line from (x1,y1) to (x2,y2) using current pen style/cap/join. 481 ''texture'' specifies the source color to use when filling the line } 283 482 procedure DrawLineAntialias(x1, y1, x2, y2: single; texture: IBGRAScanner; w: single); override; 284 procedure DrawLineAntialias(x1, y1, x2, y2: single; c: TBGRAPixel; w: single; Closed: boolean); override; 285 procedure DrawLineAntialias(x1, y1, x2, y2: single; texture: IBGRAScanner; w: single; Closed: boolean); override; 286 483 {** Draws a line from (x1,y1) to (x2,y2) using current pen style/cap/join. 484 ''Closed'' specifies if the end of the line is closed. If it is not closed, 485 a space is left so that the next line can fit } 486 procedure DrawLineAntialias(x1, y1, x2, y2: single; c: TBGRAPixel; w: single; ClosedCap: boolean); override; 487 {** Same as above with ''texture'' specifying the source color to use when filling the line } 488 procedure DrawLineAntialias(x1, y1, x2, y2: single; texture: IBGRAScanner; w: single; ClosedCap: boolean); override; 489 490 {** Draws a polyline using current pen style/cap/join } 287 491 procedure DrawPolyLineAntialias(const points: array of TPointF; c: TBGRAPixel; w: single); override; 492 {** Draws a polyline using current pen style/cap/join. 493 ''texture'' specifies the source color to use when filling the line } 288 494 procedure DrawPolyLineAntialias(const points: array of TPointF; texture: IBGRAScanner; w: single); override; 289 procedure DrawPolyLineAntialias(const points: array of TPointF; c: TBGRAPixel; w: single; Closed: boolean); override; 495 {** Draws a polyline using current pen style/cap/join. 496 ''Closed'' specifies if the end of the line is closed. If it is not closed, 497 a space is left so that the next line can fit } 498 procedure DrawPolyLineAntialias(const points: array of TPointF; c: TBGRAPixel; w: single; ClosedCap: boolean); override; 499 procedure DrawPolyLineAntialias(const points: array of TPointF; texture: IBGRAScanner; w: single; ClosedCap: boolean); override; 500 {** Draws a polyline using current pen style/cap/join. 501 ''fillcolor'' specifies a color to fill the polygon formed by the points } 290 502 procedure DrawPolyLineAntialias(const points: array of TPointF; c: TBGRAPixel; w: single; fillcolor: TBGRAPixel); override; 503 {** Draws a polyline using current pen style/cap/join. 504 The last point considered as a join with the first point if it has 505 the same coordinate } 506 procedure DrawPolyLineAntialiasAutocycle(const points: array of TPointF; c: TBGRAPixel; w: single); override; 507 procedure DrawPolyLineAntialiasAutocycle(const points: array of TPointF; texture: IBGRAScanner; w: single); override; 508 {** Draws a polygon using current pen style/cap/join. 509 The polygon is always closed. You don't need to set the last point 510 to be the same as the first point } 291 511 procedure DrawPolygonAntialias(const points: array of TPointF; c: TBGRAPixel; w: single); override; 512 {** Draws a polygon using current pen style/cap/join. 513 The polygon is always closed. You don't need to set the last point 514 to be the same as the first point } 292 515 procedure DrawPolygonAntialias(const points: array of TPointF; texture: IBGRAScanner; w: single); override; 516 {** Draws a filled polygon using current pen style/cap/join. 517 The polygon is always closed. You don't need to set the last point 518 to be the same as the first point. } 293 519 procedure DrawPolygonAntialias(const points: array of TPointF; c: TBGRAPixel; w: single; fillcolor: TBGRAPixel); override; 294 520 295 procedure EraseLine(x1, y1, x2, y2: integer; alpha: byte; DrawLastPixel: boolean); override; 296 procedure EraseLineAntialias(x1, y1, x2, y2: integer; alpha: byte; DrawLastPixel: boolean); override; 521 {** Erases a line from (x1,y1) to (x2,y2) using current pen style/cap/join } 297 522 procedure EraseLineAntialias(x1, y1, x2, y2: single; alpha: byte; w: single); override; 523 {** Erases a line from (x1,y1) to (x2,y2) using current pen style/cap/join. 524 ''Closed'' specifies if the end of the line is closed. If it is not closed, 525 a space is left so that the next line can fit } 298 526 procedure EraseLineAntialias(x1, y1, x2, y2: single; alpha: byte; w: single; Closed: boolean); override; 527 {** Erases a polyline using current pen style/cap/join } 299 528 procedure ErasePolyLineAntialias(const points: array of TPointF; alpha: byte; w: single); override; 300 529 301 procedure FillPath(APath: IBGRAPath; c: TBGRAPixel); override; 302 procedure FillPath(APath: IBGRAPath; texture: IBGRAScanner); override; 303 304 procedure FillTriangleLinearColor(pt1,pt2,pt3: TPointF; c1,c2,c3: TBGRAPixel); override; 305 procedure FillTriangleLinearColorAntialias(pt1,pt2,pt3: TPointF; c1,c2,c3: TBGRAPixel); override; 306 procedure FillTriangleLinearMapping(pt1,pt2,pt3: TPointF; texture: IBGRAScanner; tex1, tex2, tex3: TPointF; TextureInterpolation: Boolean= True); override; 307 procedure FillTriangleLinearMappingLightness(pt1,pt2,pt3: TPointF; texture: IBGRAScanner; tex1, tex2, tex3: TPointF; light1,light2,light3: word; TextureInterpolation: Boolean= True); override; 308 procedure FillTriangleLinearMappingAntialias(pt1,pt2,pt3: TPointF; texture: IBGRAScanner; tex1, tex2, tex3: TPointF); override; 309 310 procedure FillQuadLinearColor(pt1,pt2,pt3,pt4: TPointF; c1,c2,c3,c4: TBGRAPixel); override; 311 procedure FillQuadLinearColorAntialias(pt1,pt2,pt3,pt4: TPointF; c1,c2,c3,c4: TBGRAPixel); override; 312 procedure FillQuadLinearMapping(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; TextureInterpolation: Boolean= True); override; 313 procedure FillQuadLinearMappingLightness(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; light1,light2,light3,light4: word; TextureInterpolation: Boolean= True); override; 314 procedure FillQuadLinearMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); override; 315 procedure FillQuadPerspectiveMapping(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); override; 316 procedure FillQuadPerspectiveMapping(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; ACleanBorders: TRect); override; 317 procedure FillQuadPerspectiveMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); override; 318 procedure FillQuadPerspectiveMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; ACleanBorders: TRect); override; 319 320 procedure FillPolyLinearMapping(const points: array of TPointF; texture: IBGRAScanner; texCoords: array of TPointF; TextureInterpolation: Boolean); override; 321 procedure FillPolyLinearMappingLightness(const points: array of TPointF; texture: IBGRAScanner; texCoords: array of TPointF; lightnesses: array of word; TextureInterpolation: Boolean); override; 322 procedure FillPolyLinearColor(const points: array of TPointF; AColors: array of TBGRAPixel); override; 323 procedure FillPolyPerspectiveMapping(const points: array of TPointF; const pointsZ: array of single; texture: IBGRAScanner; texCoords: array of TPointF; TextureInterpolation: Boolean; zbuffer: psingle = nil); override; 324 procedure FillPolyPerspectiveMappingLightness(const points: array of TPointF; const pointsZ: array of single; texture: IBGRAScanner; texCoords: array of TPointF; lightnesses: array of word; TextureInterpolation: Boolean; zbuffer: psingle = nil); override; 325 530 {==== Rectangles (integer coordinates) ====} 531 {* The integer coordinates of rectangles interpreted such that 532 that the bottom/right pixels are not drawn. The width is equal 533 to x2-x, and pixels are drawn from x to x2-1. If x = x2, then nothing 534 is drawn. See [[BGRABitmap tutorial 13|coordinate system]]. 535 * These functions do not take into account current pen style/cap/join. 536 They draw a continuous 1-pixel width border } 537 538 {** Draw a size border of a rectangle, 539 using the specified ''mode'' } 540 procedure Rectangle(x, y, x2, y2: integer; c: TBGRAPixel; mode: TDrawMode); override; 541 {** Draw a filled rectangle with a border of color ''BorderColor'', 542 using the specified ''mode'' } 543 procedure Rectangle(x, y, x2, y2: integer; BorderColor, FillColor: TBGRAPixel; mode: TDrawMode); override; 544 {** Fills completely a rectangle, without any border, with the specified ''mode'' } 545 procedure FillRect(x, y, x2, y2: integer; c: TBGRAPixel; mode: TDrawMode); override; overload; 546 {** Fills completely a rectangle, without any border, with the specified ''texture'' and 547 with the specified ''mode'' } 548 procedure FillRect(x, y, x2, y2: integer; texture: IBGRAScanner; mode: TDrawMode; AScanOffset: TPoint); override; overload; 549 procedure FillRect(x, y, x2, y2: integer; texture: IBGRAScanner; mode: TDrawMode; AScanOffset: TPoint; ditheringAlgorithm: TDitheringAlgorithm); override; overload; 550 {** Sets the alpha value within the specified rectangle } 551 procedure AlphaFillRect(x, y, x2, y2: integer; alpha: byte); override; 552 {** Draws a filled round rectangle, with corners having an elliptical diameter of ''DX'' and ''DY'' } 553 procedure RoundRect(X1, Y1, X2, Y2: integer; DX, DY: integer; BorderColor, FillColor: TBGRAPixel; ADrawMode: TDrawMode = dmDrawWithTransparency); override; 554 {** Draws a round rectangle, with corners having an elliptical diameter of ''DX'' and ''DY'' } 555 procedure RoundRect(X1, Y1, X2, Y2: integer; DX, DY: integer; BorderColor: TBGRAPixel; ADrawMode: TDrawMode = dmDrawWithTransparency); override; 556 557 {==== Rectangles and ellipses (floating point coordinates) ====} 558 {* These functions use the current pen style/cap/join. The parameter ''w'' 559 specifies the width of the line and the base unit for dashes 560 * The coordinates are pixel-centered, so that when filling a rectangle, 561 if the supplied values are integers, the border will be half transparent. 562 If you want the border to be completely filled, you can subtract/add 563 0.5 to the coordinates to include the remaining thin border. 564 See [[BGRABitmap tutorial 13|coordinate system]]. } 565 566 {** Draws a rectangle with antialiasing and fills it with color ''back''. 567 Note that the pixel (x2,y2) is included contrary to integer coordinates } 568 procedure RectangleAntialias(x, y, x2, y2: single; c: TBGRAPixel; w: single; back: TBGRAPixel); override; 569 {** Draws a rectangle with antialiasing. Note that the pixel (x2,y2) is 570 included contrary to integer coordinates } 571 procedure RectangleAntialias(x, y, x2, y2: single; texture: IBGRAScanner; w: single); override; 572 {** Fills a rectangle with antialiasing. For example (-0.5,-0.5,0.5,0.5) 573 fills one pixel } 574 procedure FillRectAntialias(x, y, x2, y2: single; c: TBGRAPixel; pixelCenteredCoordinates: boolean = true); override; 575 {** Fills a rectangle with a texture } 576 procedure FillRectAntialias(x, y, x2, y2: single; texture: IBGRAScanner; pixelCenteredCoordinates: boolean = true); override; 577 {** Erases the content of a rectangle with antialiasing } 578 procedure EraseRectAntialias(x, y, x2, y2: single; alpha: byte; pixelCenteredCoordinates: boolean = true); override; 579 580 {** Draws a rounded rectangle border with antialiasing. The corners have an 581 elliptical radius of ''rx'' and ''ry''. ''options'' specifies how to 582 draw the corners. See [[BGRABitmap Geometry types|geometry types]] } 583 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; c: TBGRAPixel; w: single; options: TRoundRectangleOptions = []); override; 584 {** Draws a rounded rectangle border with the specified texture. 585 The corners have an elliptical radius of ''rx'' and ''ry''. 586 ''options'' specifies how to draw the corners. 587 See [[BGRABitmap Geometry types|geometry types]] } 588 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; texture: IBGRAScanner; w: single; options: TRoundRectangleOptions = []); override; 589 {** Draws and fills a round rectangle } 590 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; pencolor: TBGRAPixel; w: single; fillcolor: TBGRAPixel; options: TRoundRectangleOptions = []); override; 591 {** Draws and fills a round rectangle with textures } 592 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; penTexture: IBGRAScanner; w: single; fillTexture: IBGRAScanner; options: TRoundRectangleOptions = []); override; 593 594 {** Fills a rounded rectangle with antialiasing. The corners have an 595 elliptical radius of ''rx'' and ''ry''. ''options'' specifies how to 596 draw the corners. See [[BGRABitmap Geometry types|geometry types]] } 597 procedure FillRoundRectAntialias(x,y,x2,y2,rx,ry: single; c: TBGRAPixel; options: TRoundRectangleOptions = []; pixelCenteredCoordinates: boolean = true); override; 598 {** Fills a rounded rectangle with a texture } 599 procedure FillRoundRectAntialias(x,y,x2,y2,rx,ry: single; texture: IBGRAScanner; options: TRoundRectangleOptions = []; pixelCenteredCoordinates: boolean = true); override; 600 {** Erases the content of a rounded rectangle with a texture } 601 procedure EraseRoundRectAntialias(x,y,x2,y2,rx,ry: single; alpha: byte; options: TRoundRectangleOptions = []; pixelCenteredCoordinates: boolean = true); override; 602 603 {** Draws an ellipse with antialising. ''rx'' is the horizontal radius and 604 ''ry'' the vertical radius } 605 procedure EllipseAntialias(x, y, rx, ry: single; c: TBGRAPixel; w: single); override; 606 {** Draws an ellipse border with a ''texture'' } 607 procedure EllipseAntialias(x, y, rx, ry: single; texture: IBGRAScanner; w: single); override; 608 {** Draws and fills an ellipse } 609 procedure EllipseAntialias(x, y, rx, ry: single; c: TBGRAPixel; w: single; back: TBGRAPixel); override; 610 {** Fills an ellipse } 611 procedure FillEllipseAntialias(x, y, rx, ry: single; c: TBGRAPixel); override; 612 {** Fills an ellipse with a ''texture'' } 613 procedure FillEllipseAntialias(x, y, rx, ry: single; texture: IBGRAScanner); override; 614 {** Fills an ellipse with a gradient of color. ''outercolor'' specifies 615 the end color of the gradient on the border of the ellipse and 616 ''innercolor'' the end color of the gradient at the center of the 617 ellipse } 618 procedure FillEllipseLinearColorAntialias(x, y, rx, ry: single; outercolor, innercolor: TBGRAPixel); override; 619 {** Erases the content of an ellipse } 620 procedure EraseEllipseAntialias(x, y, rx, ry: single; alpha: byte); override; 621 622 {==== Polygons and path ====} 326 623 procedure FillPoly(const points: array of TPointF; c: TBGRAPixel; drawmode: TDrawMode); override; 327 624 procedure FillPoly(const points: array of TPointF; texture: IBGRAScanner; drawmode: TDrawMode); override; … … 331 628 procedure ErasePolyAntialias(const points: array of TPointF; alpha: byte); override; 332 629 630 procedure FillTriangleLinearColor(pt1,pt2,pt3: TPointF; c1,c2,c3: TBGRAPixel); override; 631 procedure FillTriangleLinearColorAntialias(pt1,pt2,pt3: TPointF; c1,c2,c3: TBGRAPixel); override; 632 procedure FillTriangleLinearMapping(pt1,pt2,pt3: TPointF; texture: IBGRAScanner; tex1, tex2, tex3: TPointF; TextureInterpolation: Boolean= True); override; 633 procedure FillTriangleLinearMappingLightness(pt1,pt2,pt3: TPointF; texture: IBGRAScanner; tex1, tex2, tex3: TPointF; light1,light2,light3: word; TextureInterpolation: Boolean= True); override; 634 procedure FillTriangleLinearMappingAntialias(pt1,pt2,pt3: TPointF; texture: IBGRAScanner; tex1, tex2, tex3: TPointF); override; 635 636 procedure FillQuadLinearColor(pt1,pt2,pt3,pt4: TPointF; c1,c2,c3,c4: TBGRAPixel); override; 637 procedure FillQuadLinearColorAntialias(pt1,pt2,pt3,pt4: TPointF; c1,c2,c3,c4: TBGRAPixel); override; 638 procedure FillQuadLinearMapping(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; TextureInterpolation: Boolean= True; ACulling: TFaceCulling = fcNone); override; 639 procedure FillQuadLinearMappingLightness(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; light1,light2,light3,light4: word; TextureInterpolation: Boolean= True); override; 640 procedure FillQuadLinearMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; ACulling: TFaceCulling = fcNone); override; 641 procedure FillQuadPerspectiveMapping(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; ADrawMode: TDrawMode = dmDrawWithTransparency); override; 642 procedure FillQuadPerspectiveMapping(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; ACleanBorders: TRect; ADrawMode: TDrawMode = dmDrawWithTransparency); override; 643 procedure FillQuadPerspectiveMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); override; 644 procedure FillQuadPerspectiveMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; ACleanBorders: TRect); override; 645 procedure FillQuadAffineMapping(Orig,HAxis,VAxis: TPointF; AImage: TBGRACustomBitmap; APixelCenteredCoordinates: boolean = true; ADrawMode: TDrawMode = dmDrawWithTransparency; AOpacity: byte = 255); override; 646 procedure FillQuadAffineMappingAntialias(Orig,HAxis,VAxis: TPointF; AImage: TBGRACustomBitmap; APixelCenteredCoordinates: boolean = true; AOpacity: byte = 255); override; 647 648 procedure FillPolyLinearMapping(const points: array of TPointF; texture: IBGRAScanner; texCoords: array of TPointF; TextureInterpolation: Boolean); override; 649 procedure FillPolyLinearMappingLightness(const points: array of TPointF; texture: IBGRAScanner; texCoords: array of TPointF; lightnesses: array of word; TextureInterpolation: Boolean); override; 650 procedure FillPolyLinearColor(const points: array of TPointF; AColors: array of TBGRAPixel); override; 651 procedure FillPolyPerspectiveMapping(const points: array of TPointF; const pointsZ: array of single; texture: IBGRAScanner; texCoords: array of TPointF; TextureInterpolation: Boolean; zbuffer: psingle = nil); override; 652 procedure FillPolyPerspectiveMappingLightness(const points: array of TPointF; const pointsZ: array of single; texture: IBGRAScanner; texCoords: array of TPointF; lightnesses: array of word; TextureInterpolation: Boolean; zbuffer: psingle = nil); override; 653 333 654 procedure FillShape(shape: TBGRACustomFillInfo; c: TBGRAPixel; drawmode: TDrawMode); override; 334 655 procedure FillShape(shape: TBGRACustomFillInfo; texture: IBGRAScanner; drawmode: TDrawMode); override; … … 338 659 procedure EraseShapeAntialias(shape: TBGRACustomFillInfo; alpha: byte); override; 339 660 340 procedure EllipseAntialias(x, y, rx, ry: single; c: TBGRAPixel; w: single); override; 341 procedure EllipseAntialias(x, y, rx, ry: single; texture: IBGRAScanner; w: single); override; 342 procedure EllipseAntialias(x, y, rx, ry: single; c: TBGRAPixel; w: single; back: TBGRAPixel); override; 343 procedure FillEllipseAntialias(x, y, rx, ry: single; c: TBGRAPixel); override; 344 procedure FillEllipseAntialias(x, y, rx, ry: single; texture: IBGRAScanner); override; 345 procedure FillEllipseLinearColorAntialias(x, y, rx, ry: single; outercolor, innercolor: TBGRAPixel); override; 346 procedure EraseEllipseAntialias(x, y, rx, ry: single; alpha: byte); override; 347 348 procedure Rectangle(x, y, x2, y2: integer; c: TBGRAPixel; mode: TDrawMode); override; 349 procedure Rectangle(x, y, x2, y2: integer; BorderColor, FillColor: TBGRAPixel; mode: TDrawMode); override; 350 procedure RectangleAntialias(x, y, x2, y2: single; c: TBGRAPixel; w: single; back: TBGRAPixel); override; 351 procedure RectangleAntialias(x, y, x2, y2: single; texture: IBGRAScanner; w: single); override; 352 353 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; c: TBGRAPixel; w: single; options: TRoundRectangleOptions = []); override; 354 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; texture: IBGRAScanner; w: single; options: TRoundRectangleOptions = []); override; 355 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; pencolor: TBGRAPixel; w: single; fillcolor: TBGRAPixel; options: TRoundRectangleOptions = []); override; 356 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; penTexture: IBGRAScanner; w: single; fillTexture: IBGRAScanner; options: TRoundRectangleOptions = []); override; 357 358 procedure FillRect(x, y, x2, y2: integer; c: TBGRAPixel; mode: TDrawMode); override; overload; 359 procedure FillRect(x, y, x2, y2: integer; texture: IBGRAScanner; mode: TDrawMode); override; overload; 360 procedure FillRectAntialias(x, y, x2, y2: single; c: TBGRAPixel); override; 361 procedure EraseRectAntialias(x, y, x2, y2: single; alpha: byte); override; 362 procedure FillRectAntialias(x, y, x2, y2: single; texture: IBGRAScanner); override; 363 procedure FillRoundRectAntialias(x,y,x2,y2,rx,ry: single; c: TBGRAPixel; options: TRoundRectangleOptions = []); override; 364 procedure FillRoundRectAntialias(x,y,x2,y2,rx,ry: single; texture: IBGRAScanner; options: TRoundRectangleOptions = []); override; 365 procedure EraseRoundRectAntialias(x,y,x2,y2,rx,ry: single; alpha: byte; options: TRoundRectangleOptions = []); override; 366 procedure AlphaFillRect(x, y, x2, y2: integer; alpha: byte); override; 367 procedure RoundRect(X1, Y1, X2, Y2: integer; DX, DY: integer; 368 BorderColor, FillColor: TBGRAPixel; ADrawMode: TDrawMode = dmDrawWithTransparency); override; 369 procedure RoundRect(X1, Y1, X2, Y2: integer; DX, DY: integer; 370 BorderColor: TBGRAPixel; ADrawMode: TDrawMode = dmDrawWithTransparency); override; 661 procedure DrawPath(APath: IBGRAPath; AStrokeColor: TBGRAPixel; AWidth: single; AFillColor: TBGRAPixel); override; 662 procedure DrawPath(APath: IBGRAPath; AStrokeTexture: IBGRAScanner; AWidth: single; AFillColor: TBGRAPixel); override; 663 procedure DrawPath(APath: IBGRAPath; AStrokeColor: TBGRAPixel; AWidth: single; AFillTexture: IBGRAScanner); override; 664 procedure DrawPath(APath: IBGRAPath; AStrokeTexture: IBGRAScanner; AWidth: single; AFillTexture: IBGRAScanner); override; 665 procedure DrawPath(APath: IBGRAPath; AStrokeColor: TBGRAPixel; AWidth: single); override; 666 procedure DrawPath(APath: IBGRAPath; AStrokeTexture: IBGRAScanner; AWidth: single); override; 667 procedure FillPath(APath: IBGRAPath; AFillColor: TBGRAPixel); override; 668 procedure FillPath(APath: IBGRAPath; AFillTexture: IBGRAScanner); override; 669 procedure ErasePath(APath: IBGRAPath; alpha: byte); override; 670 671 procedure DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; AStrokeColor: TBGRAPixel; AWidth: single; AFillColor: TBGRAPixel); override; 672 procedure DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; AStrokeTexture: IBGRAScanner; AWidth: single; AFillColor: TBGRAPixel); override; 673 procedure DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; AStrokeColor: TBGRAPixel; AWidth: single; AFillTexture: IBGRAScanner); override; 674 procedure DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; AStrokeTexture: IBGRAScanner; AWidth: single; AFillTexture: IBGRAScanner); override; 675 procedure DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; AStrokeColor: TBGRAPixel; AWidth: single); override; 676 procedure DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; AStrokeTexture: IBGRAScanner; AWidth: single); override; 677 procedure FillPath(APath: IBGRAPath; AMatrix: TAffineMatrix; AFillColor: TBGRAPixel); override; 678 procedure FillPath(APath: IBGRAPath; AMatrix: TAffineMatrix; AFillTexture: IBGRAScanner); override; 679 procedure ErasePath(APath: IBGRAPath; AMatrix: TAffineMatrix; alpha: byte); override; 680 681 procedure ArrowStartAsNone; override; 682 procedure ArrowStartAsClassic(AFlipped: boolean = false; ACut: boolean = false; ARelativePenWidth: single = 1); override; 683 procedure ArrowStartAsTriangle(ABackOffset: single = 0; ARounded: boolean = false; AHollow: boolean = false; AHollowPenWidth: single = 0.5); override; 684 procedure ArrowStartAsTail; override; 685 686 procedure ArrowEndAsNone; override; 687 procedure ArrowEndAsClassic(AFlipped: boolean = false; ACut: boolean = false; ARelativePenWidth: single = 1); override; 688 procedure ArrowEndAsTriangle(ABackOffset: single = 0; ARounded: boolean = false; AHollow: boolean = false; AHollowPenWidth: single = 0.5); override; 689 procedure ArrowEndAsTail; override; 371 690 372 691 { Draws the UTF8 encoded string, with color c. … … 385 704 procedure TextOutAngle(x, y: single; orientationTenthDegCCW: integer; sUTF8: string; texture: IBGRAScanner; align: TAlignment); override; overload; 386 705 706 procedure TextOutCurved(ACursor: TBGRACustomPathCursor; sUTF8: string; AColor: TBGRAPixel; AAlign: TAlignment; ALetterSpacing: single); override; overload; 707 procedure TextOutCurved(ACursor: TBGRACustomPathCursor; sUTF8: string; ATexture: IBGRAScanner; AAlign: TAlignment; ALetterSpacing: single); override; overload; 708 387 709 { Draw the UTF8 encoded string at the coordinate (x,y), clipped inside the rectangle ARect. 388 710 Additional style information is provided by the style parameter. … … 405 727 406 728 function ComputeWidePolyline(const points: array of TPointF; w: single): ArrayOfTPointF; override; 407 function ComputeWidePolyline(const points: array of TPointF; w: single; Closed : boolean): ArrayOfTPointF; override;729 function ComputeWidePolyline(const points: array of TPointF; w: single; ClosedCap: boolean): ArrayOfTPointF; override; 408 730 function ComputeWidePolygon(const points: array of TPointF; w: single): ArrayOfTPointF; override; 409 731 … … 425 747 procedure AlphaFill(alpha: byte; start, Count: integer); override; 426 748 procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; color: TBGRAPixel; ADrawMode: TDrawMode); override; 427 procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; texture: IBGRAScanner; ADrawMode: TDrawMode ); override;749 procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; texture: IBGRAScanner; ADrawMode: TDrawMode; AOpacity: byte = 255); override; 428 750 procedure FillClearTypeMask(x,y: integer; xThird: integer; AMask: TBGRACustomBitmap; color: TBGRAPixel; ARGBOrder: boolean = true); override; 429 751 procedure FillClearTypeMask(x,y: integer; xThird: integer; AMask: TBGRACustomBitmap; texture: IBGRAScanner; ARGBOrder: boolean = true); override; 430 752 procedure ReplaceColor(before, after: TColor); override; 431 753 procedure ReplaceColor(before, after: TBGRAPixel); override; 754 procedure ReplaceColor(ABounds: TRect; before, after: TColor); override; 755 procedure ReplaceColor(ABounds: TRect; before, after: TBGRAPixel); override; 432 756 procedure ReplaceTransparent(after: TBGRAPixel); override; 757 procedure ReplaceTransparent(ABounds: TRect; after: TBGRAPixel); override; 433 758 procedure ParallelFloodFill(X, Y: integer; Dest: TBGRACustomBitmap; Color: TBGRAPixel; 434 759 mode: TFloodfillMode; Tolerance: byte = 0); override; 435 760 procedure GradientFill(x, y, x2, y2: integer; c1, c2: TBGRAPixel; 436 761 gtype: TGradientType; o1, o2: TPointF; mode: TDrawMode; 437 gammaColorCorrection: boolean = True; Sinus: Boolean=False); override; 762 gammaColorCorrection: boolean = True; Sinus: Boolean=False; 763 ditherAlgo: TDitheringAlgorithm = daNearestNeighbor); override; 438 764 procedure GradientFill(x, y, x2, y2: integer; gradient: TBGRACustomGradient; 439 765 gtype: TGradientType; o1, o2: TPointF; mode: TDrawMode; 440 Sinus: Boolean=False ); override;766 Sinus: Boolean=False; ditherAlgo: TDitheringAlgorithm = daNearestNeighbor); override; 441 767 function CreateBrushTexture(ABrushStyle: TBrushStyle; APatternColor, ABackgroundColor: TBGRAPixel; 442 768 AWidth: integer = 8; AHeight: integer = 8; APenWidth: single = 1): TBGRACustomBitmap; override; … … 449 775 450 776 {Canvas drawing functions} 451 procedure DataDrawTransparent(ACanvas: TCanvas; Rect: TRect;452 AData: Pointer; ALineOrder: TRawImageLineOrder; AWidth, AHeight: integer); override;453 procedure DataDrawOpaque(ACanvas: TCanvas; Rect: TRect; AData: Pointer;454 ALineOrder: TRawImageLineOrder; AWidth, AHeight: integer); override;455 procedure GetImageFromCanvas(CanvasSource: TCanvas; x, y: integer); override;456 777 procedure Draw(ACanvas: TCanvas; x, y: integer; Opaque: boolean = True); override; 457 778 procedure Draw(ACanvas: TCanvas; Rect: TRect; Opaque: boolean = True); override; … … 463 784 procedure CrossFade(ARect: TRect; Source1, Source2: IBGRAScanner; AFadeMask: IBGRAScanner; mode: TDrawMode = dmDrawWithTransparency); override; 464 785 procedure PutImage(x, y: integer; Source: TBGRACustomBitmap; mode: TDrawMode; AOpacity: byte = 255); override; 465 procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AOutputBounds: TRect; AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte=255); override; 786 procedure PutImageAffine(AMatrix: TAffineMatrix; Source: TBGRACustomBitmap; AOutputBounds: TRect; AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte=255); override; overload; 787 function GetImageAffineBounds(AMatrix: TAffineMatrix; ASourceBounds: TRect; AClipOutput: boolean = true): TRect; override; overload; 788 function IsAffineRoughlyTranslation(AMatrix: TAffineMatrix; ASourceBounds: TRect): boolean; override; 789 466 790 procedure StretchPutImage(ARect: TRect; Source: TBGRACustomBitmap; mode: TDrawMode; AOpacity: byte = 255); override; 467 791 … … 476 800 function Equals(comp: TBGRACustomBitmap): boolean; override; 477 801 function Equals(comp: TBGRAPixel): boolean; override; 478 function GetImageBounds(Channel: TChannel = cAlpha; ANothingValue: Byte = 0): TRect; override;479 function GetImageBounds(Channels: TChannels; ANothingValue: Byte = 0): TRect; override;480 802 function GetDifferenceBounds(ABitmap: TBGRACustomBitmap): TRect; override; 481 803 function MakeBitmapCopy(BackgroundColor: TColor): TBitmap; override; … … 483 805 function Resample(newWidth, newHeight: integer; 484 806 mode: TResampleMode = rmFineResample): TBGRACustomBitmap; override; 485 procedure VerticalFlip(ARect: TRect); override; 486 procedure HorizontalFlip(ARect: TRect); override; 807 procedure VerticalFlip(ARect: TRect); override; overload; 808 procedure HorizontalFlip(ARect: TRect); override; overload; 487 809 function RotateCW: TBGRACustomBitmap; override; 488 810 function RotateCCW: TBGRACustomBitmap; override; … … 491 813 procedure LinearNegative; override; 492 814 procedure LinearNegativeRect(ABounds: TRect); override; 493 procedure InplaceGrayscale; override; 494 procedure InplaceGrayscale(ABounds: TRect); override; 815 procedure InplaceGrayscale(AGammaCorrection: boolean = true); override; 816 procedure InplaceGrayscale(ABounds: TRect; AGammaCorrection: boolean = true); override; 817 procedure InplaceNormalize(AEachChannel: boolean = True); override; 818 procedure InplaceNormalize(ABounds: TRect; AEachChannel: boolean = True); override; 495 819 procedure SwapRedBlue; override; 820 procedure SwapRedBlue(ARect: TRect); override; 496 821 procedure GrayscaleToAlpha; override; 497 822 procedure AlphaToGrayscale; override; 498 procedure ApplyMask(mask: TBGRACustomBitmap; ARect: TRect; AMaskRectTopLeft: TPoint); override; 823 procedure ApplyMask(mask: TBGRACustomBitmap; ARect: TRect; AMaskRectTopLeft: TPoint); override; overload; 499 824 procedure ApplyGlobalOpacity(alpha: byte); override; 825 procedure ApplyGlobalOpacity(ABounds: TRect; alpha: byte); override; 500 826 procedure ConvertToLinearRGB; override; 501 827 procedure ConvertFromLinearRGB; override; … … 510 836 function FilterContour: TBGRACustomBitmap; override; 511 837 function FilterPixelate(pixelSize: integer; useResample: boolean; filter: TResampleFilter = rfLinear): TBGRACustomBitmap; override; 512 function FilterBlurRadial(radius: integer; 513 blurType: TRadialBlurType): TBGRACustomBitmap; override; 514 function FilterBlurRadial(ABounds: TRect; radius: integer; 515 blurType: TRadialBlurType): TBGRACustomBitmap; override; 516 function FilterBlurMotion(distance: integer; angle: single; 517 oriented: boolean): TBGRACustomBitmap; override; 518 function FilterBlurMotion(ABounds: TRect; distance: integer; angle: single; 519 oriented: boolean): TBGRACustomBitmap; override; 838 function FilterBlurRadial(radius: single; blurType: TRadialBlurType): TBGRACustomBitmap; override; 839 function FilterBlurRadial(ABounds: TRect; radius: single; blurType: TRadialBlurType): TBGRACustomBitmap; override; 840 function FilterBlurRadial(radiusX, radiusY: single; blurType: TRadialBlurType): TBGRACustomBitmap; override; 841 function FilterBlurRadial(ABounds: TRect; radiusX, radiusY: single; blurType: TRadialBlurType): TBGRACustomBitmap; override; 842 function FilterBlurMotion(distance: single; angle: single; oriented: boolean): TBGRACustomBitmap; override; 843 function FilterBlurMotion(ABounds: TRect; distance: single; angle: single; oriented: boolean): TBGRACustomBitmap; override; 520 844 function FilterCustomBlur(mask: TBGRACustomBitmap): TBGRACustomBitmap; override; 521 845 function FilterCustomBlur(ABounds: TRect; mask: TBGRACustomBitmap): TBGRACustomBitmap; override; 522 function FilterEmboss(angle: single ): TBGRACustomBitmap; override;523 function FilterEmboss(angle: single; ABounds: TRect ): TBGRACustomBitmap; override;846 function FilterEmboss(angle: single; AStrength: integer= 64; AOptions: TEmbossOptions = []): TBGRACustomBitmap; override; 847 function FilterEmboss(angle: single; ABounds: TRect; AStrength: integer= 64; AOptions: TEmbossOptions = []): TBGRACustomBitmap; override; 524 848 function FilterEmbossHighlight(FillSelection: boolean): TBGRACustomBitmap; override; 525 849 function FilterEmbossHighlight(FillSelection: boolean; BorderColor: TBGRAPixel): TBGRACustomBitmap; override; … … 530 854 function FilterNormalize(ABounds: TRect; eachChannel: boolean = True): TBGRACustomBitmap; override; 531 855 function FilterRotate(origin: TPointF; angle: single; correctBlur: boolean = false): TBGRACustomBitmap; override; 856 function FilterAffine(AMatrix: TAffineMatrix; correctBlur: boolean = false): TBGRACustomBitmap; override; 532 857 function FilterSphere: TBGRACustomBitmap; override; 533 858 function FilterTwirl(ACenter: TPoint; ARadius: Single; ATurn: Single=1; AExponent: Single=3): TBGRACustomBitmap; override; … … 535 860 function FilterCylinder: TBGRACustomBitmap; override; 536 861 function FilterPlane: TBGRACustomBitmap; override; 537 538 property CanvasBGRA: TBGRACanvas read GetCanvasBGRA;539 property Canvas2D: TBGRACanvas2D read GetCanvas2D;540 862 end; 541 863 … … 544 866 TBGRAPtrBitmap = class(TBGRADefaultBitmap) 545 867 protected 868 function GetLineOrder: TRawImageLineOrder; override; 869 procedure SetLineOrder(AValue: TRawImageLineOrder); override; 546 870 procedure ReallocData; override; 547 871 procedure FreeData; override; 872 procedure CannotResize; 873 procedure NotImplemented; 874 procedure RebuildBitmap; override; 875 876 function CreateDefaultFontRenderer: TBGRACustomFontRenderer; override; //to override 877 function LoadFromRawImage({%H-}ARawImage: TRawImage; {%H-}DefaultOpacity: byte; 878 {%H-}AlwaysReplaceAlpha: boolean=False; {%H-}RaiseErrorOnInvalidPixelFormat: boolean 879 =True): boolean; override; //to override 548 880 public 549 881 constructor Create(AWidth, AHeight: integer; AData: Pointer); overload; 550 882 function Duplicate(DuplicateProperties: Boolean = False): TBGRACustomBitmap; override; 551 883 procedure SetDataPtr(AData: Pointer); 552 property LineOrder: TRawImageLineOrder Read FLineOrder Write FLineOrder; 884 property LineOrder: TRawImageLineOrder Read GetLineOrder Write SetLineOrder; 885 886 procedure DataDrawTransparent({%H-}ACanvas: TCanvas; {%H-}Rect: TRect; {%H-}AData: Pointer; 887 {%H-}ALineOrder: TRawImageLineOrder; {%H-}AWidth, {%H-}AHeight: integer); override; //to override 888 procedure DataDrawOpaque({%H-}ACanvas: TCanvas; {%H-}Rect: TRect; {%H-}AData: Pointer; 889 {%H-}ALineOrder: TRawImageLineOrder; {%H-}AWidth, {%H-}AHeight: integer); override; //to override 890 procedure GetImageFromCanvas({%H-}CanvasSource: TCanvas; {%H-}x, {%H-}y: integer); override; //to override 891 892 procedure Assign({%H-}Source: TPersistent); override; 893 procedure TakeScreenshot({%H-}ARect: TRect); override; 894 procedure TakeScreenshotOfPrimaryMonitor; override; 895 procedure LoadFromDevice({%H-}DC: System.THandle); override; 896 procedure LoadFromDevice({%H-}DC: System.THandle; {%H-}ARect: TRect); override; 553 897 end; 554 898 … … 560 904 gammaColorCorrection: boolean = True; Sinus: Boolean=False); 561 905 562 implementation563 564 uses Math, LCLIntf, LCLType,565 BGRABlend, BGRAFilters, BGRAText, BGRATextFX, BGRAGradientScanner,566 BGRAResample, BGRATransform, BGRAPolygon, BGRAPolygonAliased,567 BGRAPath, FPReadPcx, FPWritePcx, FPReadXPM, FPWriteXPM;568 569 906 type 907 908 { TBitmapTracker } 909 570 910 TBitmapTracker = class(TBitmap) 571 911 protected … … 576 916 end; 577 917 918 implementation 919 920 uses Math, BGRAUTF8, BGRABlend, BGRAFilters, BGRAGradientScanner, 921 BGRAResample, BGRAPolygon, BGRAPolygonAliased, 922 BGRAPath, FPReadPcx, FPWritePcx, FPReadXPM, FPWriteXPM, 923 BGRAReadBMP, BGRAReadJpeg, 924 BGRADithering, BGRAFilterScanner; 925 926 { TBitmapTracker } 927 578 928 constructor TBitmapTracker.Create(AUser: TBGRADefaultBitmap); 579 929 begin … … 592 942 593 943 function TBGRADefaultBitmap.CheckEmpty: boolean; 944 const 945 alphaMask = $ff shl TBGRAPixel_AlphaShift; 594 946 var 595 947 i: integer; … … 597 949 begin 598 950 p := Data; 599 for i := NbPixels- 1 downto 0 do600 begin 601 if p^.alpha<> 0 then951 for i := (NbPixels shr 1) - 1 downto 0 do 952 begin 953 if PInt64(p)^ and (alphaMask or (alphaMask shl 32)) <> 0 then 602 954 begin 603 955 Result := False; 604 956 exit; 605 957 end; 606 Inc(p); 958 Inc(p,2); 959 end; 960 if Odd(NbPixels) and (p^.alpha <> 0) then 961 begin 962 Result := false; 963 exit; 607 964 end; 608 965 Result := True; … … 616 973 function TBGRADefaultBitmap.GetCustomPenStyle: TBGRAPenStyle; 617 974 begin 618 result := DuplicatePenStyle(F CustomPenStyle);975 result := DuplicatePenStyle(FPenStroker.CustomPenStyle); 619 976 end; 620 977 … … 628 985 else 629 986 FCanvasOpacity := 0; 987 end; 988 989 procedure TBGRADefaultBitmap.DoLoadFromBitmap; 990 begin 991 //nothing 630 992 end; 631 993 … … 648 1010 procedure TBGRADefaultBitmap.SetCustomPenStyle(const AValue: TBGRAPenStyle); 649 1011 begin 650 F CustomPenStyle := DuplicatePenStyle(AValue);1012 FPenStroker.CustomPenStyle := DuplicatePenStyle(AValue); 651 1013 end; 652 1014 653 1015 procedure TBGRADefaultBitmap.SetPenStyle(const AValue: TPenStyle); 654 1016 begin 655 Case AValue of 656 psSolid: CustomPenStyle := SolidPenStyle; 657 psDash: CustomPenStyle := DashPenStyle; 658 psDot: CustomPenStyle := DotPenStyle; 659 psDashDot: CustomPenStyle := DashDotPenStyle; 660 psDashDotDot: CustomPenStyle := DashDotDotPenStyle; 661 else CustomPenStyle := ClearPenStyle; 662 end; 663 FPenStyle := AValue; 1017 FPenStroker.Style := AValue; 664 1018 end; 665 1019 666 1020 function TBGRADefaultBitmap.GetPenStyle: TPenStyle; 667 1021 begin 668 Result:= FPenSt yle;1022 Result:= FPenStroker.Style; 669 1023 end; 670 1024 671 1025 function TBGRADefaultBitmap.GetLineCap: TPenEndCap; 672 1026 begin 673 result := F LineCap;1027 result := FPenStroker.LineCap; 674 1028 end; 675 1029 676 1030 procedure TBGRADefaultBitmap.SetLineCap(AValue: TPenEndCap); 677 1031 begin 678 if AValue <> FLineCap then 679 begin 680 FLineCap:= AValue; 681 if Assigned(FArrow) then FArrow.LineCap := AValue; 682 end; 1032 if AValue <> FPenStroker.LineCap then 1033 begin 1034 FPenStroker.LineCap := AValue; 1035 if Assigned(FPenStroker.Arrow) then 1036 FPenStroker.Arrow.LineCap := AValue; 1037 end; 1038 end; 1039 1040 function TBGRADefaultBitmap.GetPenStroker: TBGRACustomPenStroker; 1041 begin 1042 result := FPenStroker; 683 1043 end; 684 1044 … … 771 1131 function TBGRADefaultBitmap.GetFontRenderer: TBGRACustomFontRenderer; 772 1132 begin 773 if FFontRenderer = nil then FFontRenderer := TLCLFontRenderer.Create; 1133 if FFontRenderer = nil then FFontRenderer := CreateDefaultFontRenderer; 1134 if FFontRenderer = nil then raise exception.Create('No font renderer'); 774 1135 result := FFontRenderer; 775 1136 result.FontName := FontName; … … 787 1148 end; 788 1149 1150 function TBGRADefaultBitmap.GetFontAnchorVerticalOffset: single; 1151 begin 1152 case FontVerticalAnchor of 1153 fvaTop: result := 0; 1154 fvaCenter: result := FontFullHeight*0.5; 1155 fvaCapLine: result := FontPixelMetric.CapLine; 1156 fvaCapCenter: result := (FontPixelMetric.CapLine+FontPixelMetric.Baseline)*0.5; 1157 fvaXLine: result := FontPixelMetric.xLine; 1158 fvaXCenter: result := (FontPixelMetric.xLine+FontPixelMetric.Baseline)*0.5; 1159 fvaBaseline: result := FontPixelMetric.Baseline; 1160 fvaDescentLine: result := FontPixelMetric.DescentLine; 1161 fvaBottom: result := FontFullHeight; 1162 else 1163 result := 0; 1164 end; 1165 end; 1166 1167 function TBGRADefaultBitmap.GetFontAnchorRotatedOffset: TPointF; 1168 begin 1169 result := GetFontAnchorRotatedOffset(FontOrientation); 1170 end; 1171 1172 function TBGRADefaultBitmap.GetFontAnchorRotatedOffset( 1173 ACustomOrientation: integer): TPointF; 1174 begin 1175 result := PointF(0, GetFontAnchorVerticalOffset); 1176 if ACustomOrientation <> 0 then 1177 result := AffineMatrixRotationDeg(-ACustomOrientation*0.1)*result; 1178 end; 1179 789 1180 { Get scanline without checking bounds nor updated from TBitmap } 790 1181 function TBGRADefaultBitmap.GetScanlineFast(y: integer): PBGRAPixel; inline; … … 894 1285 BGRAClass := TBGRABitmapAny(self.ClassType); 895 1286 Result := BGRAClass.Create(Filename,AIsUtf8); 1287 end; 1288 1289 function TBGRADefaultBitmap.NewBitmap(Filename: string; AIsUtf8: boolean; 1290 AOptions: TBGRALoadingOptions): TBGRACustomBitmap; 1291 var 1292 BGRAClass: TBGRABitmapAny; 1293 begin 1294 BGRAClass := TBGRABitmapAny(self.ClassType); 1295 Result := BGRAClass.Create(Filename,AIsUtf8,AOptions); 1296 end; 1297 1298 function TBGRADefaultBitmap.NewBitmap(AFPImage: TFPCustomImage): TBGRACustomBitmap; 1299 var 1300 BGRAClass: TBGRABitmapAny; 1301 begin 1302 BGRAClass := TBGRABitmapAny(self.ClassType); 1303 Result := BGRAClass.Create(AFPImage); 1304 end; 1305 1306 procedure TBGRADefaultBitmap.LoadFromStream(Str: TStream; 1307 Handler: TFPCustomImageReader; AOptions: TBGRALoadingOptions); 1308 var OldBmpOption: TBMPTransparencyOption; 1309 OldJpegPerf: TJPEGReadPerformance; 1310 begin 1311 if (loBmpAutoOpaque in AOptions) and (Handler is TBGRAReaderBMP) then 1312 begin 1313 OldBmpOption := TBGRAReaderBMP(Handler).TransparencyOption; 1314 TBGRAReaderBMP(Handler).TransparencyOption := toAuto; 1315 inherited LoadFromStream(Str, Handler, AOptions); 1316 TBGRAReaderBMP(Handler).TransparencyOption := OldBmpOption; 1317 end else 1318 if (loJpegQuick in AOptions) and (Handler is TBGRAReaderJpeg) then 1319 begin 1320 OldJpegPerf := TBGRAReaderJpeg(Handler).Performance; 1321 TBGRAReaderJpeg(Handler).Performance := jpBestSpeed; 1322 inherited LoadFromStream(Str, Handler, AOptions); 1323 TBGRAReaderJpeg(Handler).Performance := OldJpegPerf; 1324 end else 1325 inherited LoadFromStream(Str, Handler, AOptions); 896 1326 end; 897 1327 … … 919 1349 FWidth := AWidth; 920 1350 FHeight := AHeight; 1351 FScanWidth := FWidth; 1352 FScanHeight:= FHeight; 921 1353 FNbPixels := AWidth * AHeight; 922 1354 if FNbPixels < 0 then // 2 Go limit … … 936 1368 end; 937 1369 1370 constructor TBGRADefaultBitmap.Create(AFPImage: TFPCustomImage); 1371 begin 1372 Init; 1373 inherited Create(AFPImage.Width, AFPImage.Height); 1374 Assign(AFPImage); 1375 end; 1376 938 1377 { Creates an image of dimensions AWidth and AHeight and filled with transparent pixels. } 939 constructor TBGRADefaultBitmap.Create(ABitmap: TBitmap );1378 constructor TBGRADefaultBitmap.Create(ABitmap: TBitmap; AUseTransparent: boolean); 940 1379 begin 941 1380 Init; 942 1381 inherited Create(ABitmap.Width, ABitmap.Height); 943 Assign(ABitmap );1382 Assign(ABitmap, AUseTransparent); 944 1383 end; 945 1384 … … 973 1412 destructor TBGRADefaultBitmap.Destroy; 974 1413 begin 975 F reeData;1414 FPenStroker.Free; 976 1415 FFontRenderer.Free; 977 FBitmap.Free;978 1416 FCanvasFP.Free; 979 1417 FCanvasBGRA.Free; 980 1418 FCanvas2D.Free; 981 FArrow.Free; 1419 FreeData; 1420 FreeBitmap; 982 1421 inherited Destroy; 983 1422 end; … … 997 1436 end; 998 1437 1438 constructor TBGRADefaultBitmap.Create(AFilename: string; AIsUtf8: boolean; 1439 AOptions: TBGRALoadingOptions); 1440 begin 1441 Init; 1442 inherited Create(0, 0); 1443 if AIsUtf8 then 1444 LoadFromFileUTF8(Afilename, AOptions) 1445 else 1446 LoadFromFile(Afilename, AOptions); 1447 end; 1448 999 1449 { Creates an image by loading its content from the stream AStream. } 1000 1450 constructor TBGRADefaultBitmap.Create(AStream: TStream); … … 1003 1453 inherited Create(0, 0); 1004 1454 LoadFromStream(AStream); 1005 end;1006 1007 procedure TBGRADefaultBitmap.Assign(ARaster: TRasterImage);1008 var TempBmp: TBitmap;1009 ConvertOk: boolean;1010 begin1011 DiscardBitmapChange;1012 SetSize(ARaster.Width, ARaster.Height);1013 if not LoadFromRawImage(ARaster.RawImage,0,False,False) then1014 if ARaster is TBitmap then1015 begin //try to convert1016 TempBmp := TBitmap.Create;1017 TempBmp.Width := ARaster.Width;1018 TempBmp.Height := ARaster.Height;1019 TempBmp.Canvas.Draw(0,0,ARaster);1020 ConvertOk := LoadFromRawImage(TempBmp.RawImage,0,False,False);1021 TempBmp.Free;1022 if not ConvertOk then1023 raise Exception.Create('Unable to convert image to 24 bit');1024 end else1025 raise Exception.Create('Unable to convert image to 24 bit');1026 If Empty then AlphaFill(255); // if bitmap seems to be empty, assume1027 // it is an opaque bitmap without alpha channel1028 end;1029 1030 procedure TBGRADefaultBitmap.Assign(MemBitmap: TBGRACustomBitmap);1031 begin1032 DiscardBitmapChange;1033 SetSize(MemBitmap.Width, MemBitmap.Height);1034 PutImage(0, 0, MemBitmap, dmSet);1035 1455 end; 1036 1456 … … 1042 1462 AStream.Write(lWidth,sizeof(lWidth)); 1043 1463 AStream.Write(lHeight,sizeof(lHeight)); 1464 If TBGRAPixel_RGBAOrder then TBGRAFilterScannerSwapRedBlue.ComputeFilterAt(FData,FData,FNbPixels,False); 1044 1465 for y := 0 to Height-1 do 1045 1466 AStream.Write(ScanLine[y]^, Width*sizeof(TBGRAPixel)); 1046 end;1047 1048 {$hints off} 1467 If TBGRAPixel_RGBAOrder then TBGRAFilterScannerSwapRedBlue.ComputeFilterAt(FData,FData,FNbPixels,False); 1468 end; 1469 1049 1470 procedure TBGRADefaultBitmap.Deserialize(AStream: TStream); 1050 1471 var lWidth,lHeight,y: integer; 1051 1472 begin 1052 AStream.Read( lWidth,sizeof(lWidth));1053 AStream.Read( lHeight,sizeof(lHeight));1473 AStream.Read({%H-}lWidth,sizeof(lWidth)); 1474 AStream.Read({%H-}lHeight,sizeof(lHeight)); 1054 1475 lWidth := LEtoN(lWidth); 1055 1476 lHeight := LEtoN(lHeight); … … 1057 1478 for y := 0 to Height-1 do 1058 1479 AStream.Read(ScanLine[y]^, Width*sizeof(TBGRAPixel)); 1059 end; 1060 {$hints on} 1480 If TBGRAPixel_RGBAOrder then TBGRAFilterScannerSwapRedBlue.ComputeFilterAt(FData,FData,FNbPixels,False); 1481 InvalidateBitmap; 1482 end; 1061 1483 1062 1484 class procedure TBGRADefaultBitmap.SerializeEmpty(AStream: TStream); … … 1068 1490 end; 1069 1491 1070 procedure TBGRADefaultBitmap.SaveToFile(const filename: string); 1071 var 1072 ext: string; 1073 writer: TFPCustomImageWriter; 1074 begin 1075 ext := AnsiLowerCase(ExtractFileExt(filename)); 1076 1077 { When saving to PNG, define some parameters so that the 1078 image be readable by most programs } 1079 if ext = '.png' then 1080 writer := CreateAdaptedPngWriter 1081 else 1082 if (ext='.xpm') and (Width*Height > 32768) then //xpm is slow so avoid big images 1083 raise exception.Create('Image is too big to be saved as XPM') else 1084 writer := nil; 1085 1086 if writer <> nil then //use custom writer if defined 1087 begin 1088 inherited SaveToFile(Filename, writer); 1089 writer.Free; 1090 end 1091 else 1092 inherited SaveToFile(Filename); 1093 end; 1094 1095 procedure TBGRADefaultBitmap.SaveToStreamAsPng(Str: TStream); 1096 var writer: TFPWriterPNG; 1097 begin 1098 writer := CreateAdaptedPngWriter; 1099 SaveToStream(Str,writer); 1100 writer.Free; 1492 procedure TBGRADefaultBitmap.Assign(Source: TPersistent); 1493 var pdest: PBGRAPixel; 1494 x,y: NativeInt; 1495 begin 1496 if Source is TBGRACustomBitmap then 1497 begin 1498 DiscardBitmapChange; 1499 SetSize(TBGRACustomBitmap(Source).Width, TBGRACustomBitmap(Source).Height); 1500 PutImage(0, 0, TBGRACustomBitmap(Source), dmSet); 1501 end else 1502 if Source is TFPCustomImage then 1503 begin 1504 DiscardBitmapChange; 1505 SetSize(TFPCustomImage(Source).Width, TFPCustomImage(Source).Height); 1506 for y := 0 to TFPCustomImage(Source).Height-1 do 1507 begin 1508 pdest := ScanLine[y]; 1509 for x := 0 to TFPCustomImage(Source).Width-1 do 1510 begin 1511 pdest^ := FPColorToBGRA(TFPCustomImage(Source).Colors[x,y]); 1512 inc(pdest); 1513 end; 1514 end; 1515 end else 1516 inherited Assign(Source); 1517 end; 1518 1519 procedure TBGRADefaultBitmap.Assign(Source: TBitmap; AUseTransparent: boolean); 1520 var 1521 transpColor: TBGRAPixel; 1522 begin 1523 Assign(Source); 1524 if AUseTransparent and TBitmap(Source).Transparent then 1525 begin 1526 if TBitmap(Source).TransparentMode = tmFixed then 1527 transpColor := ColorToBGRA(TBitmap(Source).TransparentColor) 1528 else 1529 transpColor := GetPixel(0,Height-1); 1530 ReplaceColor(transpColor, BGRAPixelTransparent); 1531 end; 1101 1532 end; 1102 1533 … … 1132 1563 iFactY: int32or64): TBGRAPixel; 1133 1564 var 1134 ixMod1,ixMod2: int32or64; 1135 w1,w2,w3,w4,alphaW: UInt32or64; 1136 bSum, gSum, rSum: UInt32or64; 1137 aSum: UInt32or64; 1138 1139 c: TBGRAPixel; 1565 ixMod2: int32or64; 1566 pUpLeft, pUpRight, pDownLeft, pDownRight: PBGRAPixel; 1140 1567 scan: PBGRAPixel; 1141 1568 begin 1142 w4 := (iFactX*iFactY+127) shr 8;1143 w3 := iFactY-w4;1144 w1 := cardinal(256-iFactX)-w3;1145 w2 := iFactX-w4;1146 1147 rSum := 0;1148 gSum := 0;1149 bSum := 0;1150 aSum := 0;1151 1152 1569 scan := GetScanlineFast(iy); 1153 1570 1154 ixMod1 := ix; 1155 c := (scan + ix)^; 1156 alphaW := c.alpha * w1; 1157 aSum += alphaW; 1158 1159 rSum += c.red * alphaW; 1160 gSum += c.green * alphaW; 1161 bSum += c.blue * alphaW; 1162 1571 pUpLeft := (scan + ix); 1163 1572 ixMod2 := ix+1; 1164 1573 if ixMod2=Width then ixMod2 := 0; 1165 c := (scan + ixMod2)^; 1166 alphaW := c.alpha * w2; 1167 aSum += alphaW; 1168 1169 rSum += c.red * alphaW; 1170 gSum += c.green * alphaW; 1171 bSum += c.blue * alphaW; 1574 pUpRight := (scan + ixMod2); 1172 1575 1173 1576 Inc(iy); 1174 1577 if iy = Height then iy := 0; 1175 1578 scan := GetScanlineFast(iy); 1176 1177 c := (scan + ixMod2)^; 1178 alphaW := c.alpha * w4; 1179 aSum += alphaW; 1180 1181 rSum += c.red * alphaW; 1182 gSum += c.green * alphaW; 1183 bSum += c.blue * alphaW; 1184 1185 c := (scan + ixMod1)^; 1186 alphaW := c.alpha * w3; 1187 aSum += alphaW; 1188 1189 rSum += c.red * alphaW; 1190 gSum += c.green * alphaW; 1191 bSum += c.blue * alphaW; 1192 1193 if (aSum < 128) then 1194 Result := BGRAPixelTransparent 1195 else 1196 begin 1197 Result.red := (rSum + aSum shr 1) div aSum; 1198 Result.green := (gSum + aSum shr 1) div aSum; 1199 Result.blue := (bSum + aSum shr 1) div aSum; 1200 Result.alpha := (aSum + 128) shr 8; 1201 end; 1579 pDownLeft := (scan + ix); 1580 pDownRight := (scan + ixMod2); 1581 1582 InterpolateBilinear(pUpLeft, pUpRight, pDownLeft, 1583 pDownRight, iFactX, iFactY, @result); 1202 1584 end; 1203 1585 … … 1205 1587 iFactY: int32or64; smoothBorder: boolean): TBGRAPixel; 1206 1588 var 1207 w1,w2,w3,w4,alphaW: cardinal; 1208 rSum, gSum, bSum: cardinal; //rgbDiv = aSum 1209 aSum, aDiv: cardinal; 1210 c: TBGRAPixel; 1589 pUpLeft, pUpRight, pDownLeft, pDownRight: PBGRAPixel; 1211 1590 scan: PBGRAPixel; 1212 1591 begin 1213 rSum := 0;1214 gSum := 0;1215 bSum := 0;1216 aSum := 0;1217 aDiv := 0;1218 1219 w4 := (iFactX*iFactY+127) shr 8;1220 w3 := iFactY-w4;1221 {$PUSH}{$HINTS OFF}1222 w1 := (256-iFactX)-w3;1223 {$POP}1224 w2 := iFactX-w4;1225 1226 { For each pixel around the coordinate, compute1227 the weight for it and multiply values by it before1228 adding to the sum }1229 1592 if (iy >= 0) and (iy < Height) then 1230 1593 begin … … 1232 1595 1233 1596 if (ix >= 0) and (ix < Width) then 1234 begin 1235 c := (scan + ix)^; 1236 alphaW := c.alpha * w1; 1237 aDiv += w1; 1238 aSum += alphaW; 1239 rSum += c.red * alphaW; 1240 gSum += c.green * alphaW; 1241 bSum += c.blue * alphaW; 1242 end; 1243 1244 Inc(ix); 1597 pUpLeft := scan+ix 1598 else if smoothBorder then 1599 pUpLeft := @BGRAPixelTransparent 1600 else 1601 pUpLeft := nil; 1602 1603 if (ix+1 >= 0) and (ix+1 < Width) then 1604 pUpRight := scan+(ix+1) 1605 else if smoothBorder then 1606 pUpRight := @BGRAPixelTransparent 1607 else 1608 pUpRight := nil; 1609 end else 1610 if smoothBorder then 1611 begin 1612 pUpLeft := @BGRAPixelTransparent; 1613 pUpRight := @BGRAPixelTransparent; 1614 end else 1615 begin 1616 pUpLeft := nil; 1617 pUpRight := nil; 1618 end; 1619 1620 if (iy+1 >= 0) and (iy+1 < Height) then 1621 begin 1622 scan := GetScanlineFast(iy+1); 1623 1245 1624 if (ix >= 0) and (ix < Width) then 1246 begin 1247 c := (scan + ix)^; 1248 alphaW := c.alpha * w2; 1249 aDiv += w2; 1250 aSum += alphaW; 1251 rSum += c.red * alphaW; 1252 gSum += c.green * alphaW; 1253 bSum += c.blue * alphaW; 1254 end; 1255 end 1256 else 1257 begin 1258 Inc(ix); 1259 end; 1260 1261 Inc(iy); 1262 if (iy >= 0) and (iy < Height) then 1263 begin 1264 scan := GetScanlineFast(iy); 1265 1266 if (ix >= 0) and (ix < Width) then 1267 begin 1268 c := (scan + ix)^; 1269 alphaW := c.alpha * w4; 1270 aDiv += w4; 1271 aSum += alphaW; 1272 rSum += c.red * alphaW; 1273 gSum += c.green * alphaW; 1274 bSum += c.blue * alphaW; 1275 end; 1276 1277 Dec(ix); 1278 if (ix >= 0) and (ix < Width) then 1279 begin 1280 c := (scan + ix)^; 1281 alphaW := c.alpha * w3; 1282 aDiv += w3; 1283 aSum += alphaW; 1284 rSum += c.red * alphaW; 1285 gSum += c.green * alphaW; 1286 bSum += c.blue * alphaW; 1287 end; 1288 end; 1289 1290 if aSum < 128 then //if there is no alpha 1291 Result := BGRAPixelTransparent 1292 else 1293 begin 1294 Result.red := (rSum + aSum shr 1) div aSum; 1295 Result.green := (gSum + aSum shr 1) div aSum; 1296 Result.blue := (bSum + aSum shr 1) div aSum; 1297 if smoothBorder or (aDiv = 256) then 1298 Result.alpha := (aSum + 128) shr 8 1625 pDownLeft := scan+ix 1626 else if smoothBorder then 1627 pDownLeft := @BGRAPixelTransparent 1299 1628 else 1300 Result.alpha := (aSum + aDiv shr 1) div aDiv; 1301 end; 1302 end; 1303 1304 function TBGRADefaultBitmap.GetPolyLineOption: TBGRAPolyLineOptions; 1305 begin 1306 result := []; 1307 if Assigned(FArrow) and FArrow.IsStartDefined then result += [plNoStartCap]; 1308 if Assigned(FArrow) and FArrow.IsEndDefined then result += [plNoEndCap]; 1629 pDownLeft := nil; 1630 1631 if (ix+1 >= 0) and (ix+1 < Width) then 1632 pDownRight := scan+(ix+1) 1633 else if smoothBorder then 1634 pDownRight := @BGRAPixelTransparent 1635 else 1636 pDownRight := nil; 1637 end else 1638 if smoothBorder then 1639 begin 1640 pDownLeft := @BGRAPixelTransparent; 1641 pDownRight := @BGRAPixelTransparent; 1642 end else 1643 begin 1644 pDownLeft := nil; 1645 pDownRight := nil; 1646 end; 1647 1648 InterpolateBilinear(pUpLeft, pUpRight, pDownLeft, 1649 pDownRight, iFactX, iFactY, @result); 1309 1650 end; 1310 1651 1311 1652 function TBGRADefaultBitmap.GetArrow: TBGRAArrow; 1312 1653 begin 1313 if FArrow = nil then 1314 begin 1315 FArrow := TBGRAArrow.Create; 1316 FArrow.LineCap := LineCap; 1317 end; 1318 result := FArrow; 1654 if FPenStroker.Arrow = nil then 1655 begin 1656 FPenStroker.Arrow := TBGRAArrow.Create; 1657 FPenStroker.Arrow.LineCap := LineCap; 1658 FPenStroker.ArrowOwned := true; 1659 end; 1660 result := FPenStroker.Arrow as TBGRAArrow; 1319 1661 end; 1320 1662 … … 1342 1684 procedure TBGRADefaultBitmap.SetPixel(x, y: int32or64; c: TColor); 1343 1685 var 1344 p: PB yte;1686 p: PBGRAPixel; 1345 1687 begin 1346 1688 if not PtInClipRect(x,y) then exit; 1347 1689 LoadFromBitmapIfNeeded; 1348 p := PByte(GetScanlineFast(y) + x); 1349 p^ := c shr 16; 1350 Inc(p); 1351 p^ := c shr 8; 1352 Inc(p); 1353 p^ := c; 1354 Inc(p); 1355 p^ := 255; 1690 p := GetScanlineFast(y) + x; 1691 RedGreenBlue(c, p^.red,p^.green,p^.blue); 1692 p^.alpha := 255; 1356 1693 InvalidateBitmap; 1357 1694 end; … … 1639 1976 end; 1640 1977 1641 { Load raw image data. It must be 32bit or 24 bits per pixel}1642 function TBGRADefaultBitmap.LoadFromRawImage(ARawImage: TRawImage;1643 DefaultOpacity: byte; AlwaysReplaceAlpha: boolean; RaiseErrorOnInvalidPixelFormat: boolean): boolean;1644 var1645 psource_byte, pdest_byte,1646 psource_first, pdest_first: PByte;1647 psource_delta, pdest_delta: integer;1648 1649 n: integer;1650 mustSwapRedBlue, mustReverse32: boolean;1651 1652 procedure CopyAndSwapIfNecessary(psrc: PBGRAPixel; pdest: PBGRAPixel; count: integer);1653 begin1654 if mustReverse32 then1655 begin1656 while count > 0 do1657 begin1658 pdest^.blue := psrc^.alpha;1659 pdest^.green := psrc^.red;1660 pdest^.red := psrc^.green;1661 pdest^.alpha := psrc^.blue;1662 dec(count);1663 inc(pdest);1664 inc(psrc);1665 end;1666 end else1667 if mustSwapRedBlue then1668 begin1669 while count > 0 do1670 begin1671 pdest^.red := psrc^.blue;1672 pdest^.green := psrc^.green;1673 pdest^.blue := psrc^.red;1674 pdest^.alpha := psrc^.alpha;1675 dec(count);1676 inc(pdest);1677 inc(psrc);1678 end;1679 end else1680 move(psrc^,pdest^,count*sizeof(TBGRAPixel));1681 end;1682 1683 procedure CopyRGBAndSwapIfNecessary(psrc: PByte; pdest: PBGRAPixel; count: integer);1684 begin1685 if mustSwapRedBlue then1686 begin1687 while count > 0 do1688 begin1689 pdest^.blue := (psrc+2)^;1690 pdest^.green := (psrc+1)^;1691 pdest^.red := psrc^;1692 pdest^.alpha := DefaultOpacity;1693 inc(psrc,3);1694 inc(pdest);1695 dec(count);1696 end;1697 end else1698 begin1699 while count > 0 do1700 begin1701 PWord(pdest)^ := PWord(psrc)^;1702 pdest^.red := (psrc+2)^;1703 pdest^.alpha := DefaultOpacity;1704 inc(psrc,3);1705 inc(pdest);1706 dec(count);1707 end;1708 end;1709 end;1710 1711 procedure CopyAndSwapIfNecessaryAndSetAlpha(psrc: PBGRAPixel; pdest: PBGRAPixel; count: integer);1712 begin1713 if mustReverse32 then1714 begin1715 while count > 0 do1716 begin1717 pdest^.blue := psrc^.alpha;1718 pdest^.green := psrc^.red;1719 pdest^.red := psrc^.green;1720 pdest^.alpha := DefaultOpacity; //use default opacity1721 inc(psrc);1722 inc(pdest);1723 dec(count);1724 end;1725 end else1726 if mustSwapRedBlue then1727 begin1728 while count > 0 do1729 begin1730 pdest^.red := psrc^.blue;1731 pdest^.green := psrc^.green;1732 pdest^.blue := psrc^.red;1733 pdest^.alpha := DefaultOpacity; //use default opacity1734 inc(psrc);1735 inc(pdest);1736 dec(count);1737 end;1738 end else1739 begin1740 while count > 0 do1741 begin1742 PWord(pdest)^ := PWord(psrc)^;1743 pdest^.red := psrc^.red;1744 pdest^.alpha := DefaultOpacity; //use default opacity1745 inc(psrc);1746 inc(pdest);1747 dec(count);1748 end;1749 end;1750 end;1751 1752 procedure CopyAndSwapIfNecessaryAndReplaceAlpha(psrc: PBGRAPixel; pdest: PBGRAPixel; count: integer);1753 var OpacityOrMask, OpacityAndMask, sourceval: Longword;1754 begin1755 OpacityOrMask := NtoLE(longword(DefaultOpacity) shl 24);1756 OpacityAndMask := NtoLE($FFFFFF);1757 if mustReverse32 then1758 begin1759 OpacityAndMask := NtoBE($FFFFFF);1760 while count > 0 do1761 begin1762 sourceval := plongword(psrc)^ and OpacityAndMask;1763 if (sourceval <> 0) and (psrc^.blue{=alpha} = 0) then //if not black but transparent1764 begin1765 pdest^.blue := psrc^.alpha;1766 pdest^.green := psrc^.red;1767 pdest^.red := psrc^.green;1768 pdest^.alpha := DefaultOpacity; //use default opacity1769 end1770 else1771 begin1772 pdest^.blue := psrc^.alpha;1773 pdest^.green := psrc^.red;1774 pdest^.red := psrc^.green;1775 pdest^.alpha := psrc^.blue;1776 end;1777 dec(count);1778 inc(pdest);1779 inc(psrc);1780 end;1781 end else1782 if mustSwapRedBlue then1783 begin1784 while count > 0 do1785 begin1786 sourceval := plongword(psrc)^ and OpacityAndMask;1787 if (sourceval <> 0) and (psrc^.alpha = 0) then //if not black but transparent1788 begin1789 pdest^.red := psrc^.blue;1790 pdest^.green := psrc^.green;1791 pdest^.blue := psrc^.red;1792 pdest^.alpha := DefaultOpacity; //use default opacity1793 end1794 else1795 begin1796 pdest^.red := psrc^.blue;1797 pdest^.green := psrc^.green;1798 pdest^.blue := psrc^.red;1799 pdest^.alpha := psrc^.alpha;1800 end;1801 dec(count);1802 inc(pdest);1803 inc(psrc);1804 end;1805 end else1806 begin1807 while count > 0 do1808 begin1809 sourceval := plongword(psrc)^ and OpacityAndMask;1810 if (sourceval <> 0) and (psrc^.alpha = 0) then //if not black but transparent1811 plongword(pdest)^ := sourceval or OpacityOrMask //use default opacity1812 else1813 pdest^ := psrc^;1814 dec(count);1815 inc(pdest);1816 inc(psrc);1817 end;1818 end;1819 end;1820 1821 begin1822 if (ARawImage.Description.Width <> cardinal(Width)) or1823 (ARawImage.Description.Height <> cardinal(Height)) then1824 raise Exception.Create('Bitmap size is inconsistant');1825 1826 DiscardBitmapChange;1827 if (Height=0) or (Width=0) then1828 begin1829 result := true;1830 exit;1831 end;1832 1833 if ARawImage.Description.LineOrder = riloTopToBottom then1834 begin1835 psource_first := ARawImage.Data;1836 psource_delta := ARawImage.Description.BytesPerLine;1837 end else1838 begin1839 psource_first := ARawImage.Data + (ARawImage.Description.Height-1) * ARawImage.Description.BytesPerLine;1840 psource_delta := -ARawImage.Description.BytesPerLine;1841 end;1842 1843 if ((ARawImage.Description.RedShift = 0) and1844 (ARawImage.Description.BlueShift = 16) and1845 (ARawImage.Description.ByteOrder = riboLSBFirst)) or1846 ((ARawImage.Description.RedShift = 24) and1847 (ARawImage.Description.BlueShift = 8) and1848 (ARawImage.Description.ByteOrder = riboMSBFirst)) then1849 begin1850 mustSwapRedBlue:= true;1851 mustReverse32 := false;1852 end1853 else1854 begin1855 mustSwapRedBlue:= false;1856 if ((ARawImage.Description.RedShift = 8) and1857 (ARawImage.Description.GreenShift = 16) and1858 (ARawImage.Description.BlueShift = 24) and1859 (ARawImage.Description.ByteOrder = riboLSBFirst)) or1860 ((ARawImage.Description.RedShift = 16) and1861 (ARawImage.Description.GreenShift = 8) and1862 (ARawImage.Description.BlueShift = 0) and1863 (ARawImage.Description.ByteOrder = riboMSBFirst)) then1864 mustReverse32 := true1865 else1866 mustReverse32 := false;1867 end;1868 1869 if self.LineOrder = riloTopToBottom then1870 begin1871 pdest_first := PByte(self.Data);1872 pdest_delta := self.Width*sizeof(TBGRAPixel);1873 end else1874 begin1875 pdest_first := PByte(self.Data) + (self.Height-1)*self.Width*sizeof(TBGRAPixel);1876 pdest_delta := -self.Width*sizeof(TBGRAPixel);1877 end;1878 1879 { 32 bits per pixel }1880 if (ARawImage.Description.BitsPerPixel = 32) and1881 (ARawImage.DataSize >= longword(NbPixels) * 4) then1882 begin1883 { If there is an alpha channel }1884 if (ARawImage.Description.AlphaPrec = 8) and not AlwaysReplaceAlpha then1885 begin1886 if DefaultOpacity = 0 then1887 begin1888 if ARawImage.Description.LineOrder = FLineOrder then1889 CopyAndSwapIfNecessary(PBGRAPixel(ARawImage.Data), FData, NbPixels) else1890 begin1891 psource_byte := psource_first;1892 pdest_byte := pdest_first;1893 for n := FHeight-1 downto 0 do1894 begin1895 CopyAndSwapIfNecessary(PBGRAPixel(psource_byte), PBGRAPixel(pdest_byte), FWidth);1896 inc(psource_byte, psource_delta);1897 inc(pdest_byte, pdest_delta);1898 end;1899 end;1900 end1901 else1902 begin1903 psource_byte := psource_first;1904 pdest_byte := pdest_first;1905 for n := FHeight-1 downto 0 do1906 begin1907 CopyAndSwapIfNecessaryAndReplaceAlpha(PBGRAPixel(psource_byte), PBGRAPixel(pdest_byte), FWidth);1908 inc(psource_byte, psource_delta);1909 inc(pdest_byte, pdest_delta);1910 end;1911 end;1912 end1913 else1914 begin { If there isn't any alpha channel }1915 psource_byte := psource_first;1916 pdest_byte := pdest_first;1917 for n := FHeight-1 downto 0 do1918 begin1919 CopyAndSwapIfNecessaryAndSetAlpha(PBGRAPixel(psource_byte), PBGRAPixel(pdest_byte), FWidth);1920 inc(psource_byte, psource_delta);1921 inc(pdest_byte, pdest_delta);1922 end;1923 end;1924 end1925 else1926 { 24 bit per pixel }1927 if (ARawImage.Description.BitsPerPixel = 24) then1928 begin1929 psource_byte := psource_first;1930 pdest_byte := pdest_first;1931 for n := FHeight-1 downto 0 do1932 begin1933 CopyRGBAndSwapIfNecessary(psource_byte, PBGRAPixel(pdest_byte), FWidth);1934 inc(psource_byte, psource_delta);1935 inc(pdest_byte, pdest_delta);1936 end;1937 end1938 else1939 begin1940 if RaiseErrorOnInvalidPixelFormat then1941 raise Exception.Create('Invalid raw image format (' + IntToStr(1942 ARawImage.Description.Depth) + ' found)') else1943 begin1944 result := false;1945 exit;1946 end;1947 end;1948 1949 InvalidateBitmap;1950 result := true;1951 end;1952 1953 1978 procedure TBGRADefaultBitmap.LoadFromBitmapIfNeeded; 1954 1979 begin 1955 1980 if FBitmapModified then 1956 1981 begin 1957 if FBitmap <> nil then 1958 LoadFromRawImage(FBitmap.RawImage, FCanvasOpacity); 1982 DoLoadFromBitmap; 1959 1983 DiscardBitmapChange; 1960 1984 end; … … 2024 2048 FWidth := 0; 2025 2049 FHeight := 0; 2050 FScanWidth := FWidth; 2051 FScanHeight:= FHeight; 2026 2052 FLineOrder := riloTopToBottom; 2027 2053 FCanvasOpacity := 255; … … 2033 2059 FontStyle := []; 2034 2060 FontAntialias := False; 2061 FontVerticalAnchor:= fvaTop; 2035 2062 FFontHeight := 20; 2036 2063 2037 PenStyle := psSolid;2038 LineCap := pecRound;2039 JoinStyle := pjsBevel;2040 JoinMiterLimit := 2;2041 2064 ResampleFilter := rfHalfCosine; 2042 2065 ScanInterpolationFilter := rfLinear; 2043 2066 ScanOffset := Point(0,0); 2067 2068 FPenStroker := TBGRAPenStroker.Create; 2069 FPenStroker.Arrow := TBGRAArrow.Create; 2070 FPenStroker.Arrow.LineCap := LineCap; 2071 FPenStroker.ArrowOwned := true; 2044 2072 end; 2045 2073 … … 2051 2079 function TBGRADefaultBitmap.GetInternalColor(x, y: integer): TFPColor; 2052 2080 begin 2053 if (x < 0) or (y < 0) or (x >= Width) or (y >= Height) then exit; 2054 result := BGRAToFPColor((Scanline[y] + x)^); 2081 if (x < 0) or (y < 0) or (x >= Width) or (y >= Height) then 2082 result := colTransparent 2083 else 2084 result := BGRAToFPColor((Scanline[y] + x)^); 2055 2085 end; 2056 2086 … … 2069 2099 c: TFPColor; 2070 2100 begin 2071 if (x < 0) or (y < 0) or (x >= Width) or (y >= Height) then exit; 2072 c := BGRAToFPColor((Scanline[y] + x)^); 2073 Result := palette.IndexOf(c); 2101 if (x < 0) or (y < 0) or (x >= Width) or (y >= Height) then 2102 result := 0 2103 else 2104 begin 2105 c := BGRAToFPColor((Scanline[y] + x)^); 2106 Result := palette.IndexOf(c); 2107 end; 2074 2108 end; 2075 2109 2076 2110 procedure TBGRADefaultBitmap.Draw(ACanvas: TCanvas; x, y: integer; Opaque: boolean); 2077 2111 begin 2078 if self = nil then 2079 exit; 2112 if (self = nil) or (Width = 0) or (Height = 0) then exit; 2080 2113 if Opaque then 2081 2114 DataDrawOpaque(ACanvas, Rect(X, Y, X + Width, Y + Height), Data, … … 2092 2125 procedure TBGRADefaultBitmap.Draw(ACanvas: TCanvas; Rect: TRect; Opaque: boolean); 2093 2126 begin 2094 if self = nil then 2095 exit; 2127 if (self = nil) or (Width = 0) or (Height = 0) then exit; 2096 2128 if Opaque then 2097 2129 DataDrawOpaque(ACanvas, Rect, Data, FLineOrder, FWidth, FHeight) … … 2099 2131 begin 2100 2132 LoadFromBitmapIfNeeded; 2101 if Empty then2102 exit;2103 2133 ACanvas.StretchDraw(Rect, Bitmap); 2104 2134 end; … … 2309 2339 end; 2310 2340 2311 procedure TBGRADefaultBitmap.SetArrowStart(AStyle: TBGRAArrowStyle; 2312 ATipStyle: TPenJoinStyle; ARelativePenWidth: single; ATriangleBackOffset: single); 2313 begin 2314 GetArrow.SetStart(AStyle,ATipStyle,ARelativePenWidth,ATriangleBackOffset); 2315 end; 2316 2317 procedure TBGRADefaultBitmap.SetArrowEnd(AStyle: TBGRAArrowStyle; 2318 ATipStyle: TPenJoinStyle; ARelativePenWidth: single; ATriangleBackOffset: single); 2319 begin 2320 GetArrow.SetEnd(AStyle,ATipStyle,ARelativePenWidth,ATriangleBackOffset); 2321 end; 2322 2323 procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; c: TBGRAPixel; w: single); 2324 var tempCanvas: TBGRACanvas2D; 2325 begin 2326 tempCanvas:= TBGRACanvas2D.Create(self); 2327 tempCanvas.strokeStyle(c); 2328 tempCanvas.lineWidth := w; 2329 tempCanvas.lineStyle(CustomPenStyle); 2330 tempCanvas.lineCapLCL := LineCap; 2331 tempCanvas.lineJoinLCL := JoinStyle; 2332 tempCanvas.path(APath); 2333 tempCanvas.stroke; 2334 tempCanvas.Free; 2335 end; 2336 2337 procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; texture: IBGRAScanner; w: single); 2338 var tempCanvas: TBGRACanvas2D; 2339 begin 2340 tempCanvas:= TBGRACanvas2D.Create(self); 2341 tempCanvas.strokeStyle(texture); 2342 tempCanvas.lineWidth := w; 2343 tempCanvas.lineStyle(CustomPenStyle); 2344 tempCanvas.lineCapLCL := LineCap; 2345 tempCanvas.lineJoinLCL := JoinStyle; 2346 tempCanvas.path(APath); 2347 tempCanvas.stroke; 2348 tempCanvas.Free; 2341 procedure TBGRADefaultBitmap.InternalTextOutCurved( 2342 ACursor: TBGRACustomPathCursor; sUTF8: string; AColor: TBGRAPixel; 2343 ATexture: IBGRAScanner; AAlign: TAlignment; ALetterSpacing: single); 2344 var 2345 pstr: pchar; 2346 left,charlen: integer; 2347 nextchar: string; 2348 charwidth, angle, textlen: single; 2349 begin 2350 if (ATexture = nil) and (AColor.alpha = 0) then exit; 2351 sUTF8 := CleanTextOutString(sUTF8); 2352 if sUTF8 = '' then exit; 2353 pstr := @sUTF8[1]; 2354 left := length(sUTF8); 2355 if AALign<> taLeftJustify then 2356 begin 2357 textlen := TextSize(sUTF8).cx + (UTF8Length(sUTF8)-1)*ALetterSpacing; 2358 case AAlign of 2359 taCenter: ACursor.MoveBackward(textlen*0.5); 2360 taRightJustify: ACursor.MoveBackward(textlen); 2361 end; 2362 end; 2363 while left > 0 do 2364 begin 2365 charlen := UTF8CharacterLength(pstr); 2366 setlength(nextchar, charlen); 2367 move(pstr^, nextchar[1], charlen); 2368 inc(pstr,charlen); 2369 dec(left,charlen); 2370 charwidth := TextSize(nextchar).cx; 2371 ACursor.MoveForward(charwidth); 2372 ACursor.MoveBackward(charwidth, false); 2373 ACursor.MoveForward(charwidth*0.5); 2374 with ACursor.CurrentTangent do angle := arctan2(y,x); 2375 with ACursor.CurrentCoordinate do 2376 begin 2377 if ATexture = nil then 2378 TextOutAngle(x,y, system.round(-angle*1800/Pi), nextchar, AColor, taCenter) 2379 else 2380 TextOutAngle(x,y, system.round(-angle*1800/Pi), nextchar, ATexture, taCenter); 2381 end; 2382 ACursor.MoveForward(charwidth*0.5 + ALetterSpacing); 2383 end; 2384 end; 2385 2386 procedure TBGRADefaultBitmap.InternalArc(cx, cy, rx, ry: single; StartAngleRad, 2387 EndAngleRad: Single; ABorderColor: TBGRAPixel; w: single; AFillColor: TBGRAPixel; AOptions: TArcOptions; 2388 ADrawChord: boolean; ATexture: IBGRAScanner); 2389 var 2390 pts, ptsFill: array of TPointF; 2391 temp: single; 2392 multi: TBGRAMultishapeFiller; 2393 begin 2394 if (rx = 0) or (ry = 0) then exit; 2395 if ADrawChord then AOptions := AOptions+[aoClosePath]; 2396 if not (aoFillPath in AOptions) then 2397 AFillColor := BGRAPixelTransparent; 2398 2399 if (ABorderColor.alpha = 0) and (AFillColor.alpha = 0) then exit; 2400 2401 if abs(StartAngleRad-EndAngleRad) >= 2*PI - 1e-6 then 2402 begin 2403 if aoPie in AOptions then 2404 EndAngleRad:= StartAngleRad+2*PI 2405 else 2406 EllipseAntialias(cx,cy,rx,ry,ABorderColor,w,AFillColor); 2407 exit; 2408 end; 2409 2410 if EndAngleRad < StartAngleRad then 2411 begin 2412 temp := StartAngleRad; 2413 StartAngleRad:= EndAngleRad; 2414 EndAngleRad:= temp; 2415 end; 2416 2417 pts := ComputeArcRad(cx,cy,rx,ry,StartAngleRad,EndAngleRad); 2418 if aoPie in AOptions then pts := ConcatPointsF([PointsF([PointF(cx,cy)]),pts]); 2419 2420 multi := TBGRAMultishapeFiller.Create; 2421 multi.PolygonOrder := poLastOnTop; 2422 if AFillColor.alpha <> 0 then 2423 begin 2424 if not (aoPie in AOptions) and (length(pts)>=2) then ptsFill := ConcatPointsF([PointsF([(pts[0]+pts[high(pts)])*0.5]),pts]) 2425 else ptsFill := pts; 2426 if ATexture <> nil then 2427 multi.AddPolygon(ptsFill, ATexture) 2428 else 2429 multi.AddPolygon(ptsFill, AFillColor); 2430 end; 2431 if ABorderColor.alpha <> 0 then 2432 begin 2433 if [aoPie,aoClosePath]*AOptions <> [] then 2434 multi.AddPolygon(ComputeWidePolygon(pts,w), ABorderColor) 2435 else 2436 multi.AddPolygon(ComputeWidePolyline(pts,w), ABorderColor); 2437 end; 2438 multi.Antialiasing := true; 2439 multi.Draw(self); 2440 multi.Free; 2441 end; 2442 2443 function TBGRADefaultBitmap.IsAffineRoughlyTranslation(AMatrix: TAffineMatrix; ASourceBounds: TRect): boolean; 2444 const oneOver512 = 1/512; 2445 var Orig,HAxis,VAxis: TPointF; 2446 begin 2447 Orig := AMatrix*PointF(ASourceBounds.Left,ASourceBounds.Top); 2448 if (abs(Orig.x-round(Orig.x)) > oneOver512) or 2449 (abs(Orig.y-round(Orig.y)) > oneOver512) then 2450 begin 2451 result := false; 2452 exit; 2453 end; 2454 HAxis := AMatrix*PointF(ASourceBounds.Right-1,ASourceBounds.Top); 2455 if (abs(HAxis.x - (round(Orig.x)+ASourceBounds.Right-1 - ASourceBounds.Left)) > oneOver512) or 2456 (abs(HAxis.y - round(Orig.y)) > oneOver512) then 2457 begin 2458 result := false; 2459 exit; 2460 end; 2461 VAxis := AMatrix*PointF(ASourceBounds.Left,ASourceBounds.Bottom-1); 2462 if (abs(VAxis.y - (round(Orig.y)+ASourceBounds.Bottom-1 - ASourceBounds.Top)) > oneOver512) or 2463 (abs(VAxis.x - round(Orig.x)) > oneOver512) then 2464 begin 2465 result := false; 2466 exit; 2467 end; 2468 result := true; 2349 2469 end; 2350 2470 … … 2381 2501 c: TBGRAPixel; w: single); 2382 2502 begin 2383 if Assigned(FArrow) then 2384 BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,c,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,nil,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX) 2385 else 2386 BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,c,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,nil,JoinMiterLimit); 2503 FillPolyAntialias( FPenStroker.ComputePolyline([PointF(x1,y1),PointF(x2,y2)],w,c), c); 2387 2504 end; 2388 2505 … … 2390 2507 texture: IBGRAScanner; w: single); 2391 2508 begin 2392 if Assigned(FArrow) then 2393 BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,BGRAPixelTransparent,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,texture,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX) 2394 else 2395 BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,BGRAPixelTransparent,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,texture,JoinMiterLimit); 2509 FillPolyAntialias( FPenStroker.ComputePolyline([PointF(x1,y1),PointF(x2,y2)],w), texture); 2396 2510 end; 2397 2511 2398 2512 procedure TBGRADefaultBitmap.DrawLineAntialias(x1, y1, x2, y2: single; 2399 c: TBGRAPixel; w: single; Closed: boolean); 2400 var 2401 options: TBGRAPolyLineOptions; 2402 begin 2403 if not closed then options := [plRoundCapOpen] else options := []; 2404 options += GetPolyLineOption; 2405 if Assigned(FArrow) then 2406 BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,c,pecRound,pjsRound,FCustomPenStyle,options,nil,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX) 2407 else 2408 BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,c,pecRound,pjsRound,FCustomPenStyle,options,nil,JoinMiterLimit) 2513 c: TBGRAPixel; w: single; ClosedCap: boolean); 2514 begin 2515 FillPolyAntialias( FPenStroker.ComputePolyline([PointF(x1,y1),PointF(x2,y2)],w,c,ClosedCap), c); 2409 2516 end; 2410 2517 2411 2518 procedure TBGRADefaultBitmap.DrawLineAntialias(x1, y1, x2, y2: single; 2412 texture: IBGRAScanner; w: single; Closed: boolean); 2413 var 2414 options: TBGRAPolyLineOptions; 2415 c: TBGRAPixel; 2416 begin 2417 if not closed then 2418 begin 2419 options := [plRoundCapOpen]; 2420 c := BGRAWhite; //needed for alpha junction 2421 end else 2422 begin 2423 options := []; 2424 c := BGRAPixelTransparent; 2425 end; 2426 options += GetPolyLineOption; 2427 if Assigned(FArrow) then 2428 BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,c,pecRound,pjsRound,FCustomPenStyle,options,texture,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX) 2429 else 2430 BGRAPen.BGRAPolyLine(self,[PointF(x1,y1),PointF(x2,y2)],w,c,pecRound,pjsRound,FCustomPenStyle,options,texture,JoinMiterLimit); 2519 texture: IBGRAScanner; w: single; ClosedCap: boolean); 2520 begin 2521 FillPolyAntialias( FPenStroker.ComputePolyline([PointF(x1,y1),PointF(x2,y2)],w,ClosedCap), texture); 2431 2522 end; 2432 2523 … … 2434 2525 c: TBGRAPixel; w: single); 2435 2526 begin 2436 if Assigned(FArrow) then 2437 BGRAPen.BGRAPolyLine(self,points,w,c,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,nil,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX) 2438 else 2439 BGRAPen.BGRAPolyLine(self,points,w,c,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,nil,JoinMiterLimit) 2527 FillPolyAntialias( FPenStroker.ComputePolyline(points,w,c), c); 2440 2528 end; 2441 2529 … … 2443 2531 const points: array of TPointF; texture: IBGRAScanner; w: single); 2444 2532 begin 2445 if Assigned(FArrow) then 2446 BGRAPen.BGRAPolyLine(self,points,w,BGRAPixelTransparent,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,texture,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX) 2447 else 2448 BGRAPen.BGRAPolyLine(self,points,w,BGRAPixelTransparent,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,texture,JoinMiterLimit); 2533 FillPolyAntialias( FPenStroker.ComputePolyline(points,w), texture); 2449 2534 end; 2450 2535 2451 2536 procedure TBGRADefaultBitmap.DrawPolyLineAntialias(const points: array of TPointF; 2452 c: TBGRAPixel; w: single; Closed : boolean);2453 var 2454 options: TBGRAPolyLineOptions;2455 begin 2456 if not closed then options := [plRoundCapOpen] else options := []; 2457 options += GetPolyLineOption; 2458 if Assigned(FArrow) then2459 BGRAPen.BGRAPolyLine(self,points,w,c,pecRound,JoinStyle,FCustomPenStyle,options,nil,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX)2460 else 2461 BGRAPen.BGRAPolyLine(self,points,w,c,pecRound,JoinStyle,FCustomPenStyle,options,nil,JoinMiterLimit);2537 c: TBGRAPixel; w: single; ClosedCap: boolean); 2538 begin 2539 FillPolyAntialias( FPenStroker.ComputePolyline(points,w,c,ClosedCap), c); 2540 end; 2541 2542 procedure TBGRADefaultBitmap.DrawPolyLineAntialias( 2543 const points: array of TPointF; texture: IBGRAScanner; w: single; 2544 ClosedCap: boolean); 2545 begin 2546 FillPolyAntialias( FPenStroker.ComputePolyline(points,w,ClosedCap), texture); 2462 2547 end; 2463 2548 … … 2478 2563 end; 2479 2564 2565 procedure TBGRADefaultBitmap.DrawPolyLineAntialiasAutocycle( 2566 const points: array of TPointF; c: TBGRAPixel; w: single); 2567 begin 2568 FillPolyAntialias( FPenStroker.ComputePolylineAutocycle(points,w), c); 2569 end; 2570 2571 procedure TBGRADefaultBitmap.DrawPolyLineAntialiasAutocycle( 2572 const points: array of TPointF; texture: IBGRAScanner; w: single); 2573 begin 2574 FillPolyAntialias( FPenStroker.ComputePolylineAutocycle(points,w), texture); 2575 end; 2576 2480 2577 procedure TBGRADefaultBitmap.DrawPolygonAntialias(const points: array of TPointF; 2481 2578 c: TBGRAPixel; w: single); 2482 2579 begin 2483 BGRAPolyLine(self,points,w,c,LineCap,JoinStyle,FCustomPenStyle,[plCycle],nil,JoinMiterLimit);2580 FillPolyAntialias( FPenStroker.ComputePolygon(points,w), c); 2484 2581 end; 2485 2582 … … 2487 2584 const points: array of TPointF; texture: IBGRAScanner; w: single); 2488 2585 begin 2489 BGRAPolyLine(self,points,w,BGRAPixelTransparent,LineCap,JoinStyle,FCustomPenStyle,[plCycle],texture,JoinMiterLimit);2586 FillPolyAntialias( FPenStroker.ComputePolygon(points,w), texture); 2490 2587 end; 2491 2588 … … 2534 2631 end; 2535 2632 2536 procedure TBGRADefaultBitmap.FillPath(APath: IBGRAPath; c: TBGRAPixel); 2537 var tempCanvas: TBGRACanvas2D; 2538 begin 2539 tempCanvas:= TBGRACanvas2D.Create(self); 2540 tempCanvas.fillStyle(c); 2541 tempCanvas.path(APath); 2542 tempCanvas.fill; 2543 tempCanvas.Free; 2544 end; 2545 2546 procedure TBGRADefaultBitmap.FillPath(APath: IBGRAPath; texture: IBGRAScanner); 2547 var tempCanvas: TBGRACanvas2D; 2548 begin 2549 tempCanvas:= TBGRACanvas2D.Create(self); 2550 tempCanvas.fillStyle(texture); 2551 tempCanvas.path(APath); 2552 tempCanvas.fill; 2553 tempCanvas.Free; 2633 procedure TBGRADefaultBitmap.FillPath(APath: IBGRAPath; AFillColor: TBGRAPixel); 2634 begin 2635 FillPolyAntialias(APath.getPoints,AFillColor); 2636 end; 2637 2638 procedure TBGRADefaultBitmap.FillPath(APath: IBGRAPath; AFillTexture: IBGRAScanner); 2639 begin 2640 FillPolyAntialias(APath.getPoints,AFillTexture); 2641 end; 2642 2643 procedure TBGRADefaultBitmap.ErasePath(APath: IBGRAPath; alpha: byte); 2644 begin 2645 ErasePolyAntialias(APath.getPoints,alpha); 2646 end; 2647 2648 procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; 2649 AStrokeColor: TBGRAPixel; AWidth: single; AFillColor: TBGRAPixel); 2650 var tempPath: TBGRAPath; 2651 multi: TBGRAMultishapeFiller; 2652 begin 2653 tempPath := TBGRAPath.Create(APath); 2654 multi := TBGRAMultishapeFiller.Create; 2655 multi.PolygonOrder := poLastOnTop; 2656 multi.AddPathFill(tempPath,AMatrix,AFillColor); 2657 multi.AddPathStroke(tempPath,AMatrix,AStrokeColor,AWidth,FPenStroker); 2658 multi.Draw(self); 2659 multi.Free; 2660 tempPath.Free; 2661 end; 2662 2663 procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; 2664 AStrokeTexture: IBGRAScanner; AWidth: single; AFillColor: TBGRAPixel); 2665 var tempPath: TBGRAPath; 2666 multi: TBGRAMultishapeFiller; 2667 begin 2668 tempPath := TBGRAPath.Create(APath); 2669 multi := TBGRAMultishapeFiller.Create; 2670 multi.PolygonOrder := poLastOnTop; 2671 multi.AddPathFill(tempPath,AMatrix,AFillColor); 2672 multi.AddPathStroke(tempPath,AMatrix,AStrokeTexture,AWidth,FPenStroker); 2673 multi.Draw(self); 2674 multi.Free; 2675 tempPath.Free; 2676 end; 2677 2678 procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; 2679 AStrokeColor: TBGRAPixel; AWidth: single; AFillTexture: IBGRAScanner); 2680 var tempPath: TBGRAPath; 2681 multi: TBGRAMultishapeFiller; 2682 begin 2683 tempPath := TBGRAPath.Create(APath); 2684 multi := TBGRAMultishapeFiller.Create; 2685 multi.PolygonOrder := poLastOnTop; 2686 multi.AddPathFill(tempPath,AMatrix,AFillTexture); 2687 multi.AddPathStroke(tempPath,AMatrix,AStrokeColor,AWidth,FPenStroker); 2688 multi.Draw(self); 2689 multi.Free; 2690 tempPath.Free; 2691 end; 2692 2693 procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; 2694 AStrokeTexture: IBGRAScanner; AWidth: single; AFillTexture: IBGRAScanner); 2695 var 2696 tempPath: TBGRAPath; 2697 multi: TBGRAMultishapeFiller; 2698 begin 2699 tempPath := TBGRAPath.Create(APath); 2700 multi := TBGRAMultishapeFiller.Create; 2701 multi.PolygonOrder := poLastOnTop; 2702 multi.AddPathFill(tempPath,AMatrix,AFillTexture); 2703 multi.AddPathStroke(tempPath,AMatrix,AStrokeTexture,AWidth,FPenStroker); 2704 multi.Draw(self); 2705 multi.Free; 2706 tempPath.Free; 2707 end; 2708 2709 procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; 2710 AStrokeColor: TBGRAPixel; AWidth: single); 2711 var tempPath: TBGRAPath; 2712 begin 2713 tempPath := TBGRAPath.Create(APath); 2714 tempPath.stroke(self, AMatrix, AStrokeColor, AWidth); 2715 tempPath.Free; 2716 end; 2717 2718 procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; AMatrix: TAffineMatrix; 2719 AStrokeTexture: IBGRAScanner; AWidth: single); 2720 var tempPath: TBGRAPath; 2721 begin 2722 tempPath := TBGRAPath.Create(APath); 2723 tempPath.stroke(self, AMatrix, AStrokeTexture, AWidth); 2724 tempPath.Free; 2725 end; 2726 2727 procedure TBGRADefaultBitmap.FillPath(APath: IBGRAPath; AMatrix: TAffineMatrix; 2728 AFillColor: TBGRAPixel); 2729 begin 2730 FillPolyAntialias(APath.getPoints(AMatrix),AFillColor); 2731 end; 2732 2733 procedure TBGRADefaultBitmap.FillPath(APath: IBGRAPath; AMatrix: TAffineMatrix; 2734 AFillTexture: IBGRAScanner); 2735 begin 2736 FillPolyAntialias(APath.getPoints(AMatrix),AFillTexture); 2737 end; 2738 2739 procedure TBGRADefaultBitmap.ErasePath(APath: IBGRAPath; 2740 AMatrix: TAffineMatrix; alpha: byte); 2741 begin 2742 ErasePolyAntialias(APath.getPoints(AMatrix),alpha); 2743 end; 2744 2745 procedure TBGRADefaultBitmap.ArrowStartAsNone; 2746 begin 2747 GetArrow.StartAsNone; 2748 end; 2749 2750 procedure TBGRADefaultBitmap.ArrowStartAsClassic(AFlipped: boolean; 2751 ACut: boolean; ARelativePenWidth: single); 2752 begin 2753 GetArrow.StartAsClassic(AFlipped,ACut,ARelativePenWidth); 2754 end; 2755 2756 procedure TBGRADefaultBitmap.ArrowStartAsTriangle(ABackOffset: single; 2757 ARounded: boolean; AHollow: boolean; AHollowPenWidth: single); 2758 begin 2759 GetArrow.StartAsTriangle(ABackOffset,ARounded,AHollow,AHollowPenWidth); 2760 end; 2761 2762 procedure TBGRADefaultBitmap.ArrowStartAsTail; 2763 begin 2764 GetArrow.StartAsTail; 2765 end; 2766 2767 procedure TBGRADefaultBitmap.ArrowEndAsNone; 2768 begin 2769 GetArrow.EndAsNone; 2770 end; 2771 2772 procedure TBGRADefaultBitmap.ArrowEndAsClassic(AFlipped: boolean; 2773 ACut: boolean; ARelativePenWidth: single); 2774 begin 2775 GetArrow.EndAsClassic(AFlipped,ACut,ARelativePenWidth); 2776 end; 2777 2778 procedure TBGRADefaultBitmap.ArrowEndAsTriangle(ABackOffset: single; 2779 ARounded: boolean; AHollow: boolean; AHollowPenWidth: single); 2780 begin 2781 GetArrow.EndAsTriangle(ABackOffset,ARounded,AHollow,AHollowPenWidth); 2782 end; 2783 2784 procedure TBGRADefaultBitmap.ArrowEndAsTail; 2785 begin 2786 GetArrow.EndAsTail; 2554 2787 end; 2555 2788 … … 2632 2865 2633 2866 procedure TBGRADefaultBitmap.FillQuadLinearMapping(pt1, pt2, pt3, pt4: TPointF; 2634 texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; TextureInterpolation: Boolean= True); 2635 var 2636 center: TPointF; 2637 centerTex: TPointF; 2638 begin 2639 center := (pt1+pt2+pt3+pt4)*(1/4); 2640 centerTex := (tex1+tex2+tex3+tex4)*(1/4); 2641 FillTriangleLinearMapping(pt1,pt2,center, texture,tex1,tex2,centerTex, TextureInterpolation); 2642 FillTriangleLinearMapping(pt2,pt3,center, texture,tex2,tex3,centerTex, TextureInterpolation); 2643 FillTriangleLinearMapping(pt3,pt4,center, texture,tex3,tex4,centerTex, TextureInterpolation); 2644 FillTriangleLinearMapping(pt4,pt1,center, texture,tex4,tex1,centerTex, TextureInterpolation); 2867 texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; 2868 TextureInterpolation: Boolean; ACulling: TFaceCulling); 2869 var 2870 scan: TBGRAQuadLinearScanner; 2871 begin 2872 if ((abs(pt1.y-pt2.y)<1e-6) and (abs(pt3.y-pt4.y)<1e-6)) or 2873 ((abs(pt3.y-pt2.y)<1e-6) and (abs(pt1.y-pt4.y)<1e-6)) then 2874 FillPolyLinearMapping([pt1,pt2,pt3,pt4], texture, 2875 [tex1,tex2,tex3,tex4], TextureInterpolation) 2876 else 2877 begin 2878 scan := TBGRAQuadLinearScanner.Create(texture, 2879 [tex1,tex2,tex3,tex4], 2880 [pt1,pt2,pt3,pt4],TextureInterpolation); 2881 scan.Culling := ACulling; 2882 FillPoly([pt1,pt2,pt3,pt4],scan,dmDrawWithTransparency); 2883 scan.Free; 2884 end; 2645 2885 end; 2646 2886 … … 2663 2903 2664 2904 procedure TBGRADefaultBitmap.FillQuadLinearMappingAntialias(pt1, pt2, pt3, 2665 pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); 2905 pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; 2906 ACulling: TFaceCulling); 2666 2907 var multi : TBGRAMultishapeFiller; 2667 2908 begin 2668 2909 multi := TBGRAMultishapeFiller.Create; 2669 multi.AddQuadLinearMapping(pt1, pt2, pt3, pt4, texture, tex1,tex2,tex3,tex4 );2910 multi.AddQuadLinearMapping(pt1, pt2, pt3, pt4, texture, tex1,tex2,tex3,tex4, ACulling); 2670 2911 multi.Draw(self); 2671 2912 multi.free; … … 2673 2914 2674 2915 procedure TBGRADefaultBitmap.FillQuadPerspectiveMapping(pt1, pt2, pt3, 2675 pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); 2916 pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; 2917 ADrawMode: TDrawMode); 2676 2918 var 2677 2919 persp: TBGRAPerspectiveScannerTransform; 2678 2920 begin 2679 2921 persp := TBGRAPerspectiveScannerTransform.Create(texture,[tex1,tex2,tex3,tex4],[pt1,pt2,pt3,pt4]); 2680 FillPoly([pt1,pt2,pt3,pt4],persp, dmDrawWithTransparency);2922 FillPoly([pt1,pt2,pt3,pt4],persp,ADrawMode); 2681 2923 persp.Free; 2682 2924 end; … … 2684 2926 procedure TBGRADefaultBitmap.FillQuadPerspectiveMapping(pt1, pt2, pt3, 2685 2927 pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; 2686 ACleanBorders: TRect );2928 ACleanBorders: TRect; ADrawMode: TDrawMode); 2687 2929 var 2688 2930 persp: TBGRAPerspectiveScannerTransform; … … 2691 2933 clean := TBGRAExtendedBorderScanner.Create(texture,ACleanBorders); 2692 2934 persp := TBGRAPerspectiveScannerTransform.Create(clean,[tex1,tex2,tex3,tex4],[pt1,pt2,pt3,pt4]); 2693 FillPoly([pt1,pt2,pt3,pt4],persp, dmDrawWithTransparency);2935 FillPoly([pt1,pt2,pt3,pt4],persp,ADrawMode); 2694 2936 persp.Free; 2695 2937 clean.Free; … … 2720 2962 end; 2721 2963 2964 procedure TBGRADefaultBitmap.FillQuadAffineMapping(Orig, HAxis, VAxis: TPointF; 2965 AImage: TBGRACustomBitmap; APixelCenteredCoordinates: boolean; ADrawMode: TDrawMode; AOpacity: byte); 2966 var pts3: TPointF; 2967 affine: TBGRAAffineBitmapTransform; 2968 begin 2969 if not APixelCenteredCoordinates then 2970 begin 2971 Orig -= PointF(0.5,0.5); 2972 HAxis -= PointF(0.5,0.5); 2973 VAxis -= PointF(0.5,0.5); 2974 end; 2975 pts3 := HAxis+(VAxis-Orig); 2976 affine := TBGRAAffineBitmapTransform.Create(AImage,False,AImage.ScanInterpolationFilter,not APixelCenteredCoordinates); 2977 affine.GlobalOpacity:= AOpacity; 2978 affine.Fit(Orig,HAxis,VAxis); 2979 FillPoly([Orig,HAxis,pts3,VAxis],affine,ADrawMode); 2980 affine.Free; 2981 end; 2982 2983 procedure TBGRADefaultBitmap.FillQuadAffineMappingAntialias(Orig, HAxis, 2984 VAxis: TPointF; AImage: TBGRACustomBitmap; APixelCenteredCoordinates: boolean; AOpacity: byte); 2985 var pts3: TPointF; 2986 affine: TBGRAAffineBitmapTransform; 2987 begin 2988 if not APixelCenteredCoordinates then 2989 begin 2990 Orig -= PointF(0.5,0.5); 2991 HAxis -= PointF(0.5,0.5); 2992 VAxis -= PointF(0.5,0.5); 2993 end; 2994 pts3 := HAxis+(VAxis-Orig); 2995 affine := TBGRAAffineBitmapTransform.Create(AImage,False,AImage.ScanInterpolationFilter,not APixelCenteredCoordinates); 2996 affine.GlobalOpacity:= AOpacity; 2997 affine.Fit(Orig,HAxis,VAxis); 2998 FillPolyAntialias([Orig,HAxis,pts3,VAxis],affine); 2999 affine.Free; 3000 end; 3001 2722 3002 procedure TBGRADefaultBitmap.FillPolyLinearMapping(const points: array of TPointF; 2723 3003 texture: IBGRAScanner; texCoords: array of TPointF; … … 2838 3118 end; 2839 3119 3120 procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; 3121 AStrokeColor: TBGRAPixel; AWidth: single; AFillColor: TBGRAPixel); 3122 begin 3123 DrawPath(APath,AffineMatrixIdentity,AStrokeColor,AWidth,AFillColor); 3124 end; 3125 3126 procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; 3127 AStrokeTexture: IBGRAScanner; AWidth: single; AFillColor: TBGRAPixel); 3128 begin 3129 DrawPath(APath,AffineMatrixIdentity,AStrokeTexture,AWidth,AFillColor); 3130 end; 3131 3132 procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; 3133 AStrokeColor: TBGRAPixel; AWidth: single; AFillTexture: IBGRAScanner); 3134 begin 3135 DrawPath(APath,AffineMatrixIdentity,AStrokeColor,AWidth,AFillTexture); 3136 end; 3137 3138 procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; 3139 AStrokeTexture: IBGRAScanner; AWidth: single; AFillTexture: IBGRAScanner); 3140 begin 3141 DrawPath(APath,AffineMatrixIdentity,AStrokeTexture,AWidth,AFillTexture); 3142 end; 3143 3144 procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; AStrokeColor: TBGRAPixel; AWidth: single); 3145 begin 3146 DrawPath(APath, AffineMatrixIdentity, AStrokeColor, AWidth); 3147 end; 3148 3149 procedure TBGRADefaultBitmap.DrawPath(APath: IBGRAPath; AStrokeTexture: IBGRAScanner; AWidth: single); 3150 begin 3151 DrawPath(APath, AffineMatrixIdentity, AStrokeTexture, AWidth); 3152 end; 3153 2840 3154 procedure TBGRADefaultBitmap.EllipseAntialias(x, y, rx, ry: single; 2841 3155 c: TBGRAPixel; w: single); 2842 3156 begin 2843 if IsClearPenStyle(FCustomPenStyle) or (c.alpha = 0) then exit;2844 if IsSolidPenStyle(FCustomPenStyle) then3157 if (PenStyle = psClear) or (c.alpha = 0) then exit; 3158 if (PenStyle = psSolid) then 2845 3159 BGRAPolygon.BorderEllipseAntialias(self, x, y, rx, ry, w, c, FEraseMode, LinearAntialiasing) 2846 3160 else … … 2851 3165 texture: IBGRAScanner; w: single); 2852 3166 begin 2853 if IsClearPenStyle(FCustomPenStyle) then exit;2854 if IsSolidPenStyle(FCustomPenStyle) then3167 if (PenStyle = psClear) then exit; 3168 if (PenStyle = psSolid) then 2855 3169 BGRAPolygon.BorderEllipseAntialiasWithTexture(self, x, y, rx, ry, w, texture, LinearAntialiasing) 2856 3170 else … … 2874 3188 { use multishape filler for fine junction between polygons } 2875 3189 multi := TBGRAMultishapeFiller.Create; 2876 if not IsClearPenStyle(FCustomPenStyle) and (c.alpha <> 0) then2877 begin 2878 if IsSolidPenStyle(FCustomPenStyle) then3190 if not (PenStyle = psClear) and (c.alpha <> 0) then 3191 begin 3192 if (PenStyle = psSolid) then 2879 3193 begin 2880 3194 multi.AddEllipse(x,y,rx-hw,ry-hw,back); … … 2941 3255 hw: single; 2942 3256 begin 2943 if IsClearPenStyle(FCustomPenStyle) or (c.alpha=0) or (w=0) then3257 if (PenStyle = psClear) or (c.alpha=0) or (w=0) then 2944 3258 begin 2945 3259 if back <> BGRAPixelTransparent then … … 2966 3280 multi := TBGRAMultishapeFiller.Create; 2967 3281 multi.FillMode := FillMode; 2968 if (JoinStyle = pjsMiter) and IsSolidPenStyle(FCustomPenStyle) then3282 if (JoinStyle = pjsMiter) and (PenStyle = psSolid) then 2969 3283 multi.AddRectangleBorder(x,y,x2,y2,w,c) 2970 3284 else … … 2985 3299 multi: TBGRAMultishapeFiller; 2986 3300 begin 2987 if IsClearPenStyle(FCustomPenStyle) or (w=0) then exit;3301 if (PenStyle = psClear) or (w=0) then exit; 2988 3302 2989 3303 hw := w/2; … … 3005 3319 multi := TBGRAMultishapeFiller.Create; 3006 3320 multi.FillMode := FillMode; 3007 if (JoinStyle = pjsMiter) and IsSolidPenStyle(FCustomPenStyle) then3321 if (JoinStyle = pjsMiter) and (PenStyle = psSolid) then 3008 3322 multi.AddRectangleBorder(x,y,x2,y2,w, texture) 3009 3323 else … … 3016 3330 c: TBGRAPixel; w: single; options: TRoundRectangleOptions); 3017 3331 begin 3018 if IsClearPenStyle(FCustomPenStyle) or (c.alpha = 0) then exit;3019 if IsSolidPenStyle(FCustomPenStyle) then3332 if (PenStyle = psClear) or (c.alpha = 0) then exit; 3333 if (PenStyle = psSolid) then 3020 3334 BGRAPolygon.BorderRoundRectangleAntialias(self,x,y,x2,y2,rx,ry,w,options,c,False, LinearAntialiasing) 3021 3335 else … … 3029 3343 multi: TBGRAMultishapeFiller; 3030 3344 begin 3031 if IsClearPenStyle(FCustomPenStyle) or (pencolor.alpha = 0) then3345 if (PenStyle = psClear) or (pencolor.alpha = 0) then 3032 3346 begin 3033 3347 FillRoundRectAntialias(x,y,x2,y2,rx,ry,fillColor,options); 3034 3348 exit; 3035 3349 end; 3036 if IsSolidPenStyle(FCustomPenStyle) then3350 if (PenStyle = psSolid) then 3037 3351 BGRAPolygon.BorderAndFillRoundRectangleAntialias(self,x,y,x2,y2,rx,ry,w,options,pencolor,fillcolor,nil,nil,False) 3038 3352 else … … 3053 3367 multi: TBGRAMultishapeFiller; 3054 3368 begin 3055 if IsClearPenStyle(FCustomPenStyle) then3369 if (PenStyle = psClear) then 3056 3370 begin 3057 3371 FillRoundRectAntialias(x,y,x2,y2,rx,ry,fillTexture,options); 3058 3372 exit; 3059 3373 end else 3060 if IsSolidPenStyle(FCustomPenStyle) then3374 if (PenStyle = psSolid) then 3061 3375 BGRAPolygon.BorderAndFillRoundRectangleAntialias(self,x,y,x2,y2,rx,ry,w,options,BGRAPixelTransparent,BGRAPixelTransparent,pentexture,filltexture,False) 3062 3376 else … … 3074 3388 texture: IBGRAScanner; w: single; options: TRoundRectangleOptions); 3075 3389 begin 3076 if IsClearPenStyle(FCustomPenStyle) then exit;3077 if IsSolidPenStyle(FCustomPenStyle) then3390 if (PenStyle = psClear) then exit; 3391 if (PenStyle = psSolid) then 3078 3392 BGRAPolygon.BorderRoundRectangleAntialiasWithTexture(self,x,y,x2,y2,rx,ry,w,options,texture, LinearAntialiasing) 3079 3393 else … … 3260 3574 3261 3575 procedure TBGRADefaultBitmap.FillRect(x, y, x2, y2: integer; 3262 texture: IBGRAScanner; mode: TDrawMode );3576 texture: IBGRAScanner; mode: TDrawMode; AScanOffset: TPoint); 3263 3577 var 3264 3578 yb, tx, delta: integer; … … 3278 3592 for yb := y to y2 do 3279 3593 begin 3280 texture.ScanMoveTo(x ,yb);3594 texture.ScanMoveTo(x+AScanOffset.X,yb+AScanOffset.Y); 3281 3595 ScannerPutPixels(texture, p, tx, mode); 3282 3596 Inc(p, delta); … … 3284 3598 3285 3599 InvalidateBitmap; 3600 end; 3601 3602 procedure TBGRADefaultBitmap.FillRect(x, y, x2, y2: integer; 3603 texture: IBGRAScanner; mode: TDrawMode; AScanOffset: TPoint; ditheringAlgorithm: TDitheringAlgorithm); 3604 var dither: TDitheringTask; 3605 begin 3606 if not CheckClippedRectBounds(x,y,x2,y2) then exit; 3607 dither := CreateDitheringTask(ditheringAlgorithm, texture, self, rect(x,y,x2,y2)); 3608 dither.ScanOffset := AScanOffset; 3609 dither.DrawMode := mode; 3610 dither.Execute; 3611 dither.Free; 3286 3612 end; 3287 3613 … … 3315 3641 end; 3316 3642 3317 procedure TBGRADefaultBitmap.FillRectAntialias(x, y, x2, y2: single; c: TBGRAPixel );3643 procedure TBGRADefaultBitmap.FillRectAntialias(x, y, x2, y2: single; c: TBGRAPixel; pixelCenteredCoordinates: boolean); 3318 3644 var tx,ty: single; 3319 3645 begin 3646 if not pixelCenteredCoordinates then 3647 begin 3648 x -= 0.5; 3649 y -= 0.5; 3650 x2 -= 0.5; 3651 y2 -= 0.5; 3652 end; 3653 3320 3654 tx := x2-x; 3321 3655 ty := y2-y; 3322 if ( tx=0) or (ty=0) then exit;3656 if (abs(tx)<1e-3) or (abs(ty)<1e-3) then exit; 3323 3657 if (abs(tx) > 2) and (abs(ty) > 2) then 3324 3658 begin … … 3345 3679 3346 3680 procedure TBGRADefaultBitmap.EraseRectAntialias(x, y, x2, y2: single; 3347 alpha: byte); 3348 begin 3681 alpha: byte; pixelCenteredCoordinates: boolean); 3682 begin 3683 if not pixelCenteredCoordinates then 3684 begin 3685 x -= 0.5; 3686 y -= 0.5; 3687 x2 -= 0.5; 3688 y2 -= 0.5; 3689 end; 3349 3690 ErasePolyAntialias([pointf(x, y), pointf(x2, y), pointf(x2, y2), pointf(x, y2)], alpha); 3350 3691 end; 3351 3692 3352 3693 procedure TBGRADefaultBitmap.FillRectAntialias(x, y, x2, y2: single; 3353 texture: IBGRAScanner); 3354 begin 3694 texture: IBGRAScanner; pixelCenteredCoordinates: boolean); 3695 begin 3696 if not pixelCenteredCoordinates then 3697 begin 3698 x -= 0.5; 3699 y -= 0.5; 3700 x2 -= 0.5; 3701 y2 -= 0.5; 3702 end; 3355 3703 FillPolyAntialias([pointf(x, y), pointf(x2, y), pointf(x2, y2), pointf(x, y2)], texture); 3356 3704 end; 3357 3705 3358 3706 procedure TBGRADefaultBitmap.FillRoundRectAntialias(x, y, x2, y2, rx,ry: single; 3359 c: TBGRAPixel; options: TRoundRectangleOptions); 3360 begin 3707 c: TBGRAPixel; options: TRoundRectangleOptions; pixelCenteredCoordinates: boolean); 3708 begin 3709 if not pixelCenteredCoordinates then 3710 begin 3711 x -= 0.5; 3712 y -= 0.5; 3713 x2 -= 0.5; 3714 y2 -= 0.5; 3715 end; 3361 3716 BGRAPolygon.FillRoundRectangleAntialias(self,x,y,x2,y2,rx,ry,options,c,False, LinearAntialiasing); 3362 3717 end; 3363 3718 3364 3719 procedure TBGRADefaultBitmap.FillRoundRectAntialias(x, y, x2, y2, rx, 3365 ry: single; texture: IBGRAScanner; options: TRoundRectangleOptions); 3366 begin 3720 ry: single; texture: IBGRAScanner; options: TRoundRectangleOptions; pixelCenteredCoordinates: boolean); 3721 begin 3722 if not pixelCenteredCoordinates then 3723 begin 3724 x -= 0.5; 3725 y -= 0.5; 3726 x2 -= 0.5; 3727 y2 -= 0.5; 3728 end; 3367 3729 BGRAPolygon.FillRoundRectangleAntialiasWithTexture(self,x,y,x2,y2,rx,ry,options,texture, LinearAntialiasing); 3368 3730 end; 3369 3731 3370 3732 procedure TBGRADefaultBitmap.EraseRoundRectAntialias(x, y, x2, y2, rx, 3371 ry: single; alpha: byte; options: TRoundRectangleOptions); 3372 begin 3733 ry: single; alpha: byte; options: TRoundRectangleOptions; pixelCenteredCoordinates: boolean); 3734 begin 3735 if not pixelCenteredCoordinates then 3736 begin 3737 x -= 0.5; 3738 y -= 0.5; 3739 x2 -= 0.5; 3740 y2 -= 0.5; 3741 end; 3373 3742 BGRAPolygon.FillRoundRectangleAntialias(self,x,y,x2,y2,rx,ry,options,BGRA(0,0,0,alpha),True, LinearAntialiasing); 3374 3743 end; … … 3391 3760 sUTF8: string; c: TBGRAPixel; align: TAlignment); 3392 3761 begin 3393 FontRenderer.TextOutAngle(self,x,y,orientationTenthDegCCW,CleanTextOutString(sUTF8),c,align); 3762 with (PointF(x,y)-GetFontAnchorRotatedOffset(orientationTenthDegCCW)) do 3763 FontRenderer.TextOutAngle(self,x,y,orientationTenthDegCCW,CleanTextOutString(sUTF8),c,align); 3394 3764 end; 3395 3765 … … 3397 3767 sUTF8: string; texture: IBGRAScanner; align: TAlignment); 3398 3768 begin 3399 FontRenderer.TextOutAngle(self,x,y,orientationTenthDegCCW,CleanTextOutString(sUTF8),texture,align); 3769 with (PointF(x,y)-GetFontAnchorRotatedOffset(orientationTenthDegCCW)) do 3770 FontRenderer.TextOutAngle(self,x,y,orientationTenthDegCCW,CleanTextOutString(sUTF8),texture,align); 3771 end; 3772 3773 procedure TBGRADefaultBitmap.TextOutCurved(ACursor: TBGRACustomPathCursor; sUTF8: string; AColor: TBGRAPixel; AAlign: TAlignment; ALetterSpacing: single); 3774 begin 3775 InternalTextOutCurved(ACursor, sUTF8, AColor, nil, AAlign, ALetterSpacing); 3776 end; 3777 3778 procedure TBGRADefaultBitmap.TextOutCurved(ACursor: TBGRACustomPathCursor; sUTF8: string; ATexture: IBGRAScanner; AAlign: TAlignment; ALetterSpacing: single); 3779 begin 3780 InternalTextOutCurved(ACursor, sUTF8, BGRAPixelTransparent, ATexture, AAlign, ALetterSpacing); 3400 3781 end; 3401 3782 … … 3409 3790 c: TBGRAPixel; align: TAlignment); 3410 3791 begin 3411 FontRenderer.TextOut(self,x,y,CleanTextOutString(sUTF8),c,align); 3792 with (PointF(x,y)-GetFontAnchorRotatedOffset) do 3793 FontRenderer.TextOut(self,x,y,CleanTextOutString(sUTF8),c,align); 3412 3794 end; 3413 3795 … … 3415 3797 sUTF8: string; style: TTextStyle; c: TBGRAPixel); 3416 3798 begin 3417 FontRenderer.TextRect(self,ARect,x,y,sUTF8,style,c); 3799 with (PointF(x,y)-GetFontAnchorRotatedOffset(0)) do 3800 FontRenderer.TextRect(self,ARect,system.round(x),system.round(y),sUTF8,style,c); 3418 3801 end; 3419 3802 … … 3421 3804 style: TTextStyle; texture: IBGRAScanner); 3422 3805 begin 3423 FontRenderer.TextRect(self,ARect,x,y,sUTF8,style,texture); 3806 with (PointF(x,y)-GetFontAnchorRotatedOffset(0)) do 3807 FontRenderer.TextRect(self,ARect,system.round(x),system.round(y),sUTF8,style,texture); 3424 3808 end; 3425 3809 … … 3470 3854 w: single): ArrayOfTPointF; 3471 3855 begin 3472 if Assigned(FArrow) then 3473 Result:= BGRAPen.ComputeWidePolylinePoints(points,w,BGRAWhite,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX) 3474 else 3475 Result:= BGRAPen.ComputeWidePolylinePoints(points,w,BGRAWhite,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption,JoinMiterLimit) 3856 result := FPenStroker.ComputePolyline(points,w); 3476 3857 end; 3477 3858 3478 3859 function TBGRADefaultBitmap.ComputeWidePolyline(const points: array of TPointF; 3479 w: single; Closed: boolean): ArrayOfTPointF; 3480 var 3481 options: TBGRAPolyLineOptions; 3482 begin 3483 if not closed then options := [plRoundCapOpen] else options := []; 3484 options += GetPolyLineOption; 3485 if Assigned(FArrow) then 3486 Result:= BGRAPen.ComputeWidePolylinePoints(points,w,BGRAWhite,pecRound,pjsRound,FCustomPenStyle,options,JoinMiterLimit,@FArrow.ComputeStartAt,FArrow.StartOffsetX,@FArrow.ComputeEndAt,FArrow.EndOffsetX) 3487 else 3488 Result:= BGRAPen.ComputeWidePolylinePoints(points,w,BGRAWhite,pecRound,pjsRound,FCustomPenStyle,options,JoinMiterLimit); 3860 w: single; ClosedCap: boolean): ArrayOfTPointF; 3861 begin 3862 result := FPenStroker.ComputePolyline(points,w,ClosedCap); 3489 3863 end; 3490 3864 … … 3492 3866 w: single): ArrayOfTPointF; 3493 3867 begin 3494 Result:= BGRAPen.ComputeWidePolylinePoints(points,w,BGRAWhite,LineCap,JoinStyle,FCustomPenStyle,GetPolyLineOption+[plCycle],JoinMiterLimit);3868 result := FPenStroker.ComputePolygon(points,w); 3495 3869 end; 3496 3870 … … 3598 3972 3599 3973 procedure TBGRADefaultBitmap.FillMask(x, y: integer; AMask: TBGRACustomBitmap; 3600 texture: IBGRAScanner; ADrawMode: TDrawMode );3974 texture: IBGRAScanner; ADrawMode: TDrawMode; AOpacity: byte); 3601 3975 var 3602 3976 scan: TBGRACustomScanner; 3603 3977 begin 3604 3978 if AMask = nil then exit; 3605 scan := TBGRATextureMaskScanner.Create(AMask,Point(-X,-Y),texture );3979 scan := TBGRATextureMaskScanner.Create(AMask,Point(-X,-Y),texture, AOpacity); 3606 3980 self.FillRect(X,Y,X+AMask.Width,Y+AMask.Height,scan,ADrawMode); 3607 3981 scan.Free; … … 3626 4000 n: integer; 3627 4001 colorMask,beforeBGR, afterBGR: longword; 3628 begin 3629 colorMask := NtoLE($00FFFFFF); 3630 beforeBGR := NtoLE((before and $FF shl 16) + (before and $FF00) + (before shr 16 and $FF)); 3631 afterBGR := NtoLE((after and $FF shl 16) + (after and $FF00) + (after shr 16 and $FF)); 4002 rAfter,gAfter,bAfter,rBefore,gBefore,bBefore: byte; 4003 begin 4004 colorMask := LongWord(BGRA(255,255,255,0)); 4005 RedGreenBlue(before, rBefore,gBefore,bBefore); 4006 RedGreenBlue(after, rAfter,gAfter,bAfter); 4007 beforeBGR := LongWord(BGRA(rBefore,gBefore,bBefore,0)); 4008 afterBGR := LongWord(BGRA(rAfter,gAfter,bAfter,0)); 3632 4009 3633 4010 p := PLongWord(Data); … … 3654 4031 for n := NbPixels - 1 downto 0 do 3655 4032 begin 3656 if p^ = beforethen4033 if PDWord(p)^ = DWord(before) then 3657 4034 p^ := after; 3658 4035 Inc(p); 4036 end; 4037 InvalidateBitmap; 4038 end; 4039 4040 procedure TBGRADefaultBitmap.ReplaceColor(ABounds: TRect; before, after: TColor); 4041 var p: PLongWord; 4042 xb,yb,xcount: integer; 4043 4044 colorMask,beforeBGR, afterBGR: longword; 4045 rAfter,gAfter,bAfter,rBefore,gBefore,bBefore: byte; 4046 begin 4047 colorMask := LongWord(BGRA(255,255,255,0)); 4048 RedGreenBlue(before, rBefore,gBefore,bBefore); 4049 RedGreenBlue(after, rAfter,gAfter,bAfter); 4050 beforeBGR := LongWord(BGRA(rBefore,gBefore,bBefore,0)); 4051 afterBGR := LongWord(BGRA(rAfter,gAfter,bAfter,0)); 4052 4053 if not IntersectRect(ABounds,ABounds,ClipRect) then exit; 4054 xcount := ABounds.Right-ABounds.Left; 4055 for yb := ABounds.Top to ABounds.Bottom-1 do 4056 begin 4057 p := PLongWord(ScanLine[yb]+ABounds.Left); 4058 for xb := xcount-1 downto 0 do 4059 begin 4060 if p^ and colorMask = beforeBGR then 4061 p^ := (p^ and not ColorMask) or afterBGR; 4062 Inc(p); 4063 end; 4064 end; 4065 InvalidateBitmap; 4066 end; 4067 4068 procedure TBGRADefaultBitmap.ReplaceColor(ABounds: TRect; before, 4069 after: TBGRAPixel); 4070 var p: PBGRAPixel; 4071 xb,yb,xcount: integer; 4072 begin 4073 if before.alpha = 0 then 4074 begin 4075 ReplaceTransparent(ABounds,after); 4076 exit; 4077 end; 4078 if not IntersectRect(ABounds,ABounds,ClipRect) then exit; 4079 xcount := ABounds.Right-ABounds.Left; 4080 for yb := ABounds.Top to ABounds.Bottom-1 do 4081 begin 4082 p := ScanLine[yb]+ABounds.Left; 4083 for xb := xcount-1 downto 0 do 4084 begin 4085 if PDWord(p)^ = DWord(before) then 4086 p^ := after; 4087 Inc(p); 4088 end; 3659 4089 end; 3660 4090 InvalidateBitmap; … … 3673 4103 p^ := after; 3674 4104 Inc(p); 4105 end; 4106 InvalidateBitmap; 4107 end; 4108 4109 procedure TBGRADefaultBitmap.ReplaceTransparent(ABounds: TRect; 4110 after: TBGRAPixel); 4111 var p: PBGRAPixel; 4112 xb,yb,xcount: integer; 4113 begin 4114 if not IntersectRect(ABounds,ABounds,ClipRect) then exit; 4115 xcount := ABounds.Right-ABounds.Left; 4116 for yb := ABounds.Top to ABounds.Bottom-1 do 4117 begin 4118 p := ScanLine[yb]+ABounds.Left; 4119 for xb := xcount-1 downto 0 do 4120 begin 4121 if p^.alpha = 0 then 4122 p^ := after; 4123 Inc(p); 4124 end; 3675 4125 end; 3676 4126 InvalidateBitmap; … … 3826 4276 procedure TBGRADefaultBitmap.GradientFill(x, y, x2, y2: integer; 3827 4277 c1, c2: TBGRAPixel; gtype: TGradientType; o1, o2: TPointF; mode: TDrawMode; 3828 gammaColorCorrection: boolean = True; Sinus: Boolean=False); 3829 begin 3830 BGRAGradientFill(self, x, y, x2, y2, c1, c2, gtype, o1, o2, mode, gammaColorCorrection, Sinus); 4278 gammaColorCorrection: boolean; Sinus: Boolean; ditherAlgo: TDitheringAlgorithm); 4279 var 4280 scanner: TBGRAGradientScanner; 4281 begin 4282 if (c1.alpha = 0) and (c2.alpha = 0) then 4283 FillRect(x, y, x2, y2, BGRAPixelTransparent, mode) 4284 else 4285 if ditherAlgo <> daNearestNeighbor then 4286 GradientFillDithered(x,y,x2,y2,c1,c2,gtype,o1,o2,mode,gammaColorCorrection,sinus,ditherAlgo) 4287 else 4288 begin 4289 scanner := TBGRAGradientScanner.Create(c1,c2,gtype,o1,o2,gammaColorCorrection,Sinus); 4290 FillRect(x,y,x2,y2,scanner,mode); 4291 scanner.Free; 4292 end; 3831 4293 end; 3832 4294 3833 4295 procedure TBGRADefaultBitmap.GradientFill(x, y, x2, y2: integer; 3834 4296 gradient: TBGRACustomGradient; gtype: TGradientType; o1, o2: TPointF; 3835 mode: TDrawMode; Sinus: Boolean );4297 mode: TDrawMode; Sinus: Boolean; ditherAlgo: TDitheringAlgorithm); 3836 4298 var 3837 4299 scanner: TBGRAGradientScanner; 3838 4300 begin 4301 if ditherAlgo <> daNearestNeighbor then 4302 GradientFillDithered(x,y,x2,y2,gradient,gtype,o1,o2,mode,sinus,ditherAlgo) 4303 else 4304 begin 4305 scanner := TBGRAGradientScanner.Create(gradient,gtype,o1,o2,sinus); 4306 FillRect(x,y,x2,y2,scanner,mode); 4307 scanner.Free; 4308 end; 4309 end; 4310 4311 procedure TBGRADefaultBitmap.GradientFillDithered(x, y, x2, y2: integer; c1, 4312 c2: TBGRAPixel; gtype: TGradientType; o1, o2: TPointF; 4313 mode: TDrawMode; gammaColorCorrection: boolean; Sinus: Boolean; 4314 ditherAlgo: TDitheringAlgorithm); 4315 var 4316 scanner: TBGRAGradientScanner; 4317 begin 4318 if (c1.alpha = 0) and (c2.alpha = 0) then 4319 FillRect(x, y, x2, y2, BGRAPixelTransparent, dmSet) 4320 else 4321 begin 4322 scanner := TBGRAGradientScanner.Create(c1,c2,gtype,o1,o2,gammaColorCorrection,Sinus); 4323 FillRect(x,y,x2,y2,scanner,mode,ditherAlgo); 4324 scanner.Free; 4325 end; 4326 end; 4327 4328 procedure TBGRADefaultBitmap.GradientFillDithered(x, y, x2, y2: integer; 4329 gradient: TBGRACustomGradient; gtype: TGradientType; o1, o2: TPointF; 4330 mode: TDrawMode; Sinus: Boolean; ditherAlgo: TDitheringAlgorithm); 4331 var 4332 scanner: TBGRAGradientScanner; 4333 begin 3839 4334 scanner := TBGRAGradientScanner.Create(gradient,gtype,o1,o2,sinus); 3840 FillRect(x,y,x2,y2,scanner,mode );4335 FillRect(x,y,x2,y2,scanner,mode,ditherAlgo); 3841 4336 scanner.Free; 3842 4337 end; … … 3850 4345 function TBGRADefaultBitmap.ScanAtInteger(X, Y: integer): TBGRAPixel; 3851 4346 begin 3852 if FData <> nilthen3853 result := (GetScanlineFast(PositiveMod(Y+ScanOffset.Y, F Height))+PositiveMod(X+ScanOffset.X, FWidth))^4347 if (FScanWidth <> 0) and (FScanHeight <> 0) then 4348 result := (GetScanlineFast(PositiveMod(Y+ScanOffset.Y, FScanHeight))+PositiveMod(X+ScanOffset.X, FScanWidth))^ 3854 4349 else 3855 4350 result := BGRAPixelTransparent; … … 3859 4354 procedure TBGRADefaultBitmap.ScanMoveTo(X, Y: Integer); 3860 4355 begin 3861 if FData = nilthen exit;4356 if (FScanWidth = 0) or (FScanHeight = 0) then exit; 3862 4357 LoadFromBitmapIfNeeded; 3863 FScanCurX := PositiveMod(X+ScanOffset.X, F Width);3864 FScanCurY := PositiveMod(Y+ScanOffset.Y, F Height);4358 FScanCurX := PositiveMod(X+ScanOffset.X, FScanWidth); 4359 FScanCurY := PositiveMod(Y+ScanOffset.Y, FScanHeight); 3865 4360 FScanPtr := ScanLine[FScanCurY]; 3866 4361 end; … … 3868 4363 function TBGRADefaultBitmap.ScanNextPixel: TBGRAPixel; 3869 4364 begin 3870 if FData <> nilthen4365 if (FScanWidth <> 0) and (FScanHeight <> 0) then 3871 4366 begin 3872 4367 result := (FScanPtr+FScanCurX)^; 3873 4368 inc(FScanCurX); 3874 if FScanCurX = F Width then //cycle4369 if FScanCurX = FScanWidth then //cycle 3875 4370 FScanCurX := 0; 3876 4371 end … … 3884 4379 iFactX,iFactY: Int32or64; 3885 4380 begin 3886 if FData = nilthen4381 if (FScanWidth = 0) or (FScanHeight = 0) then 3887 4382 begin 3888 4383 result := BGRAPixelTransparent; … … 3892 4387 ix := round(x*256); 3893 4388 iy := round(y*256); 4389 if ScanInterpolationFilter = rfBox then 4390 begin 4391 ix := PositiveMod((ix+128)+(ScanOffset.X shl 8), FScanWidth shl 8) shr 8; 4392 iy := PositiveMod((iy+128)+(ScanOffset.Y shl 8), FScanHeight shl 8) shr 8; 4393 result := (GetScanlineFast(iy)+ix)^; 4394 exit; 4395 end; 3894 4396 iFactX := ix and 255; 3895 4397 iFactY := iy and 255; 3896 ix := PositiveMod(ix+(ScanOffset.X shl 8), F Width shl 8) shr 8;3897 iy := PositiveMod(iy+(ScanOffset.Y shl 8), F Height shl 8) shr 8;4398 ix := PositiveMod(ix+(ScanOffset.X shl 8), FScanWidth shl 8) shr 8; 4399 iy := PositiveMod(iy+(ScanOffset.Y shl 8), FScanHeight shl 8) shr 8; 3898 4400 if (iFactX = 0) and (iFactY = 0) then 3899 4401 begin … … 3920 4422 c: TBGRAPixel; 3921 4423 begin 4424 if (FScanWidth <= 0) or (FScanHeight <= 0) then 4425 begin 4426 if mode = dmSet then 4427 FillDWord(pdest^, count, DWord(BGRAPixelTransparent)); 4428 exit; 4429 end; 3922 4430 case mode of 3923 4431 dmLinearBlend: … … 3936 4444 while count > 0 do 3937 4445 begin 3938 nbCopy := F Width-FScanCurX;4446 nbCopy := FScanWidth-FScanCurX; 3939 4447 if count < nbCopy then nbCopy := count; 3940 4448 move((FScanPtr+FScanCurX)^,pdest^,nbCopy*sizeof(TBGRAPixel)); 3941 4449 inc(pdest,nbCopy); 3942 4450 inc(FScanCurX,nbCopy); 3943 if FScanCurX = F Width then FScanCurX := 0;4451 if FScanCurX = FScanWidth then FScanCurX := 0; 3944 4452 dec(count,nbCopy); 3945 4453 end; … … 3994 4502 p: PBGRAPixel; 3995 4503 n: integer; 4504 colormask: longword; 3996 4505 begin 3997 4506 if CanvasAlphaCorrection then 3998 4507 begin 3999 4508 p := FData; 4509 colormask := longword(BGRA(255,255,255,0)); 4000 4510 for n := NbPixels - 1 downto 0 do 4001 4511 begin 4002 if (longword(p^) and $FFFFFF<> 0) and (p^.alpha = 0) then4512 if (longword(p^) and colormask <> 0) and (p^.alpha = 0) then 4003 4513 p^.alpha := FCanvasOpacity; 4004 4514 Inc(p); … … 4299 4809 Parameters are the bitmap origin, the end of the horizontal axis and the end of the vertical axis. 4300 4810 The output bounds correspond to the pixels that will be affected in the destination. } 4301 procedure TBGRADefaultBitmap.PutImageAffine(Origin, HAxis, VAxis: TPointF; 4302 Source: TBGRACustomBitmap; AOutputBounds: TRect; AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte); 4811 procedure TBGRADefaultBitmap.PutImageAffine(AMatrix: TAffineMatrix; 4812 Source: TBGRACustomBitmap; AOutputBounds: TRect; 4813 AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte); 4303 4814 var affine: TBGRAAffineBitmapTransform; 4304 SourceBounds: TRect;4305 begin 4306 if (Source = nil) or ( AOpacity = 0) then exit;4815 sourceBounds: TRect; 4816 begin 4817 if (Source = nil) or (Source.Width = 0) or (Source.Height = 0) or (AOpacity = 0) then exit; 4307 4818 IntersectRect(AOutputBounds,AOutputBounds,ClipRect); 4308 4819 if IsRectEmpty(AOutputBounds) then exit; 4309 4820 4310 if (abs(Origin.x-round(Origin.x))<1e-6) and (abs(Origin.y-round(Origin.Y))<1e-6) and 4311 (abs(HAxis.x-(Origin.x+Source.Width))<1e-6) and (abs(HAxis.y-origin.y)<1e-6) and 4312 (abs(VAxis.x-Origin.x)<1e-6) and (abs(VAxis.y-(Origin.y+Source.Height))<1e-6) then 4313 begin 4314 SourceBounds := AOutputBounds; 4315 OffsetRect(SourceBounds, -round(origin.x),-round(origin.y)); 4316 IntersectRect(SourceBounds,SourceBounds,rect(0,0,Source.Width,Source.Height)); 4317 PutImagePart(round(origin.x)+SourceBounds.Left,round(origin.y)+SourceBounds.Top,Source,SourceBounds,AMode,AOpacity); 4318 exit; 4319 end; 4320 4321 { Create affine transformation } 4322 affine := TBGRAAffineBitmapTransform.Create(Source, false, AResampleFilter); 4323 affine.GlobalOpacity := AOpacity; 4324 affine.Fit(Origin,HAxis,VAxis); 4325 FillRect(AOutputBounds,affine,AMode); 4326 affine.Free; 4821 if IsAffineRoughlyTranslation(AMatrix, rect(0,0,Source.Width,Source.Height)) then 4822 begin 4823 sourceBounds := AOutputBounds; 4824 OffsetRect(sourceBounds, -round(AMatrix[1,3]),-round(AMatrix[2,3])); 4825 IntersectRect(sourceBounds,sourceBounds,rect(0,0,Source.Width,Source.Height)); 4826 PutImagePart(round(AMatrix[1,3])+sourceBounds.Left,round(AMatrix[2,3])+sourceBounds.Top,Source,sourceBounds,AMode,AOpacity); 4827 end else 4828 begin 4829 affine := TBGRAAffineBitmapTransform.Create(Source, false, AResampleFilter); 4830 affine.GlobalOpacity := AOpacity; 4831 affine.ViewMatrix := AMatrix; 4832 FillRect(AOutputBounds,affine,AMode); 4833 affine.Free; 4834 end; 4835 end; 4836 4837 function TBGRADefaultBitmap.GetImageAffineBounds(AMatrix: TAffineMatrix; 4838 ASourceBounds: TRect; AClipOutput: boolean): TRect; 4839 const pointMargin = 0.5 - 1/512; 4840 4841 procedure FirstPoint(pt: TPointF); 4842 begin 4843 result.Left := round(pt.X); 4844 result.Top := round(pt.Y); 4845 result.Right := round(pt.X)+1; 4846 result.Bottom := round(pt.Y)+1; 4847 end; 4848 4849 //include specified point in the bounds 4850 procedure IncludePoint(pt: TPointF); 4851 begin 4852 if round(pt.X) < result.Left then result.Left := round(pt.X); 4853 if round(pt.Y) < result.Top then result.Top := round(pt.Y); 4854 if round(pt.X)+1 > result.Right then result.Right := round(pt.X)+1; 4855 if round(pt.Y)+1 > result.Bottom then result.Bottom := round(pt.Y)+1; 4856 end; 4857 4858 begin 4859 result := EmptyRect; 4860 if IsRectEmpty(ASourceBounds) then exit; 4861 if IsAffineRoughlyTranslation(AMatrix,ASourceBounds) then 4862 begin 4863 result := ASourceBounds; 4864 OffsetRect(result,round(AMatrix[1,3]),round(AMatrix[2,3])); 4865 end else 4866 begin 4867 FirstPoint(AMatrix*PointF(ASourceBounds.Left-pointMargin,ASourceBounds.Top-pointMargin)); 4868 IncludePoint(AMatrix*PointF(ASourceBounds.Right-1+pointMargin,ASourceBounds.Top-pointMargin)); 4869 IncludePoint(AMatrix*PointF(ASourceBounds.Left-pointMargin,ASourceBounds.Bottom-1+pointMargin)); 4870 IncludePoint(AMatrix*PointF(ASourceBounds.Right-1+pointMargin,ASourceBounds.Bottom-1+pointMargin)); 4871 end; 4872 if AClipOutput then IntersectRect(result,result,ClipRect); 4327 4873 end; 4328 4874 … … 4434 4980 function TBGRADefaultBitmap.FilterSmooth: TBGRACustomBitmap; 4435 4981 begin 4436 Result := BGRAFilters.FilterBlurRadial Precise(self, 0.3);4982 Result := BGRAFilters.FilterBlurRadial(self, 3, rbPrecise); 4437 4983 end; 4438 4984 … … 4479 5025 end; 4480 5026 4481 function TBGRADefaultBitmap.FilterBlurRadial(radius: integer;5027 function TBGRADefaultBitmap.FilterBlurRadial(radius: single; 4482 5028 blurType: TRadialBlurType): TBGRACustomBitmap; 4483 5029 begin … … 4485 5031 end; 4486 5032 4487 function TBGRADefaultBitmap.FilterBlurRadial(ABounds: TRect; radius: integer;5033 function TBGRADefaultBitmap.FilterBlurRadial(ABounds: TRect; radius: single; 4488 5034 blurType: TRadialBlurType): TBGRACustomBitmap; 4489 5035 var task: TFilterTask; … … 4497 5043 end; 4498 5044 5045 function TBGRADefaultBitmap.FilterBlurRadial(radiusX, radiusY: single; 5046 blurType: TRadialBlurType): TBGRACustomBitmap; 5047 begin 5048 Result := BGRAFilters.FilterBlurRadial(self, radiusX,radiusY, blurType); 5049 end; 5050 5051 function TBGRADefaultBitmap.FilterBlurRadial(ABounds: TRect; radiusX, 5052 radiusY: single; blurType: TRadialBlurType): TBGRACustomBitmap; 5053 var task: TFilterTask; 5054 begin 5055 task := BGRAFilters.CreateRadialBlurTask(self, ABounds, radiusX,radiusY, blurType); 5056 try 5057 result := task.Execute; 5058 finally 5059 task.Free; 5060 end; 5061 end; 5062 4499 5063 function TBGRADefaultBitmap.FilterPixelate(pixelSize: integer; 4500 5064 useResample: boolean; filter: TResampleFilter): TBGRACustomBitmap; … … 4503 5067 end; 4504 5068 4505 function TBGRADefaultBitmap.FilterBlurMotion(distance: integer;5069 function TBGRADefaultBitmap.FilterBlurMotion(distance: single; 4506 5070 angle: single; oriented: boolean): TBGRACustomBitmap; 4507 5071 begin … … 4509 5073 end; 4510 5074 4511 function TBGRADefaultBitmap.FilterBlurMotion(ABounds: TRect; distance: integer;5075 function TBGRADefaultBitmap.FilterBlurMotion(ABounds: TRect; distance: single; 4512 5076 angle: single; oriented: boolean): TBGRACustomBitmap; 4513 5077 var task: TFilterTask; … … 4539 5103 end; 4540 5104 4541 function TBGRADefaultBitmap.FilterEmboss(angle: single): TBGRACustomBitmap; 4542 begin 4543 Result := BGRAFilters.FilterEmboss(self, angle); 4544 end; 4545 4546 function TBGRADefaultBitmap.FilterEmboss(angle: single; ABounds: TRect): TBGRACustomBitmap; 4547 begin 4548 Result := BGRAFilters.FilterEmboss(self, angle, ABounds); 5105 function TBGRADefaultBitmap.FilterEmboss(angle: single; 5106 AStrength: integer; AOptions: TEmbossOptions): TBGRACustomBitmap; 5107 begin 5108 Result := BGRAFilters.FilterEmboss(self, angle, AStrength, AOptions); 5109 end; 5110 5111 function TBGRADefaultBitmap.FilterEmboss(angle: single; ABounds: TRect; 5112 AStrength: integer; AOptions: TEmbossOptions): TBGRACustomBitmap; 5113 begin 5114 Result := BGRAFilters.FilterEmboss(self, angle, ABounds, AStrength, AOptions); 4549 5115 end; 4550 5116 … … 4592 5158 begin 4593 5159 Result := BGRAFilters.FilterRotate(self, origin, angle, correctBlur); 5160 end; 5161 5162 function TBGRADefaultBitmap.FilterAffine(AMatrix: TAffineMatrix; 5163 correctBlur: boolean): TBGRACustomBitmap; 5164 begin 5165 Result := NewBitmap(Width,Height); 5166 Result.PutImageAffine(AMatrix,self,255,correctBlur); 4594 5167 end; 4595 5168 … … 4620 5193 if pix.alpha = 0 then 4621 5194 result := clNone else 4622 result := pix.red + pix.green shl 8 + pix.blue shl 16;5195 result := RGBToColor(pix.red,pix.green,pix.blue); 4623 5196 {$hints on} 4624 5197 end; … … 4651 5224 end; 4652 5225 4653 function TBGRADefaultBitmap.CreateAdaptedPngWriter: TFPWriterPNG; 4654 begin 4655 result := TFPWriterPNG.Create; 4656 result.Indexed := False; 4657 result.UseAlpha := HasTransparentPixels; 4658 result.WordSized := false; 5226 function TBGRADefaultBitmap.GetPenJoinStyle: TPenJoinStyle; 5227 begin 5228 result := FPenStroker.JoinStyle; 5229 end; 5230 5231 procedure TBGRADefaultBitmap.SetPenJoinStyle(const AValue: TPenJoinStyle); 5232 begin 5233 FPenStroker.JoinStyle := AValue; 5234 end; 5235 5236 function TBGRADefaultBitmap.GetPenMiterLimit: single; 5237 begin 5238 result := FPenStroker.MiterLimit; 5239 end; 5240 5241 procedure TBGRADefaultBitmap.SetPenMiterLimit(const AValue: single); 5242 begin 5243 FPenStroker.MiterLimit := AValue; 4659 5244 end; 4660 5245 … … 4825 5410 It is NOT EXACTLY an involution, when applied twice, some color information is lost } 4826 5411 procedure TBGRADefaultBitmap.Negative; 4827 var 4828 p: PBGRAPixel; 4829 n: integer; 4830 begin 4831 LoadFromBitmapIfNeeded; 4832 p := Data; 4833 for n := NbPixels - 1 downto 0 do 4834 begin 4835 if p^.alpha <> 0 then 4836 begin 4837 p^.red := GammaCompressionTab[not GammaExpansionTab[p^.red]]; 4838 p^.green := GammaCompressionTab[not GammaExpansionTab[p^.green]]; 4839 p^.blue := GammaCompressionTab[not GammaExpansionTab[p^.blue]]; 4840 end; 4841 Inc(p); 4842 end; 4843 InvalidateBitmap; 5412 begin 5413 TBGRAFilterScannerNegative.ComputeFilterInplace(self, rect(0,0,FWidth,FHeight), True); 4844 5414 end; 4845 5415 4846 5416 procedure TBGRADefaultBitmap.NegativeRect(ABounds: TRect); 4847 var p: PBGRAPixel;4848 xb,yb,xcount: integer;4849 5417 begin 4850 5418 if not IntersectRect(ABounds,ABounds,ClipRect) then exit; 4851 xcount := ABounds.Right-ABounds.Left; 4852 for yb := ABounds.Top to ABounds.Bottom-1 do 4853 begin 4854 p := ScanLine[yb]+ABounds.Left; 4855 for xb := xcount-1 downto 0 do 4856 begin 4857 if p^.alpha <> 0 then 4858 begin 4859 p^.red := GammaCompressionTab[not GammaExpansionTab[p^.red]]; 4860 p^.green := GammaCompressionTab[not GammaExpansionTab[p^.green]]; 4861 p^.blue := GammaCompressionTab[not GammaExpansionTab[p^.blue]]; 4862 end; 4863 Inc(p); 4864 end; 4865 end; 5419 TBGRAFilterScannerNegative.ComputeFilterInplace(self, ABounds, True); 4866 5420 end; 4867 5421 … … 4870 5424 It is an involution, i.e it does nothing when applied twice } 4871 5425 procedure TBGRADefaultBitmap.LinearNegative; 4872 var 4873 p: PBGRAPixel; 4874 n: integer; 4875 begin 4876 LoadFromBitmapIfNeeded; 4877 p := Data; 4878 for n := NbPixels - 1 downto 0 do 4879 begin 4880 if p^.alpha <> 0 then 4881 begin 4882 p^.red := not p^.red; 4883 p^.green := not p^.green; 4884 p^.blue := not p^.blue; 4885 end; 4886 Inc(p); 4887 end; 4888 InvalidateBitmap; 5426 begin 5427 TBGRAFilterScannerNegative.ComputeFilterInplace(self, rect(0,0,FWidth,FHeight), False); 4889 5428 end; 4890 5429 4891 5430 procedure TBGRADefaultBitmap.LinearNegativeRect(ABounds: TRect); 4892 var p: PBGRAPixel;4893 xb,yb,xcount: integer;4894 5431 begin 4895 5432 if not IntersectRect(ABounds,ABounds,ClipRect) then exit; 4896 xcount := ABounds.Right-ABounds.Left; 4897 for yb := ABounds.Top to ABounds.Bottom-1 do 4898 begin 4899 p := ScanLine[yb]+ABounds.Left; 4900 for xb := xcount-1 downto 0 do 4901 begin 4902 if p^.alpha <> 0 then 4903 begin 4904 p^.red := not p^.red; 4905 p^.green := not p^.green; 4906 p^.blue := not p^.blue; 4907 end; 4908 Inc(p); 4909 end; 4910 end; 4911 end; 4912 4913 procedure TBGRADefaultBitmap.InplaceGrayscale; 4914 begin 4915 InplaceGrayscale(rect(0,0,Width,Height)); 4916 end; 4917 4918 procedure TBGRADefaultBitmap.InplaceGrayscale(ABounds: TRect); 4919 var 4920 task: TFilterTask; 4921 begin 4922 task := CreateGrayscaleTask(self, ABounds); 4923 task.Destination := self; 4924 task.Execute; 4925 task.Free; 5433 TBGRAFilterScannerNegative.ComputeFilterInplace(self, ABounds, False); 5434 end; 5435 5436 procedure TBGRADefaultBitmap.InplaceGrayscale(AGammaCorrection: boolean = true); 5437 begin 5438 TBGRAFilterScannerGrayscale.ComputeFilterInplace(self, rect(0,0,FWidth,FHeight), AGammaCorrection); 5439 end; 5440 5441 procedure TBGRADefaultBitmap.InplaceGrayscale(ABounds: TRect; AGammaCorrection: boolean = true); 5442 begin 5443 if not IntersectRect(ABounds,ABounds,ClipRect) then exit; 5444 TBGRAFilterScannerGrayscale.ComputeFilterInplace(self, ABounds, AGammaCorrection); 5445 end; 5446 5447 procedure TBGRADefaultBitmap.InplaceNormalize(AEachChannel: boolean); 5448 begin 5449 InplaceNormalize(rect(0,0,Width,Height),AEachChannel); 5450 end; 5451 5452 procedure TBGRADefaultBitmap.InplaceNormalize(ABounds: TRect; 5453 AEachChannel: boolean); 5454 var scanner: TBGRAFilterScannerNormalize; 5455 begin 5456 if not IntersectRect(ABounds,ABounds,ClipRect) then exit; 5457 scanner := TBGRAFilterScannerNormalize.Create(self,Point(0,0),ABounds,AEachChannel); 5458 FillRect(ABounds,scanner,dmSet); 5459 scanner.Free; 4926 5460 end; 4927 5461 … … 4930 5464 It is an involution, i.e it does nothing when applied twice } 4931 5465 procedure TBGRADefaultBitmap.SwapRedBlue; 5466 begin 5467 TBGRAFilterScannerSwapRedBlue.ComputeFilterInplace(self, rect(0,0,FWidth,FHeight), False); 5468 end; 5469 5470 procedure TBGRADefaultBitmap.SwapRedBlue(ARect: TRect); 5471 begin 5472 if not CheckClippedRectBounds(ARect.Left,ARect.Top,ARect.Right,ARect.Bottom) then exit; 5473 TBGRAFilterScannerSwapRedBlue.ComputeFilterInplace(self, ARect, False); 5474 end; 5475 5476 { Convert a grayscale image into a black image with alpha value } 5477 procedure TBGRADefaultBitmap.GrayscaleToAlpha; 4932 5478 var 4933 5479 n: integer; 4934 temp: longword;4935 5480 p: PLongword; 4936 5481 begin … … 4941 5486 exit; 4942 5487 repeat 4943 temp := LEtoN(p^); 4944 p^ := NtoLE(((temp and $FF) shl 16) or ((temp and $FF0000) shr 16) or 4945 temp and $FF00FF00); 5488 p^ := (p^ shr TBGRAPixel_RedShift and $FF) shl TBGRAPixel_AlphaShift; 4946 5489 Inc(p); 4947 5490 Dec(n); … … 4950 5493 end; 4951 5494 4952 { Convert a grayscale image into a black image with alpha value } 4953 procedure TBGRADefaultBitmap.GrayscaleToAlpha; 5495 procedure TBGRADefaultBitmap.AlphaToGrayscale; 4954 5496 var 4955 5497 n: integer; … … 4963 5505 exit; 4964 5506 repeat 4965 temp := LEtoN(p^); 4966 p^ := NtoLE((temp and $FF) shl 24); 4967 Inc(p); 4968 Dec(n); 4969 until n = 0; 4970 InvalidateBitmap; 4971 end; 4972 4973 procedure TBGRADefaultBitmap.AlphaToGrayscale; 4974 var 4975 n: integer; 4976 temp: longword; 4977 p: PLongword; 4978 begin 4979 LoadFromBitmapIfNeeded; 4980 p := PLongword(Data); 4981 n := NbPixels; 4982 if n = 0 then 4983 exit; 4984 repeat 4985 temp := LEtoN(p^ shr 24); 4986 p^ := NtoLE(temp or (temp shl 8) or (temp shl 16) or $FF000000); 5507 temp := (p^ shr TBGRAPixel_AlphaShift) and $ff; 5508 p^ := (temp shl TBGRAPixel_RedShift) or (temp shl TBGRAPixel_GreenShift) 5509 or (temp shl TBGRAPixel_BlueShift) or ($ff shl TBGRAPixel_AlphaShift); 4987 5510 Inc(p); 4988 5511 Dec(n); … … 5045 5568 end; 5046 5569 end; 5570 end; 5571 5572 procedure TBGRADefaultBitmap.ApplyGlobalOpacity(ABounds: TRect; alpha: byte); 5573 var p: PBGRAPixel; 5574 xb,yb,xcount: integer; 5575 begin 5576 if not IntersectRect(ABounds,ABounds,ClipRect) then exit; 5577 xcount := ABounds.Right-ABounds.Left; 5578 for yb := ABounds.Top to ABounds.Bottom-1 do 5579 begin 5580 p := ScanLine[yb]+ABounds.Left; 5581 for xb := xcount-1 downto 0 do 5582 begin 5583 p^.alpha := ApplyOpacity(p^.alpha, alpha); 5584 Inc(p); 5585 end; 5586 end; 5587 InvalidateBitmap; 5047 5588 end; 5048 5589 … … 5127 5668 end; 5128 5669 5129 { Get bounds of non zero values of specified channel }5130 function TBGRADefaultBitmap.GetImageBounds(Channel: TChannel = cAlpha; ANothingValue: Byte = 0): TRect;5131 begin5132 result := GetImageBounds([Channel], ANothingValue);5133 end;5134 5135 function TBGRADefaultBitmap.GetImageBounds(Channels: TChannels; ANothingValue: Byte = 0): TRect;5136 var5137 minx, miny, maxx, maxy: integer;5138 xb, xb2, yb: integer;5139 p: PDWord;5140 colorMask, colorZeros: DWord;5141 begin5142 maxx := -1;5143 maxy := -1;5144 minx := self.Width;5145 miny := self.Height;5146 colorMask := 0;5147 colorZeros := 0;5148 if cBlue in Channels then5149 begin5150 colorMask := colorMask or $ff;5151 colorZeros:= colorZeros or ANothingValue;5152 end;5153 if cGreen in Channels then5154 begin5155 colorMask := colorMask or $ff00;5156 colorZeros:= colorZeros or (ANothingValue shl 8);5157 end;5158 if cRed in Channels then5159 begin5160 colorMask := colorMask or $ff0000;5161 colorZeros:= colorZeros or (ANothingValue shl 16);5162 end;5163 if cAlpha in Channels then5164 begin5165 colorMask := colorMask or $ff000000;5166 colorZeros:= colorZeros or (ANothingValue shl 24);5167 end;5168 colorMask := NtoLE(colorMask);5169 colorZeros := NtoLE(colorZeros);5170 for yb := 0 to self.Height - 1 do5171 begin5172 p := PDWord(self.ScanLine[yb]);5173 for xb := 0 to self.Width - 1 do5174 begin5175 if (p^ and colorMask) <> colorZeros then5176 begin5177 if xb < minx then5178 minx := xb;5179 if yb < miny then5180 miny := yb;5181 if xb > maxx then5182 maxx := xb;5183 if yb > maxy then5184 maxy := yb;5185 5186 inc(p, self.width-1-xb);5187 for xb2 := self.Width-1 downto xb+1 do5188 begin5189 if (p^ and colorMask) <> colorZeros then5190 begin5191 if xb2 > maxx then5192 maxx := xb2;5193 break;5194 end;5195 dec(p);5196 end;5197 break;5198 end;5199 Inc(p);5200 end;5201 end;5202 if minx > maxx then5203 begin5204 Result.left := 0;5205 Result.top := 0;5206 Result.right := 0;5207 Result.bottom := 0;5208 end5209 else5210 begin5211 Result.left := minx;5212 Result.top := miny;5213 Result.right := maxx + 1;5214 Result.bottom := maxy + 1;5215 end;5216 end;5217 5218 5670 function TBGRADefaultBitmap.GetDifferenceBounds(ABitmap: TBGRACustomBitmap): TRect; 5219 5671 var … … 5378 5830 begin 5379 5831 if LineOrder = riloTopToBottom then 5380 ptrbmp := TBGRAPtrBitmap.Create(Width,Bottom-Top,ScanLine[Top]) else5381 ptrbmp := TBGRAPtrBitmap.Create(Width,Bottom-Top,ScanLine[Bottom-1]);5832 ptrbmp := CreatePtrBitmap(Width,Bottom-Top,ScanLine[Top]) else 5833 ptrbmp := CreatePtrBitmap(Width,Bottom-Top,ScanLine[Bottom-1]); 5382 5834 ptrbmp.LineOrder := LineOrder; 5383 5835 result := ptrbmp; 5384 5836 end; 5385 end;5386 5387 { Draw BGRA data to a canvas with transparency }5388 procedure TBGRADefaultBitmap.DataDrawTransparent(ACanvas: TCanvas;5389 Rect: TRect; AData: Pointer; ALineOrder: TRawImageLineOrder; AWidth, AHeight: integer);5390 var5391 Temp: TBitmap;5392 RawImage: TRawImage;5393 BitmapHandle, MaskHandle: HBitmap;5394 begin5395 RawImage.Init;5396 RawImage.Description.Init_BPP32_B8G8R8A8_BIO_TTB(AWidth, AHeight);5397 RawImage.Description.LineOrder := ALineOrder;5398 RawImage.Data := PByte(AData);5399 RawImage.DataSize := AWidth * AHeight * sizeof(TBGRAPixel);5400 if not RawImage_CreateBitmaps(RawImage, BitmapHandle, MaskHandle, False) then5401 raise FPImageException.Create('Failed to create bitmap handle');5402 Temp := TBitmap.Create;5403 Temp.Handle := BitmapHandle;5404 Temp.MaskHandle := MaskHandle;5405 ACanvas.StretchDraw(Rect, Temp);5406 Temp.Free;5407 end;5408 5409 { Draw BGRA data to a canvas without transparency }5410 procedure TBGRADefaultBitmap.DataDrawOpaque(ACanvas: TCanvas;5411 Rect: TRect; AData: Pointer; ALineOrder: TRawImageLineOrder; AWidth, AHeight: integer);5412 var5413 Temp: TBitmap;5414 RawImage: TRawImage;5415 BitmapHandle, MaskHandle: HBitmap;5416 TempData: Pointer;5417 x, y: integer;5418 PTempData: PByte;5419 PSource: PByte;5420 ADataSize: integer;5421 ALineEndMargin: integer;5422 CreateResult: boolean;5423 {$IFDEF DARWIN}5424 TempShift: Byte;5425 {$ENDIF}5426 begin5427 if (AHeight = 0) or (AWidth = 0) then5428 exit;5429 5430 ALineEndMargin := (4 - ((AWidth * 3) and 3)) and 3;5431 ADataSize := (AWidth * 3 + ALineEndMargin) * AHeight;5432 5433 {$HINTS OFF}5434 GetMem(TempData, ADataSize);5435 {$HINTS ON}5436 PTempData := TempData;5437 PSource := AData;5438 5439 {$IFDEF DARWIN} //swap red and blue values5440 for y := 0 to AHeight - 1 do5441 begin5442 for x := 0 to AWidth - 1 do5443 begin5444 PTempData^ := (PSource+2)^;5445 (PTempData+1)^ := (PSource+1)^;5446 (PTempData+2)^ := PSource^;5447 inc(PTempData,3);5448 inc(PSource,4);5449 end;5450 Inc(PTempData, ALineEndMargin);5451 end;5452 {$ELSE}5453 for y := 0 to AHeight - 1 do5454 begin5455 for x := 0 to AWidth - 1 do5456 begin5457 PWord(PTempData)^ := PWord(PSource)^;5458 (PTempData+2)^ := (PSource+2)^;5459 Inc(PTempData,3);5460 Inc(PSource, 4);5461 end;5462 Inc(PTempData, ALineEndMargin);5463 end;5464 {$ENDIF}5465 5466 RawImage.Init;5467 RawImage.Description.Init_BPP24_B8G8R8_BIO_TTB(AWidth, AHeight);5468 {$IFDEF DARWIN}5469 TempShift := RawImage.Description.RedShift;5470 RawImage.Description.RedShift := RawImage.Description.BlueShift;5471 RawImage.Description.BlueShift := TempShift;5472 {$ENDIF}5473 5474 RawImage.Description.LineOrder := ALineOrder;5475 RawImage.Description.LineEnd := rileDWordBoundary;5476 5477 if integer(RawImage.Description.BytesPerLine) <> AWidth * 3 + ALineEndMargin then5478 begin5479 FreeMem(TempData);5480 raise FPImageException.Create('Line size is inconsistant');5481 end;5482 RawImage.Data := PByte(TempData);5483 RawImage.DataSize := ADataSize;5484 5485 CreateResult := RawImage_CreateBitmaps(RawImage, BitmapHandle, MaskHandle, False);5486 FreeMem(TempData);5487 5488 if not CreateResult then5489 raise FPImageException.Create('Failed to create bitmap handle');5490 5491 Temp := TBitmap.Create;5492 Temp.Handle := BitmapHandle;5493 Temp.MaskHandle := MaskHandle;5494 ACanvas.StretchDraw(Rect, Temp);5495 Temp.Free;5496 5837 end; 5497 5838 … … 5514 5855 end; 5515 5856 5516 procedure TBGRADefaultBitmap.RebuildBitmap; 5517 var 5518 RawImage: TRawImage; 5519 BitmapHandle, MaskHandle: HBitmap; 5520 begin 5521 if FBitmap <> nil then 5522 FBitmap.Free; 5523 5524 FBitmap := TBitmapTracker.Create(self); 5525 5526 if (FWidth > 0) and (FHeight > 0) then 5527 begin 5528 RawImage.Init; 5529 RawImage.Description.Init_BPP32_B8G8R8A8_BIO_TTB(FWidth, FHeight); 5530 RawImage.Description.LineOrder := FLineOrder; 5531 RawImage.Data := PByte(FData); 5532 RawImage.DataSize := FWidth * FHeight * sizeof(TBGRAPixel); 5533 if not RawImage_CreateBitmaps(RawImage, BitmapHandle, MaskHandle, False) then 5534 raise FPImageException.Create('Failed to create bitmap handle'); 5535 FBitmap.Handle := BitmapHandle; 5536 FBitmap.MaskHandle := MaskHandle; 5537 end; 5538 5539 FBitmap.Canvas.AntialiasingMode := amOff; 5540 FBitmapModified := False; 5857 function TBGRADefaultBitmap.CreatePtrBitmap(AWidth, AHeight: integer; 5858 AData: PBGRAPixel): TBGRAPtrBitmap; 5859 begin 5860 result := TBGRAPtrBitmap.Create(AWidth,AHeight,AData); 5541 5861 end; 5542 5862 … … 5546 5866 end; 5547 5867 5548 procedure TBGRADefaultBitmap.GetImageFromCanvas(CanvasSource: TCanvas; x, y: integer);5549 var5550 bmp: TBitmap;5551 subBmp: TBGRACustomBitmap;5552 subRect: TRect;5553 cw,ch: integer;5554 begin5555 DiscardBitmapChange;5556 cw := CanvasSource.Width;5557 ch := CanvasSource.Height;5558 if (x < 0) or (y < 0) or (x+Width > cw) or5559 (y+Height > ch) then5560 begin5561 FillTransparent;5562 if (x+Width <= 0) or (y+Height <= 0) or5563 (x >= cw) or (y >= ch) then5564 exit;5565 5566 if (x > 0) then subRect.Left := x else subRect.Left := 0;5567 if (y > 0) then subRect.Top := y else subRect.Top := 0;5568 if (x+Width > cw) then subRect.Right := cw else5569 subRect.Right := x+Width;5570 if (y+Height > ch) then subRect.Bottom := ch else5571 subRect.Bottom := y+Height;5572 5573 subBmp := NewBitmap(subRect.Right-subRect.Left,subRect.Bottom-subRect.Top);5574 subBmp.GetImageFromCanvas(CanvasSource,subRect.Left,subRect.Top);5575 PutImage(subRect.Left-x,subRect.Top-y,subBmp,dmSet);5576 subBmp.Free;5577 exit;5578 end;5579 bmp := TBitmap.Create;5580 bmp.PixelFormat := pf24bit;5581 bmp.Width := Width;5582 bmp.Height := Height;5583 bmp.Canvas.CopyRect(Classes.rect(0, 0, Width, Height), CanvasSource,5584 Classes.rect(x, y, x + Width, y + Height));5585 LoadFromRawImage(bmp.RawImage, 255, True);5586 bmp.Free;5587 InvalidateBitmap;5588 end;5589 5590 5868 function TBGRADefaultBitmap.GetNbPixels: integer; 5591 5869 begin … … 5613 5891 end; 5614 5892 5893 procedure TBGRADefaultBitmap.SetLineOrder(AValue: TRawImageLineOrder); 5894 begin 5895 FLineOrder := AValue; 5896 end; 5897 5615 5898 function TBGRADefaultBitmap.GetCanvasOpacity: byte; 5616 5899 begin … … 5625 5908 { TBGRAPtrBitmap } 5626 5909 5910 function TBGRAPtrBitmap.GetLineOrder: TRawImageLineOrder; 5911 begin 5912 result := inherited GetLineOrder; 5913 end; 5914 5915 procedure TBGRAPtrBitmap.SetLineOrder(AValue: TRawImageLineOrder); 5916 begin 5917 inherited SetLineOrder(AValue); 5918 end; 5919 5627 5920 procedure TBGRAPtrBitmap.ReallocData; 5628 5921 begin … … 5633 5926 begin 5634 5927 FData := nil; 5928 end; 5929 5930 procedure TBGRAPtrBitmap.CannotResize; 5931 begin 5932 raise exception.Create('A pointer bitmap cannot be resized'); 5933 end; 5934 5935 procedure TBGRAPtrBitmap.NotImplemented; 5936 begin 5937 raise exception.Create('Not implemented'); 5938 end; 5939 5940 procedure TBGRAPtrBitmap.RebuildBitmap; 5941 begin 5942 NotImplemented; 5943 end; 5944 5945 function TBGRAPtrBitmap.CreateDefaultFontRenderer: TBGRACustomFontRenderer; 5946 begin 5947 result := nil; 5948 NotImplemented; 5949 end; 5950 5951 function TBGRAPtrBitmap.LoadFromRawImage(ARawImage: TRawImage; 5952 DefaultOpacity: byte; AlwaysReplaceAlpha: boolean; 5953 RaiseErrorOnInvalidPixelFormat: boolean): boolean; 5954 begin 5955 result := false; 5956 NotImplemented; 5635 5957 end; 5636 5958 … … 5650 5972 begin 5651 5973 FData := AData; 5974 end; 5975 5976 procedure TBGRAPtrBitmap.DataDrawTransparent(ACanvas: TCanvas; Rect: TRect; 5977 AData: Pointer; ALineOrder: TRawImageLineOrder; AWidth, AHeight: integer); 5978 begin 5979 NotImplemented; 5980 end; 5981 5982 procedure TBGRAPtrBitmap.DataDrawOpaque(ACanvas: TCanvas; Rect: TRect; 5983 AData: Pointer; ALineOrder: TRawImageLineOrder; AWidth, AHeight: integer); 5984 begin 5985 NotImplemented; 5986 end; 5987 5988 procedure TBGRAPtrBitmap.GetImageFromCanvas(CanvasSource: TCanvas; x, y: integer 5989 ); 5990 begin 5991 NotImplemented; 5992 end; 5993 5994 procedure TBGRAPtrBitmap.Assign(Source: TPersistent); 5995 begin 5996 CannotResize; 5997 end; 5998 5999 procedure TBGRAPtrBitmap.TakeScreenshot(ARect: TRect); 6000 begin 6001 CannotResize; 6002 end; 6003 6004 procedure TBGRAPtrBitmap.TakeScreenshotOfPrimaryMonitor; 6005 begin 6006 CannotResize; 6007 end; 6008 6009 procedure TBGRAPtrBitmap.LoadFromDevice(DC: System.THandle); 6010 begin 6011 CannotResize; 6012 end; 6013 6014 procedure TBGRAPtrBitmap.LoadFromDevice(DC: System.THandle; ARect: TRect); 6015 begin 6016 CannotResize; 5652 6017 end; 5653 6018 … … 5655 6020 c1, c2: TBGRAPixel; gtype: TGradientType; o1, o2: TPointF; mode: TDrawMode; 5656 6021 gammaColorCorrection: boolean = True; Sinus: Boolean=False); 5657 var 5658 gradScan : TBGRAGradientScanner; 5659 begin 5660 //handles transparency 5661 if (c1.alpha = 0) and (c2.alpha = 0) then 5662 begin 5663 bmp.FillRect(x, y, x2, y2, BGRAPixelTransparent, mode); 5664 exit; 5665 end; 5666 5667 gradScan := TBGRAGradientScanner.Create(c1,c2,gtype,o1,o2,gammaColorCorrection,Sinus); 5668 bmp.FillRect(x,y,x2,y2,gradScan,mode); 5669 gradScan.Free; 6022 begin 6023 bmp.GradientFill(x,y,x2,y2,c1,c2,gtype,o1,o2,mode,gammaColorCorrection,sinus); 5670 6024 end; 5671 6025 … … 5683 6037 end; 5684 6038 5685 ImageHandlers.RegisterImageWriter ('Personal Computer eXchange', 'pcx', TFPWriterPcx);5686 ImageHandlers.RegisterImageReader ('Personal Computer eXchange', 'pcx', TFPReaderPcx);5687 5688 ImageHandlers.RegisterImageWriter ('X Pixmap', 'xpm', TFPWriterXPM);5689 ImageHandlers.RegisterImageReader ('X Pixmap', 'xpm', TFPReaderXPM);5690 5691 6039 end. 5692 6040
Note:
See TracChangeset
for help on using the changeset viewer.