From bad7dded352756c2e5aff596e84b832797ba269e Mon Sep 17 00:00:00 2001 From: Zeus Date: Wed, 11 Oct 2023 07:45:58 +0200 Subject: [PATCH] Update ALPaintRectangle, AlPaintCircle --- .../ALAnimation/_Source/ALAnimationDemo.dproj | 2 +- .../_Source/ALFacebookLogin.dproj | 2 +- .../ALFmxControls/_Source/ALFmxControls.dproj | 2 +- .../_Source/ALFmxFilterEffectsDemo.dproj | 2 +- .../_Source/ALGeoPositionSensorDemo.dproj | 2 +- .../_Source/ALLiveVideoChatClient.dproj | 2 +- .../_Source/ALNotificationServiceDemo.dproj | 2 +- Embarcadero/Alexandria/Alexandria.patch | 13 + Embarcadero/Alexandria/Update.bat | 7 + README.md | 3 +- Source/Alcinoe.FMX.Common.pas | 18 +- Source/Alcinoe.FMX.Graphics.pas | 1776 +++++++++++++---- Source/Alcinoe.FMX.Objects.pas | 124 +- .../AndroidMerger/_Build/Sample/Sample.dproj | 2 +- Tools/DeployMan/_Build/Sample/Sample.dproj | 2 +- 15 files changed, 1510 insertions(+), 449 deletions(-) diff --git a/Demos/ALAnimation/_Source/ALAnimationDemo.dproj b/Demos/ALAnimation/_Source/ALAnimationDemo.dproj index d851a8fbe..38b9a11cc 100644 --- a/Demos/ALAnimation/_Source/ALAnimationDemo.dproj +++ b/Demos/ALAnimation/_Source/ALAnimationDemo.dproj @@ -146,7 +146,7 @@ $(BDS)\bin\delphi_PROJECTICON.ico $(BDS)\bin\delphi_PROJECTICNS.icns ALAnimationDemo - ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) + ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\osx;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) DBXSqliteDriver;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage) diff --git a/Demos/ALFacebookLogin/_Source/ALFacebookLogin.dproj b/Demos/ALFacebookLogin/_Source/ALFacebookLogin.dproj index d89f82c4f..706537b25 100644 --- a/Demos/ALFacebookLogin/_Source/ALFacebookLogin.dproj +++ b/Demos/ALFacebookLogin/_Source/ALFacebookLogin.dproj @@ -160,7 +160,7 @@ true - ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) + ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\osx;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) 65001 $(BDS)\bin\delphi_PROJECTICNS.icns true diff --git a/Demos/ALFmxControls/_Source/ALFmxControls.dproj b/Demos/ALFmxControls/_Source/ALFmxControls.dproj index 7ae5d24ef..b97f3a38a 100644 --- a/Demos/ALFmxControls/_Source/ALFmxControls.dproj +++ b/Demos/ALFmxControls/_Source/ALFmxControls.dproj @@ -160,7 +160,7 @@ true - ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) + ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\osx;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) $(BDS)\bin\delphi_PROJECTICNS.icns true true diff --git a/Demos/ALFmxFilterEffects/_Source/ALFmxFilterEffectsDemo.dproj b/Demos/ALFmxFilterEffects/_Source/ALFmxFilterEffectsDemo.dproj index 7f33ffac8..a668470dc 100644 --- a/Demos/ALFmxFilterEffects/_Source/ALFmxFilterEffectsDemo.dproj +++ b/Demos/ALFmxFilterEffects/_Source/ALFmxFilterEffectsDemo.dproj @@ -146,7 +146,7 @@ $(BDS)\bin\delphi_PROJECTICON.ico $(BDS)\bin\delphi_PROJECTICNS.icns ALFmxFilterEffectsDemo - ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) + ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\osx;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) DBXSqliteDriver;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage) diff --git a/Demos/ALGeoPositionSensor/_Source/ALGeoPositionSensorDemo.dproj b/Demos/ALGeoPositionSensor/_Source/ALGeoPositionSensorDemo.dproj index 7bd7694f1..f5da3adea 100644 --- a/Demos/ALGeoPositionSensor/_Source/ALGeoPositionSensorDemo.dproj +++ b/Demos/ALGeoPositionSensor/_Source/ALGeoPositionSensorDemo.dproj @@ -160,7 +160,7 @@ true - ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) + ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\osx;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) 65001 $(BDS)\bin\delphi_PROJECTICNS.icns true diff --git a/Demos/ALLiveVideoChat/Client/_Source/ALLiveVideoChatClient.dproj b/Demos/ALLiveVideoChat/Client/_Source/ALLiveVideoChatClient.dproj index 6506d897c..d792eff7d 100644 --- a/Demos/ALLiveVideoChat/Client/_Source/ALLiveVideoChatClient.dproj +++ b/Demos/ALLiveVideoChat/Client/_Source/ALLiveVideoChatClient.dproj @@ -182,7 +182,7 @@ $(BDS)\bin\delphi_PROJECTICON.ico $(BDS)\bin\delphi_PROJECTICNS.icns ALLiveVideoChatClient - ..\..\..\..\Embarcadero\Alexandria\fmx;..\..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\..\Embarcadero\Alexandria\rtl\android;..\..\..\..\Source;$(DCC_UnitSearchPath) + ..\..\..\..\Embarcadero\Alexandria\fmx;..\..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\osx;..\..\..\..\Embarcadero\Alexandria\rtl\android;..\..\..\..\Source;$(DCC_UnitSearchPath) true true 65001 diff --git a/Demos/ALNotificationService/_Source/ALNotificationServiceDemo.dproj b/Demos/ALNotificationService/_Source/ALNotificationServiceDemo.dproj index 2105dc40c..0773e76df 100644 --- a/Demos/ALNotificationService/_Source/ALNotificationServiceDemo.dproj +++ b/Demos/ALNotificationService/_Source/ALNotificationServiceDemo.dproj @@ -182,7 +182,7 @@ false false false - ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) + ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\osx;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) False diff --git a/Embarcadero/Alexandria/Alexandria.patch b/Embarcadero/Alexandria/Alexandria.patch index eb63f59b6..6ec0bb7f7 100644 --- a/Embarcadero/Alexandria/Alexandria.patch +++ b/Embarcadero/Alexandria/Alexandria.patch @@ -2164,6 +2164,19 @@ diff --git a/Embarcadero/Alexandria/rtl/ios/iOSapi.Security.pas b/Embarcadero/Al {$IF defined(IOS) and NOT defined(CPUARM)} initialization +Index: Embarcadero/Alexandria/rtl/ios/iOSapi.UIKit.pas +=================================================================== +diff --git a/Embarcadero/Alexandria/rtl/ios/iOSapi.UIKit.pas b/Embarcadero/Alexandria/rtl/ios/iOSapi.UIKit.pas +--- a/Embarcadero/Alexandria/rtl/ios/iOSapi.UIKit.pas (revision 1) ++++ b/Embarcadero/Alexandria/rtl/ios/iOSapi.UIKit.pas (working copy) +@@ -2634,6 +2634,7 @@ + function nativeBounds: CGRect; cdecl; + function nativeScale: CGFloat; cdecl; + function snapshotViewAfterScreenUpdates(afterUpdates: Boolean): UIView; cdecl; ++ function maximumFramesPerSecond: NSInteger; cdecl; + end; + TUIScreen = class(TOCGenericImport) end; + Index: Embarcadero/Alexandria/rtl/win/Winapi.Isapi2.pas =================================================================== diff --git a/Embarcadero/Alexandria/rtl/win/Winapi.Isapi2.pas b/Embarcadero/Alexandria/rtl/win/Winapi.Isapi2.pas diff --git a/Embarcadero/Alexandria/Update.bat b/Embarcadero/Alexandria/Update.bat index 93151e994..ca9bec3ff 100644 --- a/Embarcadero/Alexandria/Update.bat +++ b/Embarcadero/Alexandria/Update.bat @@ -24,6 +24,7 @@ IF EXIST "%FileName%" rmdir /s /q "%FileName%" IF EXIST "%FileName%" goto ERROR mkdir "%FileName%" mkdir "%FileName%\ios" +mkdir "%FileName%\osx" mkdir "%FileName%\android" mkdir "%FileName%\win" mkdir "%FileName%\net" @@ -38,6 +39,12 @@ IF EXIST "%EmbSourceDir%\rtl\ios" ( IF ERRORLEVEL 1 goto ERROR ) +IF EXIST "%EmbSourceDir%\rtl\osx" ( + echo Copy "%EmbSourceDir%\rtl\osx" + xcopy /Q "%EmbSourceDir%\rtl\osx" "%ALBaseDir%\Embarcadero\Alexandria\rtl\osx" + IF ERRORLEVEL 1 goto ERROR +) + IF EXIST "%EmbSourceDir%\rtl\android" ( echo Copy "%EmbSourceDir%\rtl\android" xcopy /Q "%EmbSourceDir%\rtl\android" "%ALBaseDir%\Embarcadero\Alexandria\rtl\android" diff --git a/README.md b/README.md index 2621bf4e5..1f29623f9 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ us to patch the original Delphi source files: * [Performance Issue - Comparing Equality Between Two Strings](https://quality.embarcadero.com/browse/RSP-42011) * [Introduce IsVisibleObject function for improved optimization on TScrollBox](https://quality.embarcadero.com/browse/RSP-42357) * [BeginUpdate/Endupdate block with add or remove of child objects : misconception](https://quality.embarcadero.com/browse/RSP-21013) -* [The width and height of a TContext3D object must be defined as single-precision floating-point numbers, not as integers](https://quality.embarcadero.com/browse/RSP-41516) +* [The width and height of a TContext3D object must be defined as single-precision, not as integers](https://quality.embarcadero.com/browse/RSP-41516) * [TTextLayout.PositionAtPoint / TTextLayoutD2D.DoPositionAtPoint totally broken in Alexandria](https://quality.embarcadero.com/browse/RSP-39734) * [Regression in Alexandria: FMX.StrokeBuilder.pas Revamp Leads to TARC Drawing Issues](https://quality.embarcadero.com/browse/RSP-41618) * [GL_TEXTURE_EXTERNAL_OES not supported](https://quality.embarcadero.com/browse/RSP-16830) @@ -57,6 +57,7 @@ us to patch the original Delphi source files: * [Miss CLLocationManager.accuracyAuthorization in iOSapi.CoreLocation.pas](https://quality.embarcadero.com/browse/RSP-41352) * [Miss constant kCLLocationAccuracyReduced in iOSapi.CoreLocation.pas](https://quality.embarcadero.com/browse/RSP-41388) * [iOS/OSX: Declaration for CLRegion.initCircularRegionWithCenter is incorrect](https://quality.embarcadero.com/browse/RSP-15717) +* [Missing function declaration for maximumFramesPerSecond in iOSapi.UIKit.UIScreen](https://quality.embarcadero.com/browse/RSP-42455) Install Alcinoe diff --git a/Source/Alcinoe.FMX.Common.pas b/Source/Alcinoe.FMX.Common.pas index 12a06cc36..9a988770c 100644 --- a/Source/Alcinoe.FMX.Common.pas +++ b/Source/Alcinoe.FMX.Common.pas @@ -34,13 +34,13 @@ TALShadow = class(TPersistent) fblur: Single; fOffsetX: Single; fOffsetY: Single; - fShadowColor: TAlphaColor; + fColor: TAlphaColor; FOnChanged: TNotifyEvent; procedure SetEnabled(const Value: boolean); procedure setblur(const Value: Single); procedure setOffsetX(const Value: Single); procedure setOffsetY(const Value: Single); - procedure setShadowColor(const Value: TAlphaColor); + procedure setColor(const Value: TAlphaColor); function IsblurStored: Boolean; function IsOffsetXStored: Boolean; function IsOffsetYStored: Boolean; @@ -54,7 +54,7 @@ TALShadow = class(TPersistent) property blur: Single read fblur write setblur stored IsblurStored; property OffsetX: Single read fOffsetX write setOffsetX stored IsOffsetXStored; property OffsetY: Single read fOffsetY write setOffsetY stored IsOffsetYStored; - property ShadowColor: TAlphaColor read fShadowColor write setShadowColor default $96000000; + property Color: TAlphaColor read fColor write setColor default $96000000; end; type @@ -310,7 +310,7 @@ constructor TALShadow.Create; fblur := 12; fOffsetX := 0; fOffsetY := 0; - fShadowColor := $96000000; + fColor := $96000000; FOnChanged := nil; end; @@ -325,7 +325,7 @@ procedure TALShadow.Assign(Source: TPersistent); fblur := TALShadow(Source).fblur; fOffsetX := TALShadow(Source).fOffsetX; fOffsetY := TALShadow(Source).fOffsetY; - fShadowColor := TALShadow(Source).fShadowColor; + fColor := TALShadow(Source).fColor; FOnChanged := LSaveChange; if Assigned(FOnChanged) then FOnChanged(Self); end @@ -386,11 +386,11 @@ procedure TALShadow.setOffsetY(const Value: Single); end; end; -{***********************************************************} -procedure TALShadow.setShadowColor(const Value: TAlphaColor); +{*****************************************************} +procedure TALShadow.setColor(const Value: TAlphaColor); begin - if FShadowColor <> Value then begin - FShadowColor := Value; + if FColor <> Value then begin + FColor := Value; if Assigned(FOnChanged) then FOnChanged(Self); end; end; diff --git a/Source/Alcinoe.FMX.Graphics.pas b/Source/Alcinoe.FMX.Graphics.pas index 9ad5165e7..f94ab9957 100644 --- a/Source/Alcinoe.FMX.Graphics.pas +++ b/Source/Alcinoe.FMX.Graphics.pas @@ -61,9 +61,8 @@ function ALTransformBitmaptoTexture(var aBitmap: Tbitmap): TTexture; {$ENDIF} type - - TALResizeImageGetDestSizeFunct = reference to function(const aOriginalSize: TPointF): TpointF; - TALResizeAndBlurImageGetDestSizeFunct = reference to function(const aOriginalSize: TPointF; var aRadius: single): TpointF; + TALResizeImageGetDestSizeFunct = reference to function(const aOriginalSize: TPointF): TpointF; + TALResizeAndBlurImageGetDestSizeFunct = reference to function(const aOriginalSize: TPointF; var aRadius: single): TpointF; {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~} //https://i.stack.imgur.com/CcESX.png - transparent pixel in the mask are removed from the resulting image @@ -220,7 +219,6 @@ function ALLoadNormalizeOrientationFileImageV3(const aFileName: String): TALRas {$IF defined(IOS)} type - PAlphaColorCGFloat = ^TAlphaColorCGFloat; TAlphaColorCGFloat = record public @@ -234,6 +232,28 @@ procedure ALGradientEvaluateCallback(info: Pointer; inData: PCGFloat; outData: P {$ENDIF} {*************************} +procedure ALPaintRectangle( + {$IF defined(ANDROID)} + const aCanvas: Jcanvas; + {$ELSEIF defined(IOS)} + const aContext: CGContextRef; + const aColorSpace: CGColorSpaceRef; + const aGridHeight: Single; + {$ELSEIF defined(MSWINDOWS) or defined(ALMacOS)} + const aCanvas: Tcanvas; + {$ENDIF} + const dstRect: TrectF; + const FillColor: TAlphaColor; + const StrokeColor: TalphaColor; + const StrokeThickness: Single; + const ShadowColor: TAlphaColor; // If ShadowColor is not null, then the Canvas must have enough space to draw the shadow (approximately ShadowBlur on each side of the rectangle) + const shadowBlur: Single; + const shadowOffsetX: Single; + const shadowOffsetY: Single; + const Sides: TSides; + const Corners: TCorners; + const XRadius: Single; + const YRadius: Single); overload; procedure ALPaintRectangle( {$IF defined(ANDROID)} const aCanvas: Jcanvas; @@ -247,13 +267,31 @@ procedure ALPaintRectangle( const dstRect: TrectF; const Fill: TBrush; const Stroke: TStrokeBrush; - const Shadow: TALShadow = nil; // if shadow then the Canvas must contain enalf space to draw the shadow (around Shadow.blur on each side of the rectangle) - const Sides: TSides = [TSide.Top, TSide.Left, TSide.Bottom, TSide.Right]; // default = AllSides - const Corners: TCorners = [TCorner.TopLeft, TCorner.TopRight, TCorner.BottomLeft, TCorner.BottomRight]; // default = AllCorners - const XRadius: Single = 0; - const YRadius: Single = 0); + const Shadow: TALShadow; // If shadow is not nil, then the Canvas must have enough space to draw the shadow (approximately Shadow.blur on each side of the rectangle) + const Sides: TSides; + const Corners: TCorners; + const XRadius: Single; + const YRadius: Single); overload; {**********************} +procedure ALPaintCircle( + {$IF defined(ANDROID)} + const aCanvas: Jcanvas; + {$ELSEIF defined(IOS)} + const aContext: CGContextRef; + const aColorSpace: CGColorSpaceRef; + const aGridHeight: Single; + {$ELSEIF defined(MSWINDOWS) or defined(ALMacOS)} + const aCanvas: Tcanvas; + {$ENDIF} + const dstRect: TrectF; + const FillColor: TAlphaColor; + const StrokeColor: TalphaColor; + const StrokeThickness: Single; + const ShadowColor: TAlphaColor; // If ShadowColor is not null, then the Canvas must have enough space to draw the shadow (approximately ShadowBlur on each side of the circle) + const shadowBlur: Single; + const shadowOffsetX: Single; + const shadowOffsetY: Single); overload; procedure ALPaintCircle( {$IF defined(ANDROID)} const aCanvas: Jcanvas; @@ -267,7 +305,7 @@ procedure ALPaintCircle( const dstRect: TrectF; const Fill: TBrush; const Stroke: TStrokeBrush; - const Shadow: TALShadow = nil); // if shadow then the Canvas must contain enalf space to draw the shadow (around Shadow.blur on each side of the rectangle) + const Shadow: TALShadow); overload; // If shadow is not nil, then the Canvas must have enough space to draw the shadow (approximately Shadow.blur on each side of the circle) {*******************************} Procedure ALCreateDrawingSurface( @@ -371,6 +409,9 @@ implementation Alcinoe.iOSApi.ImageIO, Alcinoe.FMX.Types3D, {$ENDIF} + {$IF defined(MSWINDOWS) or defined(ALMacOS)} + FMX.Effects, + {$ENDIF} {$IFDEF ALUseTexture} FMX.Canvas.GPU, {$ENDIF} @@ -682,8 +723,8 @@ function ALFitIntoAndCropAsMaskImageV2(const aStream: TCustomMemoryStream; const if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextClipToMask( LContext, ALLowerLeftCGRect( @@ -836,8 +877,8 @@ function ALFitIntoAndCropAsMaskImageV3(const aStream: TCustomMemoryStream; const try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextClipToMask( LContext, ALLowerLeftCGRect( @@ -1081,8 +1122,8 @@ function ALBlurFitIntoAndCropAsMaskImageV2(const aStream: TCustomMemoryStream; c if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextClipToMask( LContext, ALLowerLeftCGRect( @@ -1224,8 +1265,8 @@ function ALBlurFitIntoAndCropAsMaskImageV3(const aStream: TCustomMemoryStream; c try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextClipToMask( LContext, ALLowerLeftCGRect( @@ -1522,8 +1563,8 @@ function ALFitIntoAndCropAsRoundRectImageV2(const aStream: TCustomMemoryStream; if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextBeginPath(LContext); // Creates a new empty path in a graphics context. LGridHeight := H; @@ -1733,8 +1774,8 @@ function ALFitIntoAndCropAsRoundRectImageV3(const aStream: TCustomMemoryStream; try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextBeginPath(LContext); // Creates a new empty path in a graphics context. LGridHeight := H; @@ -1982,8 +2023,8 @@ function ALFitIntoAndCropAsCircleImageV2(const aStream: TCustomMemoryStream; con if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextBeginPath(LContext); // Creates a new empty path in a graphics context. CGContextAddEllipseInRect( LContext, @@ -2138,8 +2179,8 @@ function ALFitIntoAndCropAsCircleImageV3(const aStream: TCustomMemoryStream; con try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextBeginPath(LContext); // Creates a new empty path in a graphics context. CGContextAddEllipseInRect( LContext, @@ -2428,8 +2469,8 @@ function ALBlurFitIntoAndCropAsCircleImageV2(const aStream: TCustomMemoryStream; if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextBeginPath(LContext); // Creates a new empty path in a graphics context. CGContextAddEllipseInRect( LContext, @@ -2567,8 +2608,8 @@ function ALBlurFitIntoAndCropAsCircleImageV3(const aStream: TCustomMemoryStream; try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -2808,8 +2849,8 @@ function ALFitIntoAndCropImageV2(const aStream: TCustomMemoryStream; const aGetD if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -2952,8 +2993,8 @@ function ALFitIntoAndCropImageV2(const aStream: TCustomMemoryStream; const W, H: if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -3097,8 +3138,8 @@ function ALFitIntoAndCropImageV3(const aStream: TCustomMemoryStream; const aGetD try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -3240,8 +3281,8 @@ function ALFitIntoAndCropImageV3(const aStream: TCustomMemoryStream; const W, H: try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -3518,8 +3559,8 @@ function ALBlurFitIntoAndCropImageV2(const aStream: TCustomMemoryStream; const a if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -3714,8 +3755,8 @@ function ALBlurFitIntoAndCropImageV2(const aStream: TCustomMemoryStream; const W if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -3867,8 +3908,8 @@ function ALBlurFitIntoAndCropImageV3(const aStream: TCustomMemoryStream; const a try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -3992,8 +4033,8 @@ function ALBlurFitIntoAndCropImageV3(const aStream: TCustomMemoryStream; const W try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -4407,8 +4448,8 @@ function ALPlaceIntoAndCropImageV2(const aStream: TCustomMemoryStream; const aGe if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -4564,8 +4605,8 @@ function ALPlaceIntoAndCropImageV2(const aStream: TCustomMemoryStream; W, H: sin if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -4714,8 +4755,8 @@ function ALPlaceIntoAndCropImageV3(const aStream: TCustomMemoryStream; const aGe try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -4863,8 +4904,8 @@ function ALPlaceIntoAndCropImageV3(const aStream: TCustomMemoryStream; W, H: sin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -5262,8 +5303,8 @@ function ALFitIntoImageV2(const aStream: TCustomMemoryStream; const aGetDestSize if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -5406,8 +5447,8 @@ function ALFitIntoImageV2(const aStream: TCustomMemoryStream; const W, H: single if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -5544,8 +5585,8 @@ function ALFitIntoImageV3(const aStream: TCustomMemoryStream; const aGetDestSize try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -5686,8 +5727,8 @@ function ALFitIntoImageV3(const aStream: TCustomMemoryStream; const W, H: single try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -5992,8 +6033,8 @@ function ALStretchImageV2(const aStream: TCustomMemoryStream; const aGetDestSize if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -6132,8 +6173,8 @@ function ALStretchImageV2(const aStream: TCustomMemoryStream; const W, H: single if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -6268,8 +6309,8 @@ function ALStretchImageV3(const aStream: TCustomMemoryStream; const aGetDestSize try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -6408,8 +6449,8 @@ function ALStretchImageV3(const aStream: TCustomMemoryStream; const W, H: single try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextDrawImage( LContext, // c: The graphics context in which to draw the image. ALLowerLeftCGRect( @@ -6771,8 +6812,8 @@ function ALLoadNormalizeOrientationImageV3(const aStream: TCustomMemoryStream; if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextConcatCTM(LContext, LMatrix); if aExifOrientationInfo in [TalExifOrientationInfo.ROTATE_270, {UIImageOrientationLeft} TalExifOrientationInfo.TRANSPOSE, {UIImageOrientationLeftMirrored} @@ -7247,8 +7288,8 @@ function ALNormalizeImageOrientationV2(const aBitmap: TALNativeBitmap; const aE if LContext <> nil then begin try CGContextSetInterpolationQuality(LContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. - CGContextSetShouldAntialias(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(LContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(LContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(LContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. CGContextConcatCTM(LContext, LMatrix); if aExifOrientationInfo in [TalExifOrientationInfo.ROTATE_270, {UIImageOrientationLeft} TalExifOrientationInfo.TRANSPOSE, {UIImageOrientationLeftMirrored} @@ -7562,13 +7603,17 @@ procedure ALPaintRectangle( const aCanvas: Tcanvas; {$ENDIF} const dstRect: TrectF; - const Fill: TBrush; - const Stroke: TStrokeBrush; - const Shadow: TALShadow = nil; // if shadow then the Canvas must contain enalf space to draw the shadow (around Shadow.blur on each side of the rectangle) - const Sides: TSides = [TSide.Top, TSide.Left, TSide.Bottom, TSide.Right]; // default = AllSides - const Corners: TCorners = [TCorner.TopLeft, TCorner.TopRight, TCorner.BottomLeft, TCorner.BottomRight]; // default = AllCorners - const XRadius: Single = 0; - const YRadius: Single = 0); + const FillColor: TAlphaColor; + const StrokeColor: TalphaColor; + const StrokeThickness: Single; + const ShadowColor: TAlphaColor; // If ShadowColor is not null, then the Canvas must have enough space to draw the shadow (approximately ShadowBlur on each side of the rectangle) + const shadowBlur: Single; + const shadowOffsetX: Single; + const shadowOffsetY: Single; + const Sides: TSides; + const Corners: TCorners; + const XRadius: Single; + const YRadius: Single); {$REGION ' _drawRect (ANDROID)'} {$IF defined(ANDROID)} @@ -7577,7 +7622,6 @@ procedure ALPaintRectangle( const aPaint: JPaint; const aRect: TrectF; Const aDrawOnlyBorder: Boolean); - var LJRect: JRectF; LPath: JPath; LXRadius: single; @@ -7595,8 +7639,7 @@ procedure ALPaintRectangle( (sides=[TSide.Top, TSide.Left, TSide.Bottom, TSide.Right]) then begin //----- if (not aDrawOnlyBorder) and - (Shadow <> nil) and - (Shadow.enabled) then aPaint.setShadowLayer(Shadow.blur{radius}, Shadow.OffsetX{dx}, Shadow.OffsetY{dy}, integer(Shadow.ShadowColor){shadowColor}); + (ShadowColor <> TalphaColorRec.Null) then aPaint.setShadowLayer(ShadowBlur{radius}, ShadowOffsetX{dx}, ShadowOffsetY{dy}, integer(ShadowColor){shadowColor}); LJRect := TJRectf.JavaClass.init(aRect.left, aRect.top, aRect.right, aRect.bottom); aCanvas.drawRoundRect( @@ -7607,8 +7650,7 @@ procedure ALPaintRectangle( LJRect := nil; if (not aDrawOnlyBorder) and - (Shadow <> nil) and - (Shadow.enabled) then aPaint.clearShadowLayer; + (ShadowColor <> TalphaColorRec.Null) then aPaint.clearShadowLayer; //----- end @@ -7619,8 +7661,7 @@ procedure ALPaintRectangle( (sides=[TSide.Top, TSide.Left, TSide.Bottom, TSide.Right]) then begin //----- if (not aDrawOnlyBorder) and - (Shadow <> nil) and - (Shadow.enabled) then aPaint.setShadowLayer(Shadow.blur{radius}, Shadow.OffsetX{dx}, Shadow.OffsetY{dy}, integer(Shadow.ShadowColor){shadowColor}); + (ShadowColor <> TalphaColorRec.Null) then aPaint.setShadowLayer(ShadowBlur{radius}, ShadowOffsetX{dx}, ShadowOffsetY{dy}, integer(ShadowColor){shadowColor}); aCanvas.drawRect( aRect.left{left}, @@ -7630,8 +7671,7 @@ procedure ALPaintRectangle( apaint); if (not aDrawOnlyBorder) and - (Shadow <> nil) and - (Shadow.enabled) then aPaint.clearShadowLayer; + (ShadowColor <> TalphaColorRec.Null) then aPaint.clearShadowLayer; //----- end @@ -7652,7 +7692,7 @@ procedure ALPaintRectangle( LWidthMinusCorners := (aRect.width - (2 * LXRadius)); LHeightMinusCorners := (aRect.height - (2 * LYradius)); //---- - if (Stroke.Kind <> TBrushKind.None) then LHalfStrokeWidth := (Stroke.Thickness) / 2 + if (StrokeColor <> TalphaColorRec.Null) then LHalfStrokeWidth := (StrokeThickness) / 2 else LHalfStrokeWidth := 0; @@ -7777,15 +7817,13 @@ procedure ALPaintRectangle( //----- if (not aDrawOnlyBorder) and - (Shadow <> nil) and - (Shadow.enabled) then aPaint.setShadowLayer(Shadow.blur{radius}, Shadow.OffsetX{dx}, Shadow.OffsetY{dy}, integer(Shadow.ShadowColor){shadowColor}); + (ShadowColor <> TalphaColorRec.Null) then aPaint.setShadowLayer(ShadowBlur{radius}, ShadowOffsetX{dx}, ShadowOffsetY{dy}, integer(ShadowColor){shadowColor}); aCanvas.drawPath(LPath,aPaint); LPath := nil; if (not aDrawOnlyBorder) and - (Shadow <> nil) and - (Shadow.enabled) then aPaint.clearShadowLayer; + (ShadowColor <> TalphaColorRec.Null) then aPaint.clearShadowLayer; //----- end; @@ -7880,7 +7918,7 @@ procedure ALPaintRectangle( LWidthMinusCorners := (aRect.width - (2 * LXRadius)); LHeightMinusCorners := (aRect.height - (2 * LYradius)); //---- - if (Stroke.Kind <> TBrushKind.None) then LHalfStrokeWidth := (Stroke.Thickness) / 2 + if (StrokeColor <> TalphaColorRec.Null) then LHalfStrokeWidth := (StrokeThickness) / 2 else LHalfStrokeWidth := 0; @@ -8014,47 +8052,29 @@ procedure ALPaintRectangle( function _GetShapeRect: TRectF; begin Result := DstRect; - if Stroke.Kind <> TBrushKind.None then - InflateRect(Result, -(Stroke.Thickness / 2), -(Stroke.Thickness / 2)); + if StrokeColor <> TalphaColorRec.Null then + InflateRect(Result, -(StrokeThickness / 2), -(StrokeThickness / 2)); end; {$ENDIF} {$ENDREGION} -{$IF defined(IOS)} -const aDefaultInputRange: array[0..1] of CGFloat = (0, 1); -{$ENDIF} - {$IF defined(ANDROID)} var LRect: TrectF; - LTmpBitmap: Jbitmap; - LRadialShader: JRadialGradient; - LLinearShader: JLinearGradient; LPaint: JPaint; - LColors: TJavaArray; - LStops: TJavaArray; - LPorterDuffXfermode: jPorterDuffXfermode; - LBitmapInfo: AndroidBitmapInfo; - LPixelBuffer: Pointer; - LBitmapData: TBitmapData; - LJDestRectf: JrectF; - LJSrcRect: Jrect; - i: integer; {$ELSEIF defined(IOS)} var LRect: TrectF; LAlphaColor: TAlphaColorCGFloat; LColor: CGColorRef; - LCallback: CGFunctionCallbacks; - LShading: CGShadingRef; - LFunc: CGFunctionRef; - LBitmapData: TBitmapData; - LTmpContext: CGContextRef; - LImageRef: CGImageRef; - LImage: UIImage; {$ELSEIF defined(MSWINDOWS) or defined(ALMacOS)} var LShapeRect: TRectF; - Off: Single; - StrokeThicknessRestoreValue: Single; - FillShape, DrawShape: Boolean; + LOff: Single; + LFillKindRestoreValue: TBrushKind; + LFillColorRestoreValue: TAlphacolor; + LStrokeKindRestoreValue: TBrushKind; + LStrokeColorRestoreValue: TAlphacolor; + LStrokeThicknessRestoreValue: Single; + LFillShape, LDrawShape: Boolean; + LShadowEffect: TshadowEffect; {$ENDIF} begin @@ -8068,127 +8088,37 @@ procedure ALPaintRectangle( LPaint.setDither(true); // Enabling this flag applies a dither to any blit operation where the target's colour space is more constrained than the source. //init LRect - if Stroke.Kind <> TBrushKind.None then begin + if StrokeColor <> TalphaColorRec.Null then begin LRect := TrectF.Create( - dstRect.Left + (Stroke.Thickness / 2), - dstRect.Top + (Stroke.Thickness / 2), - dstRect.right - (Stroke.Thickness / 2), - dstRect.bottom - (Stroke.Thickness / 2)); // http://stackoverflow.com/questions/17038017/ios-draw-filled-circles + dstRect.Left + (StrokeThickness / 2), + dstRect.Top + (StrokeThickness / 2), + dstRect.right - (StrokeThickness / 2), + dstRect.bottom - (StrokeThickness / 2)); // http://stackoverflow.com/questions/17038017/ios-draw-filled-circles end else LRect := dstRect; // << stupid bug https://quality.embarcadero.com/browse/RSP-16607 //fill the rectangle - if Fill.Kind <> TBrushKind.None then begin + if FillColor <> TalphaColorRec.Null then begin //init LPaint - LPaint.setStyle(TJPaint_Style.JavaClass.FILL); // FILL_AND_STROCK it's absolutely useless, because it's will fill on the full LRect + Stroke.Thickness :( this result&ing in border if the fill is for exemple black and border white - - //fill with gradient - if Fill.Kind = TBrushKind.Gradient then begin - if Fill.Gradient.Style = TGradientStyle.Radial then begin - LColors := TJavaArray.Create(Fill.Gradient.Points.Count); - LStops := TJavaArray.Create(Fill.Gradient.Points.Count); - for i := 0 to Fill.Gradient.Points.Count - 1 do begin - LColors[Fill.Gradient.Points.Count - 1 - i] := integer(Fill.Gradient.Points[i].Color); - LStops[Fill.Gradient.Points.Count - 1 - i] := 1 - Fill.Gradient.Points[i].Offset; - end; - LRadialShader := TJRadialGradient.JavaClass.init( - LRect.CenterPoint.x{x}, - LRect.CenterPoint.y{y}, - LRect.width / 2{radius}, - LColors, - LStops, - TJShader_TileMode.JavaClass.CLAMP{tile}); - LPaint.setShader(LRadialShader); - _drawRect(aCanvas, LPaint, LRect, false{aDrawOnlyBorder}); - LPaint.setShader(nil); - LRadialShader := nil; - ALfreeandNil(LColors); - ALfreeandNil(LStops); - end - else if Fill.Gradient.Style = TGradientStyle.Linear then begin - LColors := TJavaArray.Create(Fill.Gradient.Points.Count); - LStops := TJavaArray.Create(Fill.Gradient.Points.Count); - for i := 0 to Fill.Gradient.Points.Count - 1 do begin - LColors[i] := integer(Fill.Gradient.Points[i].Color); - LStops[i] := Fill.Gradient.Points[i].Offset; - end; - LLinearShader := TJLinearGradient.JavaClass.init( - LRect.TopLeft.x + (Fill.Gradient.StartPosition.X * LRect.Width){x0}, - LRect.TopLeft.y + (Fill.Gradient.StartPosition.Y * LRect.Height){y0}, - LRect.BottomRight.x + (Fill.Gradient.StopPosition.X * LRect.Width){x1}, - LRect.BottomRight.y + (Fill.Gradient.StopPosition.Y * LRect.Height){y1}, - LColors, - LStops, - TJShader_TileMode.JavaClass.CLAMP{tile}); - LPaint.setShader(LLinearShader); - _drawRect(aCanvas, LPaint, LRect, false{aDrawOnlyBorder}); - LPaint.setShader(nil); - LLinearShader := nil; - ALfreeandNil(LColors); - ALfreeandNil(LStops); - end; - end - - //fill with bitmap - else if Fill.Kind = TBrushKind.Bitmap then begin - if not fill.Bitmap.Bitmap.IsEmpty then begin - if fill.Bitmap.WrapMode = TWrapMode.TileStretch then begin - //----- - LTmpBitmap := TJBitmap.JavaClass.createBitmap(fill.Bitmap.Bitmap.Width, fill.Bitmap.Bitmap.height, TJBitmap_Config.JavaClass.ARGB_8888); - //----- - FillChar(LBitmapInfo, SizeOf(LBitmapInfo), 0); - if (AndroidBitmap_getInfo(TJNIResolver.GetJNIEnv, (LTmpBitmap as ILocalObject).GetObjectID, @LBitmapInfo) = 0) and - (AndroidBitmap_lockPixels(TJNIResolver.GetJNIEnv, (LTmpBitmap as ILocalObject).GetObjectID, @LPixelBuffer) = 0) then - try - if fill.Bitmap.Bitmap.Map(TMapAccess.Read, LBitmapData) then - try - ALMove(LBitmapData.Data^, LPixelBuffer^, LBitmapData.Pitch * LBitmapData.Height); - finally - fill.Bitmap.Bitmap.Unmap(LBitmapData); - end; - finally - AndroidBitmap_unlockPixels(TJNIResolver.GetJNIEnv, (LTmpBitmap as ILocalObject).GetObjectID); - end; - //----- - _drawRect(aCanvas, LPaint, LRect, false{aDrawOnlyBorder}); - LPorterDuffXfermode := TJPorterDuffXfermode.JavaClass.init(TJPorterDuff_Mode.JavaClass.SRC_IN); - LJDestRectf := TJRectf.JavaClass.init(LRect.left, LRect.top, LRect.right, LRect.bottom); - LJSrcRect := TJRect.JavaClass.init(0, 0, fill.Bitmap.Bitmap.Width, fill.Bitmap.Bitmap.height); - LPaint.setXfermode(LPorterDuffXfermode); - aCanvas.drawBitmap(LTmpBitmap, LJSrcRect, LJDestRectf, LPaint); - LPaint.setXfermode(nil); - LPorterDuffXfermode := nil; - LJSrcRect := nil; - LJDestRectf := nil; - //----- - LTmpBitmap.recycle; - LTmpBitmap := nil; - //----- - end; - end; - end + LPaint.setStyle(TJPaint_Style.JavaClass.FILL); // FILL_AND_STROCK it's absolutely useless, because it's will fill on the full LRect + StrokeThickness :( this result&ing in border if the fill is for exemple black and border white //fill with solid color - else if Fill.Kind = TBrushKind.Solid then begin - LPaint.setColor(integer(Fill.Color)); - _drawRect(aCanvas, LPaint, LRect, false{aDrawOnlyBorder}); - end; + LPaint.setColor(integer(FillColor)); + _drawRect(aCanvas, LPaint, LRect, false{aDrawOnlyBorder}); end; //stroke the rectangle - if Stroke.Kind <> TBrushKind.None then begin + if StrokeColor <> TalphaColorRec.Null then begin //init LPaint LPaint.setStyle(TJPaint_Style.JavaClass.STROKE); - LPaint.setStrokeWidth(Stroke.Thickness); + LPaint.setStrokeWidth(StrokeThickness); //stroke with solid color - if Stroke.Kind = TBrushKind.Solid then begin - LPaint.setColor(integer(Stroke.Color)); - _drawRect(aCanvas, LPaint, LRect, true{aDrawOnlyBorder}); - end; + LPaint.setColor(integer(StrokeColor)); + _drawRect(aCanvas, LPaint, LRect, true{aDrawOnlyBorder}); end; @@ -8200,107 +8130,911 @@ procedure ALPaintRectangle( //set the paint default properties CGContextSetInterpolationQuality(aContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. http://stackoverflow.com/questions/5685884/imagequality-with-cgcontextsetinterpolationquality //----- - CGContextSetShouldAntialias(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(aContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(aContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. //init LRect - if Stroke.Kind <> TBrushKind.None then begin + if StrokeColor <> TalphaColorRec.Null then begin LRect := TrectF.Create( - DstRect.Left + (Stroke.Thickness / 2), - DstRect.Top + (Stroke.Thickness / 2), - DstRect.right - (Stroke.Thickness / 2), - DstRect.bottom - (Stroke.Thickness / 2)); // http://stackoverflow.com/questions/17038017/ios-draw-filled-circles + DstRect.Left + (StrokeThickness / 2), + DstRect.Top + (StrokeThickness / 2), + DstRect.right - (StrokeThickness / 2), + DstRect.bottom - (StrokeThickness / 2)); // http://stackoverflow.com/questions/17038017/ios-draw-filled-circles end else LRect := DstRect; // << stupid bug https://quality.embarcadero.com/browse/RSP-16607 //fill the rectangle - if Fill.Kind <> TBrushKind.None then begin - - //fill with gradient - if Fill.Kind = TBrushKind.Gradient then begin - if Fill.Gradient.Style in [TGradientStyle.Radial, - TGradientStyle.Linear] then begin - CGContextSaveGState(aContext); - //----- - LCallback.version := 0; - LCallback.evaluate := @ALGradientEvaluateCallback; - LCallback.releaseInfo:= nil; - LFunc := CGFunctionCreate( - fill.Gradient, // info - A pointer to user-defined storage for data that you want to pass to your callbacks. - 1, // domainDimension - The number of inputs. - @aDefaultInputRange, // domain - An array of (2*domainDimension) floats used to specify the valid intervals of input values - 4, // rangeDimension - The number of outputs. - nil, // range - An array of (2*rangeDimension) floats that specifies the valid intervals of output values - @LCallback); // callbacks - A pointer to a callback function table. - try - if Fill.Gradient.Style = TGradientStyle.Radial then begin - LShading := CGShadingCreateRadial( - aColorSpace, // colorspace - CGPoint.Create(TPointF.Create(LRect.Width / 2, aGridHeight - (LRect.height / 2))), // start - The center of the starting circle, in the shading's target coordinate space. - LRect.Width / 2, // startRadius - The radius of the starting circle, in the shading's target coordinate space. - CGPoint.Create(TPointF.Create(LRect.Width / 2, aGridHeight - (LRect.Height / 2))), // end - The center of the ending circle, in the shading's target coordinate space. - 0, // endRadius - The radius of the ending circle, in the shading's target coordinate space. - LFunc, // function - {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}, // extendStart - A Boolean value that specifies whether to extend the shading beyond the starting circle. - {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // extendEnd - A Boolean value that specifies whether to extend the shading beyond the ending circle. - end - else begin - LShading := CGShadingCreateAxial( - aColorSpace, // colorspace - CGPointMake( - LRect.Left + (Fill.Gradient.StartPosition.X * LRect.Width), - aGridHeight - LRect.top - (Fill.Gradient.StartPosition.Y * LRect.Height)), // start - The starting point of the axis, in the shading's target coordinate space. - CGPointMake( - LRect.Left + (Fill.Gradient.StopPosition.X * LRect.Width), - aGridHeight - LRect.top - (Fill.Gradient.StopPosition.Y * LRect.Height)), // end - The ending point of the axis, in the shading's target coordinate space. - LFunc, // function - {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}, // extendStart - A Boolean value that specifies whether to extend the shading beyond the starting point of the axis. - {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // extendEnd - A Boolean value that specifies whether to extend the shading beyond the ending point of the axis. - end; - try - _DrawPath(LRect, false{aDrawOnlyBorder}); - CGContextClip(aContext); // Modifies the current clipping path, using the nonzero winding number rule. - // Unlike the current path, the current clipping path is part of the graphics state. Therefore, - // to re-enlarge the paintable area by restoring the clipping path to a prior state, you must - // save the graphics state before you clip and restore the graphics state after you’ve completed - // any clipped drawing. - //----- - if (Shadow <> nil) and - (Shadow.enabled) then begin - LAlphaColor := TAlphaColorCGFloat.Create(Shadow.ShadowColor); - LColor := CGColorCreate(aColorSpace, @LAlphaColor); - try - CGContextSetShadowWithColor( - aContext, - CGSizeMake(Shadow.OffsetX, Shadow.OffsetY), // offset - Shadow.blur, // blur - LColor); // color - finally - CGColorRelease(LColor); - end; - end; - //----- - CGContextDrawShading(aContext, LShading); - //----- - if (Shadow <> nil) and - (Shadow.enabled) then begin - CGContextSetShadowWithColor( - aContext, - CGSizeMake(0, 0), // offset - 0, // blur - nil); // color - end; - //----- - finally - CGShadingRelease(LShading); - end; - finally - CGFunctionRelease(LFunc); - end; - //----- - CGContextRestoreGState(aContext); - end; - end + if FillColor <> TalphaColorRec.Null then begin + + //fill with solid color + LAlphaColor := TAlphaColorCGFloat.Create(FillColor); + CGContextSetRGBFillColor(aContext, LAlphaColor.R, LAlphaColor.G, LAlphaColor.B, LAlphaColor.A); + _DrawPath(LRect, false{aDrawOnlyBorder}); + //----- + if (ShadowColor <> TalphaColorRec.Null) then begin + LAlphaColor := TAlphaColorCGFloat.Create(ShadowColor); + LColor := CGColorCreate(aColorSpace, @LAlphaColor); + try + CGContextSetShadowWithColor( + aContext, + CGSizeMake(ShadowOffsetX, ShadowOffsetY), // offset + ShadowBlur, // blur + LColor); // color + finally + CGColorRelease(LColor); + end; + end; + //----- + CGContextFillPath(aContext); + //----- + if (ShadowColor <> TalphaColorRec.Null) then begin + CGContextSetShadowWithColor( + aContext, + CGSizeMake(0, 0), // offset + 0, // blur + nil); // color + end; + + end; + + //stroke the rectangle + if StrokeColor <> TalphaColorRec.Null then begin + + //stroke with solid color + LAlphaColor := TAlphaColorCGFloat.Create(StrokeColor); + CGContextSetRGBStrokeColor(aContext, LAlphaColor.R, LAlphaColor.G, LAlphaColor.B, LAlphaColor.A); + CGContextSetLineWidth(aContext, StrokeThickness); + _DrawPath(LRect, True{aDrawOnlyBorder}); + CGContextStrokePath(aContext); + + end; + + {$ELSEIF defined(MSWINDOWS) or defined(ALMacOS)} + + LFillKindRestoreValue := ACanvas.Fill.Kind; + LFillColorRestoreValue := ACanvas.Fill.color; + LStrokeKindRestoreValue := ACanvas.Stroke.kind; + LStrokeColorRestoreValue := ACanvas.Stroke.Color; + LStrokeThicknessRestoreValue := ACanvas.Stroke.Thickness; + if FillColor <> TAlphaColorRec.Null then begin + ACanvas.Fill.Kind := TBrushKind.Solid; + ACanvas.Fill.Color := FillColor; + end + else ACanvas.Fill.Kind := TBrushKind.None; + If StrokeColor <> TalphaColorRec.Null then begin + ACanvas.Stroke.Kind := TBrushKind.Solid; + ACanvas.Stroke.Color := StrokeColor; + ACanvas.Stroke.Thickness := StrokeThickness; + end + else ACanvas.Stroke.Kind := TBrushKind.None; + try + + LShapeRect := ALGetDrawingShapeRectAndSetThickness(DstRect, ACanvas.Fill, ACanvas.Stroke, False, LFillShape, LDrawShape, LStrokeThicknessRestoreValue); + + if Sides <> AllSides then + begin + LOff := LShapeRect.Left; + if not(TSide.Top in Sides) then + LShapeRect.Top := LShapeRect.Top - LOff; + if not(TSide.Left in Sides) then + LShapeRect.Left := LShapeRect.Left - LOff; + if not(TSide.Bottom in Sides) then + LShapeRect.Bottom := LShapeRect.Bottom + LOff; + if not(TSide.Right in Sides) then + LShapeRect.Right := LShapeRect.Right + LOff; + if LFillShape then + aCanvas.FillRect(LShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, ACanvas.Fill, TCornerType.Round{CornerType}); + if LDrawShape then + aCanvas.DrawRectSides(_GetShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, Sides, ACanvas.Stroke, TCornerType.Round{CornerType}); + end + else + begin + if LFillShape then + aCanvas.FillRect(LShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, ACanvas.Fill, TCornerType.Round{CornerType}); + if LDrawShape then + aCanvas.DrawRect(LShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, ACanvas.Stroke, TCornerType.Round{CornerType}); + end; + + if (ShadowColor <> TalphaColorRec.Null) then begin + + LShadowEffect := TshadowEffect.Create(nil); + try + LShadowEffect.ShadowColor := ShadowColor; + LShadowEffect.distance := 0; // Specifies the distance between the shadow and the visual object to which TShadowEffect is applied. + // i m too lazy to calculate this from fShadow.offsetX / fShadow.offsetY - if someone want to do it + LShadowEffect.Direction := 0; // Specifies the direction (in degrees) of the shadow. + // i m too lazy to calculate this from fShadow.offsetX / fShadow.offsetY - if someone want to do it + LShadowEffect.Opacity := 1; // Opacity is a System.Single value that takes values in the range from 0 through 1. + // we use the opacity of the color instead + LShadowEffect.softness := ShadowBlur / 24; // Specifies the amount of blur applied to the shadow. + // Softness is a System.Single value that takes values in the range from 0 through 9. + // i calculate approximatly that 0.5 = around 12 for blur + Acanvas.Flush; + LShadowEffect.ProcessEffect(ACanvas, Acanvas.Bitmap, 1); + finally + ALFreeAndNil(LShadowEffect); + end; + + if Sides <> AllSides then + begin + if LFillShape then + aCanvas.FillRect(LShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, ACanvas.Fill, TCornerType.Round{CornerType}); + if LDrawShape then + aCanvas.DrawRectSides(_GetShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, Sides, ACanvas.Stroke, TCornerType.Round{CornerType}); + end + else + begin + if LFillShape then + aCanvas.FillRect(LShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, ACanvas.Fill, TCornerType.Round{CornerType}); + if LDrawShape then + aCanvas.DrawRect(LShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, ACanvas.Stroke, TCornerType.Round{CornerType}); + end; + + end; + + finally + ACanvas.Fill.Kind := LFillKindRestoreValue; + ACanvas.Fill.color := LFillColorRestoreValue; + ACanvas.Stroke.kind := LStrokeKindRestoreValue; + ACanvas.Stroke.Color := LStrokeColorRestoreValue; + ACanvas.Stroke.Thickness := LStrokeThicknessRestoreValue; + end; + + {$ENDIF} + +end; + +{*************************} +procedure ALPaintRectangle( + {$IF defined(ANDROID)} + const aCanvas: Jcanvas; + {$ELSEIF defined(IOS)} + const aContext: CGContextRef; + const aColorSpace: CGColorSpaceRef; + const aGridHeight: Single; + {$ELSEIF defined(MSWINDOWS) or defined(ALMacOS)} + const aCanvas: Tcanvas; + {$ENDIF} + const dstRect: TrectF; + const Fill: TBrush; + const Stroke: TStrokeBrush; + const Shadow: TALShadow; // If shadow is not nil, then the Canvas must have enough space to draw the shadow (approximately Shadow.blur on each side of the rectangle) + const Sides: TSides; + const Corners: TCorners; + const XRadius: Single; + const YRadius: Single); + + {$REGION ' _drawRect (ANDROID)'} + {$IF defined(ANDROID)} + procedure _drawRect( + const aCanvas: Jcanvas; + const aPaint: JPaint; + const aRect: TrectF; + Const aDrawOnlyBorder: Boolean); + var LJRect: JRectF; + LPath: JPath; + LXRadius: single; + LYradius: Single; + LWidthMinusCorners: single; + LHeightMinusCorners: Single; + LCorners: TCorners; + LHalfStrokeWidth: Single; + begin + + // use drawRoundRect + if ((compareValue(xRadius, 0, TEpsilon.position) > 0) and + (compareValue(YRadius, 0, TEpsilon.position) > 0)) and + (corners=[TCorner.TopLeft, TCorner.TopRight, TCorner.BottomLeft, TCorner.BottomRight]) and + (sides=[TSide.Top, TSide.Left, TSide.Bottom, TSide.Right]) then begin + //----- + if (not aDrawOnlyBorder) and + (Shadow <> nil) and + (Shadow.enabled) then aPaint.setShadowLayer(Shadow.blur{radius}, Shadow.OffsetX{dx}, Shadow.OffsetY{dy}, integer(Shadow.ShadowColor){shadowColor}); + + LJRect := TJRectf.JavaClass.init(aRect.left, aRect.top, aRect.right, aRect.bottom); + aCanvas.drawRoundRect( + LJRect{rect}, + xRadius {rx}, + yRadius {ry}, + apaint); + LJRect := nil; + + if (not aDrawOnlyBorder) and + (Shadow <> nil) and + (Shadow.enabled) then aPaint.clearShadowLayer; + //----- + end + + // use drawRect + else if ((compareValue(xRadius, 0, TEpsilon.position) = 0) or + (compareValue(YRadius, 0, TEpsilon.position) = 0) or + (corners=[])) and + (sides=[TSide.Top, TSide.Left, TSide.Bottom, TSide.Right]) then begin + //----- + if (not aDrawOnlyBorder) and + (Shadow <> nil) and + (Shadow.enabled) then aPaint.setShadowLayer(Shadow.blur{radius}, Shadow.OffsetX{dx}, Shadow.OffsetY{dy}, integer(Shadow.ShadowColor){shadowColor}); + + aCanvas.drawRect( + aRect.left{left}, + aRect.top{top}, + aRect.right{right}, + aRect.bottom{bottom}, + apaint); + + if (not aDrawOnlyBorder) and + (Shadow <> nil) and + (Shadow.enabled) then aPaint.clearShadowLayer; + //----- + end + + // use drawPath + else begin + + LPath := TJPath.Create; + //---- + LXRadius := xRadius; + LYradius := yRadius; + if (LXRadius > aRect.width / 2) then LXRadius := aRect.width / 2; + if (LYradius > aRect.height / 2) then LYradius := aRect.height / 2; + //---- + if (compareValue(LXRadius, 0, TEpsilon.position) > 0) and + (compareValue(LYradius, 0, TEpsilon.position) > 0) then LCorners := corners + else LCorners := []; + //---- + LWidthMinusCorners := (aRect.width - (2 * LXRadius)); + LHeightMinusCorners := (aRect.height - (2 * LYradius)); + //---- + if (Stroke.Kind <> TBrushKind.None) then LHalfStrokeWidth := (Stroke.Thickness) / 2 + else LHalfStrokeWidth := 0; + + + //----- TopRight + if (TCorner.TopRight in LCorners) then begin + LPath.moveTo(aRect.right, aRect.top + LYradius); + LPath.rQuadTo(0, -LYradius, -LXRadius, -LYradius); + if not aDrawOnlyBorder then LPath.rlineTo(0, -LHalfStrokeWidth); + end + else begin + if not aDrawOnlyBorder then LPath.moveTo(aRect.right + LHalfStrokeWidth, aRect.top + LYradius) + else LPath.moveTo(aRect.right, aRect.top + LYradius); + //---- + if (not aDrawOnlyBorder) or + (TSide.right in sides) then begin + LPath.rLineTo(0, -LYradius -LHalfStrokeWidth); + if aDrawOnlyBorder then LPath.rMoveTo(0, LHalfStrokeWidth); + end + else LPath.rMoveTo(0, -LYradius); // aDrawOnlyBorder AND not TSide.right + //---- + if (not aDrawOnlyBorder) or + (TSide.top in sides) then begin + if not aDrawOnlyBorder then LPath.rLineTo(-LXRadius -LHalfStrokeWidth,0) + else begin + LPath.rMoveTo(+LHalfStrokeWidth,0); + LPath.rLineTo(-LXRadius -LHalfStrokeWidth,0); + end; + end + else LPath.rMoveTo(-LXRadius,0); // aDrawOnlyBorder AND not TSide.top + end; + //----- + if (not aDrawOnlyBorder) or + (TSide.Top in sides) then LPath.rLineTo(-LWidthMinusCorners, 0) + else LPath.rMoveTo(-LWidthMinusCorners, 0); + + //----- TopLeft + if (TCorner.TopLeft in LCorners) then begin + if not aDrawOnlyBorder then LPath.rlineTo(0, +LHalfStrokeWidth); + LPath.rQuadTo(-LXRadius, 0, -LXRadius, LYradius); + if not aDrawOnlyBorder then LPath.rlineTo(-LHalfStrokeWidth, 0); + end + else begin + if (not aDrawOnlyBorder) or + (TSide.top in sides) then begin + LPath.rLineTo(-LXRadius -LHalfStrokeWidth, 0); + if aDrawOnlyBorder then LPath.rMoveTo(LHalfStrokeWidth, 0); + end + else LPath.rMoveTo(-LXRadius, 0); // aDrawOnlyBorder AND not TSide.top + //---- + if (not aDrawOnlyBorder) or + (TSide.left in sides) then begin + if not aDrawOnlyBorder then LPath.rLineTo(0,LYradius +LHalfStrokeWidth) + else begin + LPath.rMoveTo(0,-LHalfStrokeWidth); + LPath.rLineTo(0,+LYradius +LHalfStrokeWidth); + end; + end + else LPath.rMoveTo(0,LYradius); // aDrawOnlyBorder AND not TSide.left + end; + //----- + if (not aDrawOnlyBorder) or + (TSide.left in sides) then LPath.rLineTo(0, LHeightMinusCorners) + else LPath.rMoveTo(0, LHeightMinusCorners); + + //----- BottomLeft + if (TCorner.BottomLeft in LCorners) then begin + if not aDrawOnlyBorder then LPath.rlineTo(LHalfStrokeWidth, 0); + LPath.rQuadTo(0, LYradius, LXRadius, LYradius); + if not aDrawOnlyBorder then LPath.rlineTo(0, LHalfStrokeWidth); + end + else begin + if (not aDrawOnlyBorder) or + (TSide.left in sides) then begin + LPath.rLineTo(0, LYradius +LHalfStrokeWidth); + if aDrawOnlyBorder then LPath.rMoveTo(0, -LHalfStrokeWidth); + end + else LPath.rMoveTo(0, LYradius); // aDrawOnlyBorder AND not TSide.left + //---- + if (not aDrawOnlyBorder) or + (TSide.bottom in sides) then begin + if not aDrawOnlyBorder then LPath.rLineTo(LXRadius +LHalfStrokeWidth,0) + else begin + LPath.rMoveTo(-LHalfStrokeWidth,0); + LPath.rLineTo(+LXRadius +LHalfStrokeWidth,0); + end; + end + else LPath.rMoveTo(LXRadius,0); // aDrawOnlyBorder AND not TSide.bottom + end; + //----- + if (not aDrawOnlyBorder) or + (TSide.bottom in sides) then LPath.rLineTo(LWidthMinusCorners, 0) + else LPath.rMoveTo(LWidthMinusCorners, 0); + + //----- BottomRight + if (TCorner.BottomRight in LCorners) then begin + if not aDrawOnlyBorder then LPath.rlineTo(0, -LHalfStrokeWidth); + LPath.rQuadTo(LXRadius, 0, LXRadius, -LYradius); + if not aDrawOnlyBorder then LPath.rlineTo(LHalfStrokeWidth, 0); + end + else begin + if (not aDrawOnlyBorder) or + (TSide.bottom in sides) then begin + LPath.rLineTo(LXRadius +LHalfStrokeWidth,0); + if aDrawOnlyBorder then LPath.rMoveTo(-LHalfStrokeWidth, 0); + end + else LPath.rMoveTo(LXRadius,0); // aDrawOnlyBorder AND not TSide.bottom + //---- + if (not aDrawOnlyBorder) or + (TSide.right in sides) then begin + if not aDrawOnlyBorder then LPath.rLineTo(0, -LYradius -LHalfStrokeWidth) + else begin + LPath.rMoveTo(0,+LHalfStrokeWidth); + LPath.rLineTo(0,-LYradius -LHalfStrokeWidth); + end; + end + else LPath.rMoveTo(0, -LYradius); // aDrawOnlyBorder AND not TSide.right + end; + //----- + if (not aDrawOnlyBorder) or + (TSide.right in sides) then LPath.rLineTo(0, -LHeightMinusCorners) + else LPath.rMoveTo(0, -LHeightMinusCorners); + + //----- + if (not aDrawOnlyBorder) and + (Shadow <> nil) and + (Shadow.enabled) then aPaint.setShadowLayer(Shadow.blur{radius}, Shadow.OffsetX{dx}, Shadow.OffsetY{dy}, integer(Shadow.ShadowColor){shadowColor}); + + aCanvas.drawPath(LPath,aPaint); + LPath := nil; + + if (not aDrawOnlyBorder) and + (Shadow <> nil) and + (Shadow.enabled) then aPaint.clearShadowLayer; + //----- + + end; + end; + {$ENDIF} + {$ENDREGION} + + {$REGION ' _DrawPath (IOS)'} + {$IF defined(IOS)} + procedure _DrawPath( + const aRect: TrectF; + Const aDrawOnlyBorder: Boolean); + + var LXRadius: single; + LYradius: Single; + LWidthMinusCorners: single; + LHeightMinusCorners: Single; + LCorners: TCorners; + LHalfStrokeWidth: Single; + LCurPoint: TpointF; + + {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~} + procedure _moveTo(x: Single; y: Single); + begin + CGContextMoveToPoint(aContext, X, aGridHeight - Y); + LCurPoint.X := x; + LCurPoint.Y := Y; + end; + + {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~} + procedure _rQuadTo(dx1: Single; dy1: Single; dx2: Single; dy2: Single); + begin + CGContextAddQuadCurveToPoint( + aContext, + LCurPoint.X + dx1{cpx}, + aGridHeight - (LCurPoint.Y + dy1){cpy}, + LCurPoint.X + dx2{x}, + aGridHeight - (LCurPoint.Y + dy2){y}); + LCurPoint.X := LCurPoint.X + dx2; + LCurPoint.Y := LCurPoint.Y + dy2; + end; + + {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~} + procedure _rLineTo(dx: Single; dy: Single); + begin + CGContextAddLineToPoint(aContext, LCurPoint.X + dx{x}, aGridHeight - (LCurPoint.Y + dy{y})); + LCurPoint.X := LCurPoint.X + dx; + LCurPoint.Y := LCurPoint.Y + dy; + end; + + {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~} + procedure _rMoveTo(dx: Single; dy: Single); + begin + CGContextMoveToPoint(aContext, LCurPoint.X + dx{x}, aGridHeight - (LCurPoint.Y + dy{y})); + LCurPoint.X := LCurPoint.X + dx; + LCurPoint.Y := LCurPoint.Y + dy; + end; + + begin + + // Creates a new empty path in a graphics context. + CGContextBeginPath(aContext); + + // use drawRect + if ((compareValue(xRadius, 0, TEpsilon.position) = 0) or + (compareValue(YRadius, 0, TEpsilon.position) = 0) or + (corners=[])) and + (sides=[TSide.Top, TSide.Left, TSide.Bottom, TSide.Right]) then begin + //----- + CGContextAddRect( + aContext, + ALLowerLeftCGRect( + aRect.TopLeft, + aRect.Width, + aRect.Height, + aGridHeight)); + //----- + end + + // use drawPath + else begin + + LXRadius := xRadius; + LYradius := yRadius; + if (LXRadius > aRect.width / 2) then LXRadius := aRect.width / 2; + if (LYradius > aRect.height / 2) then LYradius := aRect.height / 2; + //---- + if (compareValue(LXRadius, 0, TEpsilon.position) > 0) and + (compareValue(LYradius, 0, TEpsilon.position) > 0) then LCorners := corners + else LCorners := []; + //---- + LWidthMinusCorners := (aRect.width - (2 * LXRadius)); + LHeightMinusCorners := (aRect.height - (2 * LYradius)); + //---- + if (Stroke.Kind <> TBrushKind.None) then LHalfStrokeWidth := (Stroke.Thickness) / 2 + else LHalfStrokeWidth := 0; + + + //----- TopRight + if (TCorner.TopRight in LCorners) then begin + _moveTo(aRect.right, aRect.top + LYradius); + _rQuadTo(0, -LYradius, -LXRadius, -LYradius); + if not aDrawOnlyBorder then _rlineTo(0, -LHalfStrokeWidth); + end + else begin + if not aDrawOnlyBorder then _moveTo(aRect.right + LHalfStrokeWidth, aRect.top + LYradius) + else _moveTo(aRect.right, aRect.top + LYradius); + //---- + if (not aDrawOnlyBorder) or + (TSide.right in sides) then begin + _rLineTo(0, -LYradius -LHalfStrokeWidth); + if aDrawOnlyBorder then _rMoveTo(0, LHalfStrokeWidth); + end + else _rMoveTo(0, -LYradius); // aDrawOnlyBorder AND not TSide.right + //---- + if (not aDrawOnlyBorder) or + (TSide.top in sides) then begin + if not aDrawOnlyBorder then _rLineTo(-LXRadius -LHalfStrokeWidth,0) + else begin + _rMoveTo(+LHalfStrokeWidth,0); + _rLineTo(-LXRadius -LHalfStrokeWidth,0); + end; + end + else _rMoveTo(-LXRadius,0); // aDrawOnlyBorder AND not TSide.top + end; + //----- + if (not aDrawOnlyBorder) or + (TSide.Top in sides) then _rLineTo(-LWidthMinusCorners, 0) + else _rMoveTo(-LWidthMinusCorners, 0); + + //----- TopLeft + if (TCorner.TopLeft in LCorners) then begin + if not aDrawOnlyBorder then _rlineTo(0, +LHalfStrokeWidth); + _rQuadTo(-LXRadius, 0, -LXRadius, LYradius); + if not aDrawOnlyBorder then _rlineTo(-LHalfStrokeWidth, 0); + end + else begin + if (not aDrawOnlyBorder) or + (TSide.top in sides) then begin + _rLineTo(-LXRadius -LHalfStrokeWidth, 0); + if aDrawOnlyBorder then _rMoveTo(LHalfStrokeWidth, 0); + end + else _rMoveTo(-LXRadius, 0); // aDrawOnlyBorder AND not TSide.top + //---- + if (not aDrawOnlyBorder) or + (TSide.left in sides) then begin + if not aDrawOnlyBorder then _rLineTo(0,LYradius +LHalfStrokeWidth) + else begin + _rMoveTo(0,-LHalfStrokeWidth); + _rLineTo(0,+LYradius +LHalfStrokeWidth); + end; + end + else _rMoveTo(0,LYradius); // aDrawOnlyBorder AND not TSide.left + end; + //----- + if (not aDrawOnlyBorder) or + (TSide.left in sides) then _rLineTo(0, LHeightMinusCorners) + else _rMoveTo(0, LHeightMinusCorners); + + //----- BottomLeft + if (TCorner.BottomLeft in LCorners) then begin + if not aDrawOnlyBorder then _rlineTo(LHalfStrokeWidth, 0); + _rQuadTo(0, LYradius, LXRadius, LYradius); + if not aDrawOnlyBorder then _rlineTo(0, LHalfStrokeWidth); + end + else begin + if (not aDrawOnlyBorder) or + (TSide.left in sides) then begin + _rLineTo(0, LYradius +LHalfStrokeWidth); + if aDrawOnlyBorder then _rMoveTo(0, -LHalfStrokeWidth); + end + else _rMoveTo(0, LYradius); // aDrawOnlyBorder AND not TSide.left + //---- + if (not aDrawOnlyBorder) or + (TSide.bottom in sides) then begin + if not aDrawOnlyBorder then _rLineTo(LXRadius +LHalfStrokeWidth,0) + else begin + _rMoveTo(-LHalfStrokeWidth,0); + _rLineTo(+LXRadius +LHalfStrokeWidth,0); + end; + end + else _rMoveTo(LXRadius,0); // aDrawOnlyBorder AND not TSide.bottom + end; + //----- + if (not aDrawOnlyBorder) or + (TSide.bottom in sides) then _rLineTo(LWidthMinusCorners, 0) + else _rMoveTo(LWidthMinusCorners, 0); + + //----- BottomRight + if (TCorner.BottomRight in LCorners) then begin + if not aDrawOnlyBorder then _rlineTo(0, -LHalfStrokeWidth); + _rQuadTo(LXRadius, 0, LXRadius, -LYradius); + if not aDrawOnlyBorder then _rlineTo(LHalfStrokeWidth, 0); + end + else begin + if (not aDrawOnlyBorder) or + (TSide.bottom in sides) then begin + _rLineTo(LXRadius +LHalfStrokeWidth,0); + if aDrawOnlyBorder then _rMoveTo(-LHalfStrokeWidth, 0); + end + else _rMoveTo(LXRadius,0); // aDrawOnlyBorder AND not TSide.bottom + //---- + if (not aDrawOnlyBorder) or + (TSide.right in sides) then begin + if not aDrawOnlyBorder then _rLineTo(0, -LYradius -LHalfStrokeWidth) + else begin + _rMoveTo(0,+LHalfStrokeWidth); + _rLineTo(0,-LYradius -LHalfStrokeWidth); + end; + end + else _rMoveTo(0, -LYradius); // aDrawOnlyBorder AND not TSide.right + end; + //----- + if (not aDrawOnlyBorder) or + (TSide.right in sides) then _rLineTo(0, -LHeightMinusCorners) + else _rMoveTo(0, -LHeightMinusCorners); + + end; + + end; + {$ENDIF} + {$ENDREGION} + + {$REGION ' _GetShapeRect (MSWINDOWS / ALMacOS)'} + {$IF defined(MSWINDOWS) or defined(ALMacOS)} + function _GetShapeRect: TRectF; + begin + Result := DstRect; + if Stroke.Kind <> TBrushKind.None then + InflateRect(Result, -(Stroke.Thickness / 2), -(Stroke.Thickness / 2)); + end; + {$ENDIF} + {$ENDREGION} + +{$IF defined(IOS)} +const DefaultInputRange: array[0..1] of CGFloat = (0, 1); +{$ENDIF} + +{$IF defined(ANDROID)} +var LRect: TrectF; + LTmpBitmap: Jbitmap; + LRadialShader: JRadialGradient; + LLinearShader: JLinearGradient; + LPaint: JPaint; + LColors: TJavaArray; + LStops: TJavaArray; + LPorterDuffXfermode: jPorterDuffXfermode; + LBitmapInfo: AndroidBitmapInfo; + LPixelBuffer: Pointer; + LBitmapData: TBitmapData; + LJDestRectf: JrectF; + LJSrcRect: Jrect; + i: integer; +{$ELSEIF defined(IOS)} +var LRect: TrectF; + LAlphaColor: TAlphaColorCGFloat; + LColor: CGColorRef; + LCallback: CGFunctionCallbacks; + LShading: CGShadingRef; + LFunc: CGFunctionRef; + LBitmapData: TBitmapData; + LTmpContext: CGContextRef; + LImageRef: CGImageRef; + LImage: UIImage; +{$ELSEIF defined(MSWINDOWS) or defined(ALMacOS)} +var LShapeRect: TRectF; + LOff: Single; + LStrokeThicknessRestoreValue: Single; + LFillShape, LDrawShape: Boolean; + LShadowEffect: TshadowEffect; +{$ENDIF} + +begin + + {$IFDEF ANDROID} + + //create the canvas and the paint + LPaint := TJPaint.JavaClass.init; + LPaint.setAntiAlias(true); // Enabling this flag will cause all draw operations that support antialiasing to use it. + LPaint.setFilterBitmap(True); // enable bilinear sampling on scaled bitmaps. If cleared, scaled bitmaps will be drawn with nearest neighbor sampling, likely resulting in artifacts. + LPaint.setDither(true); // Enabling this flag applies a dither to any blit operation where the target's colour space is more constrained than the source. + + //init LRect + if Stroke.Kind <> TBrushKind.None then begin + LRect := TrectF.Create( + dstRect.Left + (Stroke.Thickness / 2), + dstRect.Top + (Stroke.Thickness / 2), + dstRect.right - (Stroke.Thickness / 2), + dstRect.bottom - (Stroke.Thickness / 2)); // http://stackoverflow.com/questions/17038017/ios-draw-filled-circles + end + else LRect := dstRect; // << stupid bug https://quality.embarcadero.com/browse/RSP-16607 + + //fill the rectangle + if Fill.Kind <> TBrushKind.None then begin + + //init LPaint + LPaint.setStyle(TJPaint_Style.JavaClass.FILL); // FILL_AND_STROCK it's absolutely useless, because it's will fill on the full LRect + Stroke.Thickness :( this result&ing in border if the fill is for exemple black and border white + + //fill with gradient + if Fill.Kind = TBrushKind.Gradient then begin + if Fill.Gradient.Style = TGradientStyle.Radial then begin + LColors := TJavaArray.Create(Fill.Gradient.Points.Count); + LStops := TJavaArray.Create(Fill.Gradient.Points.Count); + for i := 0 to Fill.Gradient.Points.Count - 1 do begin + LColors[Fill.Gradient.Points.Count - 1 - i] := integer(Fill.Gradient.Points[i].Color); + LStops[Fill.Gradient.Points.Count - 1 - i] := 1 - Fill.Gradient.Points[i].Offset; + end; + LRadialShader := TJRadialGradient.JavaClass.init( + LRect.CenterPoint.x{x}, + LRect.CenterPoint.y{y}, + LRect.width / 2{radius}, + LColors, + LStops, + TJShader_TileMode.JavaClass.CLAMP{tile}); + LPaint.setShader(LRadialShader); + _drawRect(aCanvas, LPaint, LRect, false{aDrawOnlyBorder}); + LPaint.setShader(nil); + LRadialShader := nil; + ALfreeandNil(LColors); + ALfreeandNil(LStops); + end + else if Fill.Gradient.Style = TGradientStyle.Linear then begin + LColors := TJavaArray.Create(Fill.Gradient.Points.Count); + LStops := TJavaArray.Create(Fill.Gradient.Points.Count); + for i := 0 to Fill.Gradient.Points.Count - 1 do begin + LColors[i] := integer(Fill.Gradient.Points[i].Color); + LStops[i] := Fill.Gradient.Points[i].Offset; + end; + LLinearShader := TJLinearGradient.JavaClass.init( + LRect.TopLeft.x + (Fill.Gradient.StartPosition.X * LRect.Width){x0}, + LRect.TopLeft.y + (Fill.Gradient.StartPosition.Y * LRect.Height){y0}, + LRect.BottomRight.x + (Fill.Gradient.StopPosition.X * LRect.Width){x1}, + LRect.BottomRight.y + (Fill.Gradient.StopPosition.Y * LRect.Height){y1}, + LColors, + LStops, + TJShader_TileMode.JavaClass.CLAMP{tile}); + LPaint.setShader(LLinearShader); + _drawRect(aCanvas, LPaint, LRect, false{aDrawOnlyBorder}); + LPaint.setShader(nil); + LLinearShader := nil; + ALfreeandNil(LColors); + ALfreeandNil(LStops); + end; + end + + //fill with bitmap + else if Fill.Kind = TBrushKind.Bitmap then begin + if not fill.Bitmap.Bitmap.IsEmpty then begin + if fill.Bitmap.WrapMode = TWrapMode.TileStretch then begin + //----- + LTmpBitmap := TJBitmap.JavaClass.createBitmap(fill.Bitmap.Bitmap.Width, fill.Bitmap.Bitmap.height, TJBitmap_Config.JavaClass.ARGB_8888); + //----- + FillChar(LBitmapInfo, SizeOf(LBitmapInfo), 0); + if (AndroidBitmap_getInfo(TJNIResolver.GetJNIEnv, (LTmpBitmap as ILocalObject).GetObjectID, @LBitmapInfo) = 0) and + (AndroidBitmap_lockPixels(TJNIResolver.GetJNIEnv, (LTmpBitmap as ILocalObject).GetObjectID, @LPixelBuffer) = 0) then + try + if fill.Bitmap.Bitmap.Map(TMapAccess.Read, LBitmapData) then + try + ALMove(LBitmapData.Data^, LPixelBuffer^, LBitmapData.Pitch * LBitmapData.Height); + finally + fill.Bitmap.Bitmap.Unmap(LBitmapData); + end; + finally + AndroidBitmap_unlockPixels(TJNIResolver.GetJNIEnv, (LTmpBitmap as ILocalObject).GetObjectID); + end; + //----- + _drawRect(aCanvas, LPaint, LRect, false{aDrawOnlyBorder}); + LPorterDuffXfermode := TJPorterDuffXfermode.JavaClass.init(TJPorterDuff_Mode.JavaClass.SRC_IN); + LJDestRectf := TJRectf.JavaClass.init(LRect.left, LRect.top, LRect.right, LRect.bottom); + LJSrcRect := TJRect.JavaClass.init(0, 0, fill.Bitmap.Bitmap.Width, fill.Bitmap.Bitmap.height); + LPaint.setXfermode(LPorterDuffXfermode); + aCanvas.drawBitmap(LTmpBitmap, LJSrcRect, LJDestRectf, LPaint); + LPaint.setXfermode(nil); + LPorterDuffXfermode := nil; + LJSrcRect := nil; + LJDestRectf := nil; + //----- + LTmpBitmap.recycle; + LTmpBitmap := nil; + //----- + end; + end; + end + + //fill with solid color + else if Fill.Kind = TBrushKind.Solid then begin + LPaint.setColor(integer(Fill.Color)); + _drawRect(aCanvas, LPaint, LRect, false{aDrawOnlyBorder}); + end; + + end; + + //stroke the rectangle + if Stroke.Kind <> TBrushKind.None then begin + + //init LPaint + LPaint.setStyle(TJPaint_Style.JavaClass.STROKE); + LPaint.setStrokeWidth(Stroke.Thickness); + + //stroke with solid color + if Stroke.Kind = TBrushKind.Solid then begin + LPaint.setColor(integer(Stroke.Color)); + _drawRect(aCanvas, LPaint, LRect, true{aDrawOnlyBorder}); + end; + + end; + + //free the paint and the canvas + LPaint := nil; + + {$ELSEIF DEFINED(IOS)} + + //set the paint default properties + CGContextSetInterpolationQuality(aContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. http://stackoverflow.com/questions/5685884/imagequality-with-cgcontextsetinterpolationquality + //----- + CGContextSetShouldAntialias(aContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(aContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. + + //init LRect + if Stroke.Kind <> TBrushKind.None then begin + LRect := TrectF.Create( + DstRect.Left + (Stroke.Thickness / 2), + DstRect.Top + (Stroke.Thickness / 2), + DstRect.right - (Stroke.Thickness / 2), + DstRect.bottom - (Stroke.Thickness / 2)); // http://stackoverflow.com/questions/17038017/ios-draw-filled-circles + end + else LRect := DstRect; // << stupid bug https://quality.embarcadero.com/browse/RSP-16607 + + //fill the rectangle + if Fill.Kind <> TBrushKind.None then begin + + //fill with gradient + if Fill.Kind = TBrushKind.Gradient then begin + if Fill.Gradient.Style in [TGradientStyle.Radial, + TGradientStyle.Linear] then begin + CGContextSaveGState(aContext); + //----- + LCallback.version := 0; + LCallback.evaluate := @ALGradientEvaluateCallback; + LCallback.releaseInfo:= nil; + LFunc := CGFunctionCreate( + fill.Gradient, // info - A pointer to user-defined storage for data that you want to pass to your callbacks. + 1, // domainDimension - The number of inputs. + @DefaultInputRange, // domain - An array of (2*domainDimension) floats used to specify the valid intervals of input values + 4, // rangeDimension - The number of outputs. + nil, // range - An array of (2*rangeDimension) floats that specifies the valid intervals of output values + @LCallback); // callbacks - A pointer to a callback function table. + try + if Fill.Gradient.Style = TGradientStyle.Radial then begin + LShading := CGShadingCreateRadial( + aColorSpace, // colorspace + CGPoint.Create(TPointF.Create(LRect.Width / 2, aGridHeight - (LRect.height / 2))), // start - The center of the starting circle, in the shading's target coordinate space. + LRect.Width / 2, // startRadius - The radius of the starting circle, in the shading's target coordinate space. + CGPoint.Create(TPointF.Create(LRect.Width / 2, aGridHeight - (LRect.Height / 2))), // end - The center of the ending circle, in the shading's target coordinate space. + 0, // endRadius - The radius of the ending circle, in the shading's target coordinate space. + LFunc, // function + True, // extendStart - A Boolean value that specifies whether to extend the shading beyond the starting circle. + True); // extendEnd - A Boolean value that specifies whether to extend the shading beyond the ending circle. + end + else begin + LShading := CGShadingCreateAxial( + aColorSpace, // colorspace + CGPointMake( + LRect.Left + (Fill.Gradient.StartPosition.X * LRect.Width), + aGridHeight - LRect.top - (Fill.Gradient.StartPosition.Y * LRect.Height)), // start - The starting point of the axis, in the shading's target coordinate space. + CGPointMake( + LRect.Left + (Fill.Gradient.StopPosition.X * LRect.Width), + aGridHeight - LRect.top - (Fill.Gradient.StopPosition.Y * LRect.Height)), // end - The ending point of the axis, in the shading's target coordinate space. + LFunc, // function + True, // extendStart - A Boolean value that specifies whether to extend the shading beyond the starting point of the axis. + True); // extendEnd - A Boolean value that specifies whether to extend the shading beyond the ending point of the axis. + end; + try + _DrawPath(LRect, false{aDrawOnlyBorder}); + CGContextClip(aContext); // Modifies the current clipping path, using the nonzero winding number rule. + // Unlike the current path, the current clipping path is part of the graphics state. Therefore, + // to re-enlarge the paintable area by restoring the clipping path to a prior state, you must + // save the graphics state before you clip and restore the graphics state after you’ve completed + // any clipped drawing. + //----- + if (Shadow <> nil) and + (Shadow.enabled) then begin + LAlphaColor := TAlphaColorCGFloat.Create(Shadow.Color); + LColor := CGColorCreate(aColorSpace, @LAlphaColor); + try + CGContextSetShadowWithColor( + aContext, + CGSizeMake(Shadow.OffsetX, Shadow.OffsetY), // offset + Shadow.blur, // blur + LColor); // color + finally + CGColorRelease(LColor); + end; + end; + //----- + CGContextDrawShading(aContext, LShading); + //----- + if (Shadow <> nil) and + (Shadow.enabled) then begin + CGContextSetShadowWithColor( + aContext, + CGSizeMake(0, 0), // offset + 0, // blur + nil); // color + end; + //----- + finally + CGShadingRelease(LShading); + end; + finally + CGFunctionRelease(LFunc); + end; + //----- + CGContextRestoreGState(aContext); + end; + end //fill with bitmap else if Fill.Kind = TBrushKind.Bitmap then begin @@ -8356,7 +9090,7 @@ procedure ALPaintRectangle( //----- if (Shadow <> nil) and (Shadow.enabled) then begin - LAlphaColor := TAlphaColorCGFloat.Create(Shadow.ShadowColor); + LAlphaColor := TAlphaColorCGFloat.Create(Shadow.Color); LColor := CGColorCreate(aColorSpace, @LAlphaColor); try CGContextSetShadowWithColor( @@ -8413,7 +9147,7 @@ procedure ALPaintRectangle( //----- if (Shadow <> nil) and (Shadow.enabled) then begin - LAlphaColor := TAlphaColorCGFloat.Create(Shadow.ShadowColor); + LAlphaColor := TAlphaColorCGFloat.Create(Shadow.Color); LColor := CGColorCreate(aColorSpace, @LAlphaColor); try CGContextSetShadowWithColor( @@ -8456,36 +9190,307 @@ procedure ALPaintRectangle( {$ELSEIF defined(MSWINDOWS) or defined(ALMacOS)} - StrokeThicknessRestoreValue := Stroke.Thickness; + LStrokeThicknessRestoreValue := Stroke.Thickness; try - LShapeRect := ALGetDrawingShapeRectAndSetThickness(DstRect, Fill, Stroke, False, FillShape, DrawShape, StrokeThicknessRestoreValue); + + LShapeRect := ALGetDrawingShapeRectAndSetThickness(DstRect, Fill, Stroke, False, LFillShape, LDrawShape, LStrokeThicknessRestoreValue); if Sides <> AllSides then begin - Off := LShapeRect.Left; + LOff := LShapeRect.Left; if not(TSide.Top in Sides) then - LShapeRect.Top := LShapeRect.Top - Off; + LShapeRect.Top := LShapeRect.Top - LOff; if not(TSide.Left in Sides) then - LShapeRect.Left := LShapeRect.Left - Off; + LShapeRect.Left := LShapeRect.Left - LOff; if not(TSide.Bottom in Sides) then - LShapeRect.Bottom := LShapeRect.Bottom + Off; + LShapeRect.Bottom := LShapeRect.Bottom + LOff; if not(TSide.Right in Sides) then - LShapeRect.Right := LShapeRect.Right + Off; - if FillShape then + LShapeRect.Right := LShapeRect.Right + LOff; + if LFillShape then aCanvas.FillRect(LShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, Fill, TCornerType.Round{CornerType}); - if DrawShape then + if LDrawShape then aCanvas.DrawRectSides(_GetShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, Sides, Stroke, TCornerType.Round{CornerType}); end else begin - if FillShape then + if LFillShape then aCanvas.FillRect(LShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, Fill, TCornerType.Round{CornerType}); - if DrawShape then + if LDrawShape then aCanvas.DrawRect(LShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, Stroke, TCornerType.Round{CornerType}); end; + + if (Shadow <> nil) and + (Shadow.Enabled) then begin + + LShadowEffect := TshadowEffect.Create(nil); + try + LShadowEffect.ShadowColor := Shadow.Color; + LShadowEffect.distance := 0; // Specifies the distance between the shadow and the visual object to which TShadowEffect is applied. + // i m too lazy to calculate this from fShadow.offsetX / fShadow.offsetY - if someone want to do it + LShadowEffect.Direction := 0; // Specifies the direction (in degrees) of the shadow. + // i m too lazy to calculate this from fShadow.offsetX / fShadow.offsetY - if someone want to do it + LShadowEffect.Opacity := 1; // Opacity is a System.Single value that takes values in the range from 0 through 1. + // we use the opacity of the color instead + LShadowEffect.softness := Shadow.blur / 24; // Specifies the amount of blur applied to the shadow. + // Softness is a System.Single value that takes values in the range from 0 through 9. + // i calculate approximatly that 0.5 = around 12 for blur + Acanvas.Flush; + LShadowEffect.ProcessEffect(ACanvas, Acanvas.Bitmap, 1); + finally + ALFreeAndNil(LShadowEffect); + end; + + if Sides <> AllSides then + begin + if LFillShape then + aCanvas.FillRect(LShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, Fill, TCornerType.Round{CornerType}); + if LDrawShape then + aCanvas.DrawRectSides(_GetShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, Sides, Stroke, TCornerType.Round{CornerType}); + end + else + begin + if LFillShape then + aCanvas.FillRect(LShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, Fill, TCornerType.Round{CornerType}); + if LDrawShape then + aCanvas.DrawRect(LShapeRect, XRadius, YRadius, Corners, 1{AbsoluteOpacity}, Stroke, TCornerType.Round{CornerType}); + end; + + end; + + finally + Stroke.Thickness := LStrokeThicknessRestoreValue; + end; + + {$ENDIF} + +end; + +{**********************} +procedure ALPaintCircle( + {$IF defined(ANDROID)} + const aCanvas: Jcanvas; + {$ELSEIF defined(IOS)} + const aContext: CGContextRef; + const aColorSpace: CGColorSpaceRef; + const aGridHeight: Single; + {$ELSEIF defined(MSWINDOWS) or defined(ALMacOS)} + const aCanvas: Tcanvas; + {$ENDIF} + const dstRect: TrectF; + const FillColor: TAlphaColor; + const StrokeColor: TalphaColor; + const StrokeThickness: Single; + const ShadowColor: TAlphaColor; // If ShadowColor is not null, then the Canvas must have enough space to draw the shadow (approximately ShadowBlur on each side of the circle) + const shadowBlur: Single; + const shadowOffsetX: Single; + const shadowOffsetY: Single); + +{$IF defined(IOS)} +const DefaultInputRange: array[0..1] of CGFloat = (0, 1); +{$ENDIF} + +{$IF defined(ANDROID)} +var LPaint: JPaint; + LRect: TRectf; +{$ELSEIF defined(IOS)} +var LAlphaColor: TAlphaColorCGFloat; + LColor: CGColorRef; + LRect: TRectf; +{$ELSEIF defined(MSWINDOWS) or defined(ALMacOS)} +var LShapeRect: TRectF; + LFillKindRestoreValue: TBrushKind; + LFillColorRestoreValue: TAlphacolor; + LStrokeKindRestoreValue: TBrushKind; + LStrokeColorRestoreValue: TAlphacolor; + LStrokeThicknessRestoreValue: Single; + LFillShape, LDrawShape: Boolean; + LShadowEffect: TshadowEffect; +{$ENDIF} + +begin + + {$IFDEF ANDROID} + + //create the canvas and the paint + LPaint := TJPaint.JavaClass.init; + LPaint.setAntiAlias(true); // Enabling this flag will cause all draw operations that support antialiasing to use it. + LPaint.setFilterBitmap(True); // enable bilinear sampling on scaled bitmaps. If cleared, scaled bitmaps will be drawn with nearest neighbor sampling, likely resulting in artifacts. + LPaint.setDither(true); // Enabling this flag applies a dither to any blit operation where the target's colour space is more constrained than the source. + + //init LRect + if StrokeColor <> TalphaColorRec.Null then begin + LRect := TrectF.Create( + dstRect.Left + (StrokeThickness / 2), + dstRect.Top + (StrokeThickness / 2), + dstRect.right - (StrokeThickness / 2), + dstRect.bottom - (StrokeThickness / 2)); // http://stackoverflow.com/questions/17038017/ios-draw-filled-circles + end + else LRect := dstRect; // << stupid bug https://quality.embarcadero.com/browse/RSP-16607 + + //fill the circle + if FillColor <> TalphaColorRec.Null then begin + + //init LPaint + LPaint.setStyle(TJPaint_Style.JavaClass.FILL); // FILL_AND_STROCK it's absolutely useless, because it's will fill on the full LRect + StrokeThickness :( this result&ing in border if the fill is for exemple black and border white + + //fill with solid color + LPaint.setColor(integer(FillColor)); + if (ShadowColor <> TalphaColorRec.Null) then LPaint.setShadowLayer(ShadowBlur{radius}, ShadowOffsetX{dx}, ShadowOffsetY{dy}, integer(ShadowColor){shadowColor}); + aCanvas.drawCircle(LRect.CenterPoint.x{cx}, LRect.CenterPoint.y{cy}, LRect.width / 2{radius}, LPaint); + if (ShadowColor <> TalphaColorRec.Null) then LPaint.clearShadowLayer; + + end; + + //stroke the circle + if StrokeColor <> TalphaColorRec.Null then begin + + //init LPaint + LPaint.setStyle(TJPaint_Style.JavaClass.STROKE); + LPaint.setStrokeWidth(StrokeThickness); + + //stroke with solid color + LPaint.setColor(integer(StrokeColor)); + aCanvas.drawCircle(LRect.CenterPoint.x{cx}, LRect.CenterPoint.y{cy}, LRect.width / 2{radius}, LPaint); + + end; + + //free the paint and the canvas + LPaint := nil; + + {$ELSEIF DEFINED(IOS)} + + //set the paint default properties + CGContextSetInterpolationQuality(aContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. http://stackoverflow.com/questions/5685884/imagequality-with-cgcontextsetinterpolationquality + //----- + CGContextSetShouldAntialias(aContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(aContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. + + //init LRect + if StrokeColor <> TalphaColorRec.Null then begin + LRect := TrectF.Create( + DstRect.Left + (StrokeThickness / 2), + DstRect.Top + (StrokeThickness / 2), + DstRect.right - (StrokeThickness / 2), + DstRect.bottom - (StrokeThickness / 2)); // http://stackoverflow.com/questions/17038017/ios-draw-filled-circles + end + else LRect := DstRect; // << stupid bug https://quality.embarcadero.com/browse/RSP-16607 + + //fill the circle + if FillColor <> TalphaColorRec.Null then begin + + //fill with solid color + LAlphaColor := TAlphaColorCGFloat.Create(FillColor); + CGContextSetRGBFillColor(aContext, LAlphaColor.R, LAlphaColor.G, LAlphaColor.B, LAlphaColor.A); + //----- + if (ShadowColor <> TalphaColorRec.Null) then begin + LAlphaColor := TAlphaColorCGFloat.Create(ShadowColor); + LColor := CGColorCreate(aColorSpace, @LAlphaColor); + try + CGContextSetShadowWithColor( + aContext, + CGSizeMake(ShadowOffsetX, ShadowOffsetY), // offset + Shadowblur, // blur + LColor); // color + finally + CGColorRelease(LColor); + end; + end; + //----- + CGContextFillEllipseInRect( + aContext, + ALLowerLeftCGRect( + LRect.TopLeft, + LRect.Width, + LRect.Height, + aGridHeight)); + //----- + if (ShadowColor <> TalphaColorRec.Null) then begin + CGContextSetShadowWithColor( + aContext, + CGSizeMake(0, 0), // offset + 0, // blur + nil); // color + end; + + end; + + //stroke the circle + if StrokeColor <> TalphaColorRec.Null then begin + + //stroke with solid color + LAlphaColor := TAlphaColorCGFloat.Create(StrokeColor); + CGContextSetRGBStrokeColor(aContext, LAlphaColor.R, LAlphaColor.G, LAlphaColor.B, LAlphaColor.A); + CGContextSetLineWidth(aContext, StrokeThickness); + CGContextStrokeEllipseInRect( + aContext, + ALLowerLeftCGRect( + LRect.TopLeft, + LRect.Width, + LRect.Height, + aGridHeight)); + + end; + + {$ELSEIF defined(MSWINDOWS) or defined(ALMacOS)} + + LFillKindRestoreValue := ACanvas.Fill.Kind; + LFillColorRestoreValue := ACanvas.Fill.color; + LStrokeKindRestoreValue := ACanvas.Stroke.kind; + LStrokeColorRestoreValue := ACanvas.Stroke.Color; + LStrokeThicknessRestoreValue := ACanvas.Stroke.Thickness; + if FillColor <> TAlphaColorRec.Null then begin + ACanvas.Fill.Kind := TBrushKind.Solid; + ACanvas.Fill.Color := FillColor; + end + else ACanvas.Fill.Kind := TBrushKind.None; + If StrokeColor <> TalphaColorRec.Null then begin + ACanvas.Stroke.Kind := TBrushKind.Solid; + ACanvas.Stroke.Color := StrokeColor; + ACanvas.Stroke.Thickness := StrokeThickness; + end + else ACanvas.Stroke.Kind := TBrushKind.None; + try + + LShapeRect := ALGetDrawingShapeRectAndSetThickness(DstRect, ACanvas.Fill, ACanvas.Stroke, True, LFillShape, LDrawShape, LStrokeThicknessRestoreValue); + + if LFillShape then + aCanvas.FillEllipse(LShapeRect, 1{AbsoluteOpacity}, ACanvas.Fill); + if LDrawShape then + aCanvas.DrawEllipse(LShapeRect, 1{AbsoluteOpacity}, ACanvas.Stroke); + + if (ShadowColor <> TalphaColorRec.Null) then begin + + LShadowEffect := TshadowEffect.Create(nil); + try + LShadowEffect.ShadowColor := ShadowColor; + LShadowEffect.distance := 0; // Specifies the distance between the shadow and the visual object to which TShadowEffect is applied. + // i m too lazy to calculate this from fShadow.offsetX / fShadow.offsetY - if someone want to do it + LShadowEffect.Direction := 0; // Specifies the direction (in degrees) of the shadow. + // i m too lazy to calculate this from fShadow.offsetX / fShadow.offsetY - if someone want to do it + LShadowEffect.Opacity := 1; // Opacity is a System.Single value that takes values in the range from 0 through 1. + // we use the opacity of the color instead + LShadowEffect.softness := ShadowBlur / 24; // Specifies the amount of blur applied to the shadow. + // Softness is a System.Single value that takes values in the range from 0 through 9. + // i calculate approximatly that 0.5 = around 12 for blur + Acanvas.Flush; + LShadowEffect.ProcessEffect(ACanvas, Acanvas.Bitmap, 1); + finally + ALFreeAndNil(LShadowEffect); + end; + + if LFillShape then + aCanvas.FillEllipse(LShapeRect, 1{AbsoluteOpacity}, ACanvas.Fill); + if LDrawShape then + aCanvas.DrawEllipse(LShapeRect, 1{AbsoluteOpacity}, ACanvas.Stroke); + + end; + finally - if StrokeThicknessRestoreValue <> Stroke.Thickness then - Stroke.Thickness := StrokeThicknessRestoreValue; + ACanvas.Fill.Kind := LFillKindRestoreValue; + ACanvas.Fill.color := LFillColorRestoreValue; + ACanvas.Stroke.kind := LStrokeKindRestoreValue; + ACanvas.Stroke.Color := LStrokeColorRestoreValue; + ACanvas.Stroke.Thickness := LStrokeThicknessRestoreValue; end; {$ENDIF} @@ -8506,10 +9511,10 @@ procedure ALPaintCircle( const dstRect: TrectF; const Fill: TBrush; const Stroke: TStrokeBrush; - const Shadow: TALShadow = nil); // if shadow then the Canvas must contain enalf space to draw the shadow (around Shadow.blur on each side of the rectangle) + const Shadow: TALShadow); // If shadow is not nil, then the Canvas must have enough space to draw the shadow (approximately Shadow.blur on each side of the circle) {$IF defined(IOS)} -const aDefaultInputRange: array[0..1] of CGFloat = (0, 1); +const DefaultInputRange: array[0..1] of CGFloat = (0, 1); {$ENDIF} {$IF defined(ANDROID)} @@ -8539,8 +9544,9 @@ procedure ALPaintCircle( LImage: UIImage; {$ELSEIF defined(MSWINDOWS) or defined(ALMacOS)} var LShapeRect: TRectF; - StrokeThicknessRestoreValue: Single; - FillShape, DrawShape: Boolean; + LStrokeThicknessRestoreValue: Single; + LFillShape, LDrawShape: Boolean; + LShadowEffect: TshadowEffect; {$ENDIF} begin @@ -8670,8 +9676,8 @@ procedure ALPaintCircle( //set the paint default properties CGContextSetInterpolationQuality(aContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. http://stackoverflow.com/questions/5685884/imagequality-with-cgcontextsetinterpolationquality //----- - CGContextSetShouldAntialias(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetShouldAntialias(aContext, True); // Sets anti-aliasing on or off for a graphics context. + CGContextSetAllowsAntialiasing(aContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. //init LRect if Stroke.Kind <> TBrushKind.None then begin @@ -8697,7 +9703,7 @@ procedure ALPaintCircle( LFunc := CGFunctionCreate( fill.Gradient, // info - A pointer to user-defined storage for data that you want to pass to your callbacks. 1, // domainDimension - The number of inputs. - @aDefaultInputRange, // domain - An array of (2*domainDimension) floats used to specify the valid intervals of input values + @DefaultInputRange, // domain - An array of (2*domainDimension) floats used to specify the valid intervals of input values 4, // rangeDimension - The number of outputs. nil, // range - An array of (2*rangeDimension) floats that specifies the valid intervals of output values @LCallback); // callbacks - A pointer to a callback function table. @@ -8709,8 +9715,8 @@ procedure ALPaintCircle( CGPoint.Create(TPointF.Create(LRect.Width / 2, LRect.Height / 2)), // end - The center of the ending circle, in the shading's target coordinate space. 0, // endRadius - The radius of the ending circle, in the shading's target coordinate space. LFunc, // function - {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}, // extendStart - A Boolean value that specifies whether to extend the shading beyond the starting circle. - {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // extendEnd - A Boolean value that specifies whether to extend the shading beyond the ending circle. + True, // extendStart - A Boolean value that specifies whether to extend the shading beyond the starting circle. + True); // extendEnd - A Boolean value that specifies whether to extend the shading beyond the ending circle. try CGContextBeginPath(aContext); // Creates a new empty path in a graphics context. CGContextAddEllipseInRect( @@ -8729,7 +9735,7 @@ procedure ALPaintCircle( //----- if (Shadow <> nil) and (Shadow.enabled) then begin - LAlphaColor := TAlphaColorCGFloat.Create(Shadow.ShadowColor); + LAlphaColor := TAlphaColorCGFloat.Create(Shadow.Color); LColor := CGColorCreate(aColorSpace, @LAlphaColor); try CGContextSetShadowWithColor( @@ -8826,7 +9832,7 @@ procedure ALPaintCircle( //----- if (Shadow <> nil) and (Shadow.enabled) then begin - LAlphaColor := TAlphaColorCGFloat.Create(Shadow.ShadowColor); + LAlphaColor := TAlphaColorCGFloat.Create(Shadow.Color); LColor := CGColorCreate(aColorSpace, @LAlphaColor); try CGContextSetShadowWithColor( @@ -8882,7 +9888,7 @@ procedure ALPaintCircle( //----- if (Shadow <> nil) and (Shadow.enabled) then begin - LAlphaColor := TAlphaColorCGFloat.Create(Shadow.ShadowColor); + LAlphaColor := TAlphaColorCGFloat.Create(Shadow.Color); LColor := CGColorCreate(aColorSpace, @LAlphaColor); try CGContextSetShadowWithColor( @@ -8937,16 +9943,46 @@ procedure ALPaintCircle( {$ELSEIF defined(MSWINDOWS) or defined(ALMacOS)} - StrokeThicknessRestoreValue := Stroke.Thickness; + LStrokeThicknessRestoreValue := Stroke.Thickness; try - LShapeRect := ALGetDrawingShapeRectAndSetThickness(DstRect, Fill, Stroke, True, FillShape, DrawShape, StrokeThicknessRestoreValue); - if FillShape then + + LShapeRect := ALGetDrawingShapeRectAndSetThickness(DstRect, Fill, Stroke, True, LFillShape, LDrawShape, LStrokeThicknessRestoreValue); + + if LFillShape then aCanvas.FillEllipse(LShapeRect, 1{AbsoluteOpacity}, Fill); - if DrawShape then + if LDrawShape then aCanvas.DrawEllipse(LShapeRect, 1{AbsoluteOpacity}, Stroke); + + if (Shadow <> nil) and + (Shadow.Enabled) then begin + + LShadowEffect := TshadowEffect.Create(nil); + try + LShadowEffect.ShadowColor := Shadow.Color; + LShadowEffect.distance := 0; // Specifies the distance between the shadow and the visual object to which TShadowEffect is applied. + // i m too lazy to calculate this from fShadow.offsetX / fShadow.offsetY - if someone want to do it + LShadowEffect.Direction := 0; // Specifies the direction (in degrees) of the shadow. + // i m too lazy to calculate this from fShadow.offsetX / fShadow.offsetY - if someone want to do it + LShadowEffect.Opacity := 1; // Opacity is a System.Single value that takes values in the range from 0 through 1. + // we use the opacity of the color instead + LShadowEffect.softness := Shadow.blur / 24; // Specifies the amount of blur applied to the shadow. + // Softness is a System.Single value that takes values in the range from 0 through 9. + // i calculate approximatly that 0.5 = around 12 for blur + Acanvas.Flush; + LShadowEffect.ProcessEffect(ACanvas, Acanvas.Bitmap, 1); + finally + ALFreeAndNil(LShadowEffect); + end; + + if LFillShape then + aCanvas.FillEllipse(LShapeRect, 1{AbsoluteOpacity}, Fill); + if LDrawShape then + aCanvas.DrawEllipse(LShapeRect, 1{AbsoluteOpacity}, Stroke); + + end; + finally - if StrokeThicknessRestoreValue <> Stroke.Thickness then - Stroke.Thickness := StrokeThicknessRestoreValue; + Stroke.Thickness := LStrokeThicknessRestoreValue; end; {$ENDIF} @@ -9028,11 +10064,11 @@ procedure ALPaintCircle( //set the paint default properties CGContextSetInterpolationQuality(aContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. http://stackoverflow.com/questions/5685884/imagequality-with-cgcontextsetinterpolationquality //----- - CGContextSetShouldAntialias(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // default: ON + CGContextSetShouldAntialias(aContext, True); // default: ON // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetAllowsAntialiasing(aContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. //----- - //CGContextSetShouldSmoothFonts(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // There are cases, such as rendering to a bitmap, when font smoothing is not appropriate and should be disabled. + //CGContextSetShouldSmoothFonts(aContext, True); // There are cases, such as rendering to a bitmap, when font smoothing is not appropriate and should be disabled. // Note that some contexts (such as PostScript contexts) do not support font smoothing. // ----- // Enables or disables font smoothing in a graphics context. @@ -9046,9 +10082,9 @@ procedure ALPaintCircle( // it into ignoring the color in favor of perceiving a smooth edge. One disadvantage of font smoothing is // that it relies on the fixed ordering of the sub-pixels of an LCD display. That makes the technique of // limited use on other types of monitors. Font smoothing is also of limited use on offscreen bitmaps. - //CGContextSetAllowsFontSmoothing(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow font smoothing for a graphics context. + //CGContextSetAllowsFontSmoothing(aContext, True); // Sets whether or not to allow font smoothing for a graphics context. //----- - CGContextSetShouldSubpixelPositionFonts(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // default: ON + CGContextSetShouldSubpixelPositionFonts(aContext, True); // default: ON // When enabled, the graphics context may position glyphs on nonintegral pixel boundaries. When disabled, // the position of glyphs are always forced to integral pixel boundaries. // ----- @@ -9059,9 +10095,9 @@ procedure ALPaintCircle( // take pixel boundaries in account. This can improve the visual definition of // the glyphs (making them slightly less "blurry") at the expense of honoring // the font metrics. - CGContextSetAllowsFontSubpixelPositioning(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow subpixel positioning for a graphics context + CGContextSetAllowsFontSubpixelPositioning(aContext, True); // Sets whether or not to allow subpixel positioning for a graphics context //----- - CGContextSetShouldSubpixelQuantizeFonts(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // default: ON + CGContextSetShouldSubpixelQuantizeFonts(aContext, True); // default: ON // Enables or disables subpixel quantization in a graphics context. // ----- // Subpixel quantization is only enabled if subpixel positioning is enabled. Subpixel @@ -9069,7 +10105,7 @@ procedure ALPaintCircle( // by more closely examining how the shapes that make up the glyphs cover an individual pixel. // This improvement, requires additional processing so changing this value can affect text // drawing performance. - CGContextSetAllowsFontSubpixelQuantization(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow subpixel quantization for a graphics context + CGContextSetAllowsFontSubpixelQuantization(aContext, True); // Sets whether or not to allow subpixel quantization for a graphics context except CGContextRelease(aContext); @@ -9182,11 +10218,11 @@ procedure ALFreeDrawingSurface( //set the paint default properties CGContextSetInterpolationQuality(aContext, kCGInterpolationHigh); // Sets the level of interpolation quality for a graphics context. http://stackoverflow.com/questions/5685884/imagequality-with-cgcontextsetinterpolationquality //----- - CGContextSetShouldAntialias(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // default: ON + CGContextSetShouldAntialias(aContext, True); // default: ON // Sets anti-aliasing on or off for a graphics context. - CGContextSetAllowsAntialiasing(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow anti-aliasing for a graphics context. + CGContextSetAllowsAntialiasing(aContext, True); // Sets whether or not to allow anti-aliasing for a graphics context. //----- - //CGContextSetShouldSmoothFonts(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // There are cases, such as rendering to a bitmap, when font smoothing is not appropriate and should be disabled. + //CGContextSetShouldSmoothFonts(aContext, True); // There are cases, such as rendering to a bitmap, when font smoothing is not appropriate and should be disabled. // Note that some contexts (such as PostScript contexts) do not support font smoothing. // ----- // Enables or disables font smoothing in a graphics context. @@ -9200,9 +10236,9 @@ procedure ALFreeDrawingSurface( // it into ignoring the color in favor of perceiving a smooth edge. One disadvantage of font smoothing is // that it relies on the fixed ordering of the sub-pixels of an LCD display. That makes the technique of // limited use on other types of monitors. Font smoothing is also of limited use on offscreen bitmaps. - //CGContextSetAllowsFontSmoothing(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow font smoothing for a graphics context. + //CGContextSetAllowsFontSmoothing(aContext, True); // Sets whether or not to allow font smoothing for a graphics context. //----- - CGContextSetShouldSubpixelPositionFonts(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // default: ON + CGContextSetShouldSubpixelPositionFonts(aContext, True); // default: ON // When enabled, the graphics context may position glyphs on nonintegral pixel boundaries. When disabled, // the position of glyphs are always forced to integral pixel boundaries. // ----- @@ -9213,9 +10249,9 @@ procedure ALFreeDrawingSurface( // take pixel boundaries in account. This can improve the visual definition of // the glyphs (making them slightly less "blurry") at the expense of honoring // the font metrics. - CGContextSetAllowsFontSubpixelPositioning(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow subpixel positioning for a graphics context + CGContextSetAllowsFontSubpixelPositioning(aContext, True); // Sets whether or not to allow subpixel positioning for a graphics context //----- - CGContextSetShouldSubpixelQuantizeFonts(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // default: ON + CGContextSetShouldSubpixelQuantizeFonts(aContext, True); // default: ON // Enables or disables subpixel quantization in a graphics context. // ----- // Subpixel quantization is only enabled if subpixel positioning is enabled. Subpixel @@ -9223,7 +10259,7 @@ procedure ALFreeDrawingSurface( // by more closely examining how the shapes that make up the glyphs cover an individual pixel. // This improvement, requires additional processing so changing this value can affect text // drawing performance. - CGContextSetAllowsFontSubpixelQuantization(aContext, {$IF CompilerVersion >= 34}{sydney}true{$ELSE}1{$ENDIF}); // Sets whether or not to allow subpixel quantization for a graphics context + CGContextSetAllowsFontSubpixelQuantization(aContext, True); // Sets whether or not to allow subpixel quantization for a graphics context except CGContextRelease(aContext); diff --git a/Source/Alcinoe.FMX.Objects.pas b/Source/Alcinoe.FMX.Objects.pas index f39682de5..8082f14ae 100644 --- a/Source/Alcinoe.FMX.Objects.pas +++ b/Source/Alcinoe.FMX.Objects.pas @@ -187,9 +187,6 @@ TALRectangle = class(TRectangle) fBufBitmapRect: TRectF; fBufSize: TsizeF; fShadow: TALShadow; - {$IF DEFINED(MSWindows) or DEFINED(ALMacOS)} - fShadowEffect: TshadowEffect; - {$ENDIF} procedure SetdoubleBuffered(const Value: Boolean); procedure SetShadow(const Value: TALShadow); protected @@ -218,9 +215,6 @@ TALCircle = class(TCircle) fBufBitmapRect: TRectF; fBufSize: TsizeF; fShadow: TALShadow; - {$IF DEFINED(MSWindows) or DEFINED(ALMacOS)} - fShadowEffect: TshadowEffect; - {$ENDIF} procedure SetdoubleBuffered(const Value: Boolean); procedure SetShadow(const Value: TALShadow); protected @@ -884,9 +878,6 @@ constructor TALRectangle.Create(AOwner: TComponent); fBufBitmap := nil; fShadow := TalShadow.Create; fShadow.OnChanged := ShadowChanged; - {$IF DEFINED(MSWindows) or DEFINED(ALMacOS)} - fShadowEffect := nil; - {$ENDIF} end; {******************************} @@ -894,9 +885,6 @@ destructor TALRectangle.Destroy; begin clearBufBitmap; alFreeAndNil(fShadow); - {$IF DEFINED(MSWindows) or DEFINED(ALMacOS)} - AlFreeAndNil(fShadowEffect); - {$ENDIF} inherited; end; @@ -924,27 +912,6 @@ procedure TALRectangle.StrokeChanged(Sender: TObject); procedure TALRectangle.ShadowChanged(Sender: TObject); begin clearBufBitmap; - {$IF DEFINED(MSWindows) or DEFINED(ALMacOS)} - if shadow.enabled then begin - if not assigned(fShadowEffect) then begin - fShadowEffect := TshadowEffect.Create(self); - fShadowEffect.Parent := self; - fShadowEffect.SetSubComponent(true); - fShadowEffect.stored := False; - end; - fShadowEffect.ShadowColor := shadow.ShadowColor; - fShadowEffect.distance := 0; // Specifies the distance between the shadow and the visual object to which TShadowEffect is applied. - // i m too lazy to calculate this from fShadow.offsetX / fShadow.offsetY - if someone want to do it - fShadowEffect.Direction := 0; // Specifies the direction (in degrees) of the shadow. - // i m too lazy to calculate this from fShadow.offsetX / fShadow.offsetY - if someone want to do it - fShadowEffect.Opacity := 1; // Opacity is a System.Single value that takes values in the range from 0 through 1. - // we use the opacity of the color instead - fShadowEffect.softness := fShadow.blur / 24; // Specifies the amount of blur applied to the shadow. - // Softness is a System.Single value that takes values in the range from 0 through 9. - // i calculate approximatly that 0.5 = around 12 for blur - end - else AlFreeAndNil(fShadowEffect); - {$ENDIF} if FUpdating = 0 then Repaint; end; @@ -1085,6 +1052,40 @@ function TALRectangle.MakeBufBitmap: TALRasterImage; LColorSpace); // Var aColorSpace: CGColorSpaceRef; end; + {$ELSEIF defined(MSWINDOWS) or defined(ALMacOS)} + + //create the drawing surface + ALCreateDrawingSurface( + fBufBitmap, // Var aBitmap: Tbitmap; + true, // const aClearBitmap: boolean; + round(fBufBitmapRect.Width * FScreenScale), // const w: integer; + round(fBufBitmapRect.height * FScreenScale));// const h: integer) + try + + //begin the scene + if fBufBitmap.Canvas.BeginScene then + try + + ALPaintRectangle( + fBufBitmap.Canvas, // const aBitmap: Jbitmap; + LRect, // const Rect: TrectF; + Fill, // const Fill: TBrush; + Stroke, // const Stroke: TStrokeBrush; + Shadow, // const Shadow: TALShadow + Sides, // const Sides: TSides; + Corners, // const Corners: TCorners; + XRadius * fScreenScale, // const XRadius: Single = 0; + YRadius * fScreenScale); // const YRadius: Single = 0); + + finally + fBufBitmap.Canvas.EndScene; + end; + + Except + ALFreeDrawingSurface(fBufBitmap); + raise; + end; + {$ENDIF} finally @@ -1167,9 +1168,6 @@ constructor TALCircle.Create(AOwner: TComponent); fBufBitmap := nil; fShadow := TalShadow.Create; fShadow.OnChanged := ShadowChanged; - {$IF DEFINED(MSWindows) or DEFINED(ALMacOS)} - fShadowEffect := nil; - {$ENDIF} end; {***************************} @@ -1177,9 +1175,6 @@ destructor TALCircle.Destroy; begin clearBufBitmap; alFreeAndNil(fShadow); - {$IF DEFINED(MSWindows) or DEFINED(ALMacOS)} - AlFreeandNil(fShadowEffect); - {$ENDIF} inherited; end; @@ -1207,27 +1202,6 @@ procedure TALCircle.StrokeChanged(Sender: TObject); procedure TALCircle.ShadowChanged(Sender: TObject); begin clearBufBitmap; - {$IF DEFINED(MSWindows) or DEFINED(ALMacOS)} - if shadow.enabled then begin - if not assigned(fShadowEffect) then begin - fShadowEffect := TshadowEffect.Create(self); - fShadowEffect.Parent := self; - fShadowEffect.SetSubComponent(true); - fShadowEffect.stored := False; - end; - fShadowEffect.ShadowColor := shadow.ShadowColor; - fShadowEffect.distance := 0; // Specifies the distance between the shadow and the visual object to which TShadowEffect is applied. - // i m too lazy to calculate this from fShadow.offsetX / fShadow.offsetY - if someone want to do it - fShadowEffect.Direction := 0; // Specifies the direction (in degrees) of the shadow. - // i m too lazy to calculate this from fShadow.offsetX / fShadow.offsetY - if someone want to do it - fShadowEffect.Opacity := 1; // Opacity is a System.Single value that takes values in the range from 0 through 1. - // we use the opacity of the color instead - fShadowEffect.softness := fShadow.blur / 24; // Specifies the amount of blur applied to the shadow. - // Softness is a System.Single value that takes values in the range from 0 through 9. - // i calculate approximatly that 0.5 = around 12 for blur - end - else AlFreeAndNil(fShadowEffect); - {$ENDIF} if FUpdating = 0 then Repaint; end; @@ -1347,6 +1321,36 @@ function TALCircle.MakeBufBitmap: TALRasterImage; LColorSpace); // Var aColorSpace: CGColorSpaceRef; end; + {$ELSEIF defined(MSWINDOWS) or defined(ALMacOS)} + + //create the drawing surface + ALCreateDrawingSurface( + fBufBitmap, // Var aBitmap: Tbitmap; + true, // const aClearBitmap: boolean; + round(fBufBitmapRect.Width * FScreenScale), // const w: integer; + round(fBufBitmapRect.height * FScreenScale));// const h: integer) + try + + //begin the scene + if fBufBitmap.Canvas.BeginScene then + try + + ALPaintCircle( + fBufBitmap.Canvas, // const aBitmap: Jbitmap; + LRect, // const Rect: TrectF; + Fill, // const Fill: TBrush; + Stroke, // const Stroke: TStrokeBrush; + Shadow); // const Shadow: TALShadow + + finally + fBufBitmap.Canvas.EndScene; + end; + + Except + ALFreeDrawingSurface(fBufBitmap); + raise; + end; + {$ENDIF} finally diff --git a/Tools/AndroidMerger/_Build/Sample/Sample.dproj b/Tools/AndroidMerger/_Build/Sample/Sample.dproj index 04d59e32c..1eaad2ded 100644 --- a/Tools/AndroidMerger/_Build/Sample/Sample.dproj +++ b/Tools/AndroidMerger/_Build/Sample/Sample.dproj @@ -182,7 +182,7 @@ false false false - ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) + ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\osx;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) False diff --git a/Tools/DeployMan/_Build/Sample/Sample.dproj b/Tools/DeployMan/_Build/Sample/Sample.dproj index 9d8f9e203..f5fde9de3 100644 --- a/Tools/DeployMan/_Build/Sample/Sample.dproj +++ b/Tools/DeployMan/_Build/Sample/Sample.dproj @@ -182,7 +182,7 @@ false false false - ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) + ..\..\..\Source;..\..\..\Embarcadero\Alexandria\fmx;..\..\..\Embarcadero\Alexandria\rtl\ios;..\..\..\Embarcadero\Alexandria\rtl\osx;..\..\..\Embarcadero\Alexandria\rtl\android;$(DCC_UnitSearchPath) False