diff --git a/README.md b/README.md index 81d758e6..20343c54 100644 --- a/README.md +++ b/README.md @@ -103,17 +103,17 @@ V3 preview: subclassed `SkiaShaderEffect`, implementing `ISkiaGestureProcessor`, ## What's New -### Nuget 1.2.9.2 +### Nuget 1.2.9.4 for SkiaSharp 2.88.9-preview.2.2 -* Reverted SkiaSharp to 2.88.9-preview.2.2 back from 2.88.9 -until [scaling issue](https://github.com/taublast/DrawnUi.Maui/issues/130) is solved for Windows -* Antialiasing [issue](https://github.com/taublast/DrawnUi.Maui/issues/122) solved for SkiaShape -* SkiaImageManager cancelling loads fix -* Fixed native crash when using Super.ReuseBitmaps -* SkiaSvg made more GC-friendly -* Added `WithParent` to FluentExtensions -* Some more +* SkiaShape new Types: Polygon and Line. New property for their Points: Smooth (0-1) to smooth angles. +* Shapes demo page inside SandBox project. +* VisualElement Shadow property now supported everywhere as an optional addition to existing shadows. +* Removed SkiaImage clipping to better support shadows. +* SkiaLabel new property AutoFont: Find and set system font where the first glyph in text is present. Useful for some quick unicode rendering like emoji etc. +* Updated Getsures nuget for correct lock inside MAUI native ScrollView, use Getures="Lock" for Canvas. +* Fixed controls sometimes not invalidated when canvas suface size changes +* Other fixes. ## Development Notes diff --git a/dev/github_uploadnugets.bat b/dev/github_uploadnugets.bat index c7b82b83..b34e6ae1 100644 --- a/dev/github_uploadnugets.bat +++ b/dev/github_uploadnugets.bat @@ -13,8 +13,8 @@ REM Define the source directory for the packages set "source_dir=E:\Nugets" REM Define the list of file masks for the packages -set "mask[1]=DrawnUi.Maui*.1.2.9.2*.nupkg" -set "mask[2]=AppoMobi.Maui.DrawnUi.1.2.9.2*.*nupkg" +set "mask[1]=DrawnUi.Maui*.1.2.9.4*.nupkg" +set "mask[2]=AppoMobi.Maui.DrawnUi.1.2.9.4*.*nupkg" set "mask_count=2" REM Loop through each file mask diff --git a/dev/nuget_uploadnugets.bat b/dev/nuget_uploadnugets.bat index 43c915a0..f7511333 100644 --- a/dev/nuget_uploadnugets.bat +++ b/dev/nuget_uploadnugets.bat @@ -13,8 +13,8 @@ REM Define the source directory for the packages set "source_dir=E:\Nugets" REM Define the list of file masks for the packages -set "mask[1]=DrawnUi.Maui*.1.2.9.2*.nupkg" -set "mask[2]=AppoMobi.Maui.DrawnUi.1.2.9.2*.*nupkg" +set "mask[1]=DrawnUi.Maui*.1.2.9.4*.nupkg" +set "mask[2]=AppoMobi.Maui.DrawnUi.1.2.9.4*.*nupkg" set "mask_count=2" REM Loop through each file mask diff --git a/src/Addons/DrawnUi.Maui.Camera/DrawnUi.Maui.Camera.csproj b/src/Addons/DrawnUi.Maui.Camera/DrawnUi.Maui.Camera.csproj index 7430a7ef..0b2fb24c 100644 --- a/src/Addons/DrawnUi.Maui.Camera/DrawnUi.Maui.Camera.csproj +++ b/src/Addons/DrawnUi.Maui.Camera/DrawnUi.Maui.Camera.csproj @@ -44,7 +44,7 @@ - + \ No newline at end of file diff --git a/src/Addons/DrawnUi.Maui.Game/DrawnUi.Maui.Game.csproj b/src/Addons/DrawnUi.Maui.Game/DrawnUi.Maui.Game.csproj index 8ce580ea..b3f84001 100644 --- a/src/Addons/DrawnUi.Maui.Game/DrawnUi.Maui.Game.csproj +++ b/src/Addons/DrawnUi.Maui.Game/DrawnUi.Maui.Game.csproj @@ -42,7 +42,7 @@ - + diff --git a/src/Addons/DrawnUi.Maui.MapsUi/src/DrawnUi.Maui.MapsUi.csproj b/src/Addons/DrawnUi.Maui.MapsUi/src/DrawnUi.Maui.MapsUi.csproj index 06ce899e..b43dc124 100644 --- a/src/Addons/DrawnUi.Maui.MapsUi/src/DrawnUi.Maui.MapsUi.csproj +++ b/src/Addons/DrawnUi.Maui.MapsUi/src/DrawnUi.Maui.MapsUi.csproj @@ -54,7 +54,7 @@ - + diff --git a/src/Addons/DrawnUi.Maui.Rive/DrawnUi.Maui.Rive.csproj b/src/Addons/DrawnUi.Maui.Rive/DrawnUi.Maui.Rive.csproj index 272db962..6db77439 100644 --- a/src/Addons/DrawnUi.Maui.Rive/DrawnUi.Maui.Rive.csproj +++ b/src/Addons/DrawnUi.Maui.Rive/DrawnUi.Maui.Rive.csproj @@ -47,7 +47,7 @@ - + diff --git a/src/Addons/DrawnUi.MauiGraphics/DrawnUi.MauiGraphics.csproj b/src/Addons/DrawnUi.MauiGraphics/DrawnUi.MauiGraphics.csproj index 26973555..be0af46e 100644 --- a/src/Addons/DrawnUi.MauiGraphics/DrawnUi.MauiGraphics.csproj +++ b/src/Addons/DrawnUi.MauiGraphics/DrawnUi.MauiGraphics.csproj @@ -41,7 +41,7 @@ - + diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 3d6f4fde..bb1a9409 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -5,7 +5,7 @@ Using SkiaSharp 2.xx. Checkout the DrawnUi Sandbox project for usage example. - 1.2.9.2 + 1.2.9.4 diff --git a/src/Engine/Draw/Base/SkiaControl.Shared.cs b/src/Engine/Draw/Base/SkiaControl.Shared.cs index f873ec6c..34242037 100644 --- a/src/Engine/Draw/Base/SkiaControl.Shared.cs +++ b/src/Engine/Draw/Base/SkiaControl.Shared.cs @@ -4648,7 +4648,9 @@ protected virtual void ApplyTransforms(SkiaDrawingContext ctx, SKRect destinatio Helper3d.RotateYDegrees((float)RotationY); Helper3d.RotateZDegrees(-(float)RotationZ); Helper3d.TranslateZ((float)TranslationZ); + drawingMatrix = drawingMatrix.PostConcat(Helper3d.Matrix); + Helper3d.Restore(); #endif diff --git a/src/Engine/Draw/Layout/SkiaLayout.Grid.cs b/src/Engine/Draw/Layout/SkiaLayout.Grid.cs index ed611a13..9cab07f0 100644 --- a/src/Engine/Draw/Layout/SkiaLayout.Grid.cs +++ b/src/Engine/Draw/Layout/SkiaLayout.Grid.cs @@ -1,7 +1,7 @@ //Adapted code from the Xamarin.Forms Grid implementation -using DrawnUi.Maui.Infrastructure.Xaml; using System.ComponentModel; +using DrawnUi.Maui.Infrastructure.Xaml; namespace DrawnUi.Maui.Draw; @@ -12,6 +12,7 @@ public partial class SkiaLayout public virtual ScaledSize MeasureGrid(SKRect rectForChildrenPixels, float scale) { + //Trace.WriteLine($"MeasureGrid inside {rectForChildrenPixels}"); var constraints = GetSizeInPoints(rectForChildrenPixels.Size, scale); @@ -65,6 +66,7 @@ protected virtual int DrawChildrenGrid(SkiaDrawingContext context, SKRect destin List tree = new(); + var cellIndex = 0; foreach (var child in cells) { child.OptionalOnBeforeDrawing(); //could set IsVisible or whatever inside @@ -76,6 +78,8 @@ protected virtual int DrawChildrenGrid(SkiaDrawingContext context, SKRect destin var cell = GridStructure.GetCellBoundsFor(child, (destination.Left / scale), (destination.Top / scale)); + //Trace.WriteLine($"cell {cellIndex++} rect {cell}"); + //GetCellBoundsFor is in pixels SKRect cellRect = new((float)Math.Round(cell.Left * scale), (float)Math.Round(cell.Top * scale), (float)Math.Round(cell.Right * scale), (float)Math.Round(cell.Bottom * scale)); @@ -335,4 +339,4 @@ protected void UpdateRowColumnBindingContexts() #endregion -} \ No newline at end of file +} diff --git a/src/Engine/Draw/SkiaShape.cs b/src/Engine/Draw/SkiaShape.cs index 7993ddf4..4b601489 100644 --- a/src/Engine/Draw/SkiaShape.cs +++ b/src/Engine/Draw/SkiaShape.cs @@ -271,8 +271,7 @@ protected void CalculateSizeForStroke(SKRect destination, float scale) strokeAwareSize = SKRect.Inflate(strokeAwareSize, -halfStroke, -halfStroke); - strokeAwareChildrenSize = - SKRect.Inflate(strokeAwareSize, -halfStroke, -halfStroke); + strokeAwareChildrenSize = strokeAwareSize; } MeasuredStrokeAwareSize = strokeAwareSize; @@ -393,10 +392,10 @@ public override SKPath CreateClip(object arguments, bool usePosition, SKPath pat case ShapeType.Circle: ShouldClipAntialiased = true; path.AddCircle( - (float)Math.Round(strokeAwareChildrenSize.Left + strokeAwareChildrenSize.Width / 2.0f), - (float)Math.Round(strokeAwareChildrenSize.Top + strokeAwareChildrenSize.Height / 2.0f), - Math.Min(strokeAwareChildrenSize.Width, strokeAwareChildrenSize.Height) / - 2.0f); + (float)(strokeAwareChildrenSize.Left + strokeAwareChildrenSize.Width / 2.0f), + (float)(strokeAwareChildrenSize.Top + strokeAwareChildrenSize.Height / 2.0f), + (float)Math.Floor(Math.Min(strokeAwareChildrenSize.Width, strokeAwareChildrenSize.Height) / + 2.0f) + 0); break; case ShapeType.Ellipse: @@ -419,8 +418,8 @@ public override SKPath CreateClip(object arguments, bool usePosition, SKPath pat foreach (var skiaPoint in Points) { var point = new SKPoint( - (float)(offsetX + skiaPoint.X * scaleX), - (float)(offsetY + skiaPoint.Y * scaleY)); + (float)Math.Round(offsetX + skiaPoint.X * scaleX), + (float)Math.Round(offsetY + skiaPoint.Y * scaleY)); if (first) { @@ -1071,8 +1070,6 @@ public float SmoothPoints set => SetValue(SmoothPointsProperty, value); } - //OKAY! - private void AddSmoothPath(SKPath path, IList points, SKRect rect, float smoothness, bool isClosed) { if (points == null || points.Count < 2) @@ -1179,88 +1176,10 @@ private void SmoothPoint(SKPath path, IList scaledPoints, int i, float path.LineTo(p1); - // Draw the quadratic Bezier curve to smooth the angle + // quadratic Bezier curve to smooth angle path.QuadTo(current, p2); } - /* - private void AddSmoothPath(SKPath path, IList points, SKRect rect, float smoothness, bool isClosed) - { - if (points == null || points.Count < 2) - { - return; - } - - var scaledPoints = points.Select(p => ScalePoint(p, rect)).ToList(); - - // Start the path at the first point - path.MoveTo(scaledPoints[0]); - - // Iterate over each point to add smoothing - int pointCount = scaledPoints.Count; - for (int i = 0; i < pointCount; i++) - { - // Previous point (wrap around for the first point) - var prev = scaledPoints[(i - 1 + pointCount) % pointCount]; - // Current point - var current = scaledPoints[i]; - // Next point (wrap around for the last point) - var next = scaledPoints[(i + 1) % pointCount]; - - // Calculate vectors for the segments - var v1 = new SKPoint(current.X - prev.X, current.Y - prev.Y); - var v2 = new SKPoint(next.X - current.X, next.Y - current.Y); - - float lengthV1 = (float)Math.Sqrt(v1.X * v1.X + v1.Y * v1.Y); - float lengthV2 = (float)Math.Sqrt(v2.X * v2.X + v2.Y * v2.Y); - - if (lengthV1 == 0 || lengthV2 == 0) - { - // Skip if any segment length is zero - path.LineTo(current); - continue; - } - - // Normalize vectors to get direction - v1 = new SKPoint(v1.X / lengthV1, v1.Y / lengthV1); - v2 = new SKPoint(v2.X / lengthV2, v2.Y / lengthV2); - - // Calculate the radius for smoothing (controlled by smoothness) - float smoothingRadius = lengthV1 * smoothness * 0.3f; - smoothingRadius = Math.Min(smoothingRadius, lengthV1 * 0.5f); - smoothingRadius = Math.Min(smoothingRadius, lengthV2 * 0.5f); - - if (smoothingRadius < 0.001f) - { - path.LineTo(current); // No significant smoothing is needed - continue; - } - - // Determine points p1 (start of curve) and p2 (end of curve) - var p1 = new SKPoint( - current.X - v1.X * smoothingRadius, - current.Y - v1.Y * smoothingRadius); - - var p2 = new SKPoint( - current.X + v2.X * smoothingRadius, - current.Y + v2.Y * smoothingRadius); - - // Draw the line to the beginning of the rounded section - path.LineTo(p1); - - // Draw the quadratic Bezier curve to smooth the angle - path.QuadTo(current, p2); - } - - if (isClosed) - { - // Close the path properly by adding a line to the starting point to ensure consistent smoothing - path.LineTo(scaledPoints[0]); - path.Close(); - } - } - */ - private void AddStraightPath(SKPath path, IList points, SKRect rect, bool isClosed) { if (points == null || points.Count < 2) @@ -1281,55 +1200,11 @@ private void AddStraightPath(SKPath path, IList points, SKRect rect, } } - private float AngleBetween(SKPoint v1, SKPoint v2) - { - // Calculate the dot product and magnitudes of the vectors - float dotProduct = v1.X * v2.X + v1.Y * v2.Y; - float magnitudeV1 = (float)Math.Sqrt(v1.X * v1.X + v1.Y * v1.Y); - float magnitudeV2 = (float)Math.Sqrt(v2.X * v2.X + v2.Y * v2.Y); - - // Calculate cosine of the angle - float cosTheta = dotProduct / (magnitudeV1 * magnitudeV2); - // Clamp value between -1 and 1 to handle numerical precision issues - cosTheta = Math.Max(-1.0f, Math.Min(1.0f, cosTheta)); - - // Return the angle in radians - return (float)Math.Acos(cosTheta); - } - private SKPoint ScalePoint(SkiaPoint point, SKRect rect) { return new SKPoint( - (float)(rect.Left + point.X * rect.Width), - (float)(rect.Top + point.Y * rect.Height)); - } - - private SKPoint ClampPoint(SKPoint point, SKRect rect) - { - return new SKPoint( - Math.Max(rect.Left, Math.Min(rect.Right, point.X)), - Math.Max(rect.Top, Math.Min(rect.Bottom, point.Y))); - } - - private SKPoint CalculateCentroid(List points) - { - float x = 0, y = 0; - int count = points.Count; - - for (int i = 0; i < count; i++) - { - x += points[i].X; - y += points[i].Y; - } - - return new SKPoint(x / count, y / count); - } - - private SKPoint SKPointLerp(SKPoint a, SKPoint b, float t) - { - return new SKPoint( - a.X + (b.X - a.X) * t, - a.Y + (b.Y - a.Y) * t); + (float)Math.Round(rect.Left + point.X * rect.Width), + (float)Math.Round(rect.Top + point.Y * rect.Height)); } #endregion @@ -1343,10 +1218,9 @@ public static List CreateStarPoints(int numberOfPoints, double innerR List points = new List(); double angleStep = Math.PI / numberOfPoints; - double outerRadius = 1.0; // Initial outer radius + double outerRadius = 1.0; double innerRadius = outerRadius * innerRadiusRatio; - // Generate points centered at (0, 0) for (int i = 0; i < numberOfPoints * 2; i++) { double angle = i * angleStep - Math.PI / 2; @@ -1364,18 +1238,14 @@ public static List CreateStarPoints(int numberOfPoints, double innerR var minY = points.Min(p => p.Y); var maxY = points.Max(p => p.Y); - // Compute scale factors to fit into [0,1] range var scaleX = 1.0f / (maxX - minX); var scaleY = 1.0f / (maxY - minY); - // Apply uniform scaling to fill the viewport as much as possible without distortion var scale = Math.Min(scaleX, scaleY); - // Calculate offsets to center the star var offsetX = (1.0f - (maxX - minX) * scale) / 2.0f - minX * scale; var offsetY = (1.0f - (maxY - minY) * scale) / 2.0f - minY * scale; - // Scale and translate points to fit within [0.0f, 1.0f] range and center them for (int i = 0; i < points.Count; i++) { var x = points[i].X * scale + offsetX; @@ -1394,9 +1264,8 @@ public static List CreateStarPointsCrossed(int numberOfPoints) List points = new List(); double angleStep = 2 * Math.PI / numberOfPoints; - double radius = 1.0; // Initial radius + double radius = 1.0; - // Generate outer points centered at (0,0) List outerPoints = new List(); for (int i = 0; i < numberOfPoints; i++) { @@ -1406,14 +1275,12 @@ public static List CreateStarPointsCrossed(int numberOfPoints) outerPoints.Add(new SkiaPoint((float)x, (float)y)); } - // Reorder points to create a star with crossing lines int skip = (numberOfPoints - 1) / 2; for (int i = 0; i < numberOfPoints; i++) { points.Add(outerPoints[(i * skip) % numberOfPoints]); } - // Close the shape by adding the first point at the end points.Add(points[0]); // Find bounding box @@ -1422,18 +1289,14 @@ public static List CreateStarPointsCrossed(int numberOfPoints) var minY = points.Min(p => p.Y); var maxY = points.Max(p => p.Y); - // Compute scale factors to fit into [0,1] range var scaleX = 1.0f / (maxX - minX); var scaleY = 1.0f / (maxY - minY); - // Use the minimum scale to ensure the entire star fits within the viewport var scale = Math.Min(scaleX, scaleY); - // Calculate offsets to center the star var offsetX = (1.0f - (maxX - minX) * scale) / 2.0f - minX * scale; var offsetY = (1.0f - (maxY - minY) * scale) / 2.0f - minY * scale; - // Scale and translate points to fit within [0.0f, 1.0f] range and center them for (int i = 0; i < points.Count; i++) { var x = points[i].X * scale + offsetX; diff --git a/src/Engine/Draw/Text/SkiaLabel.cs b/src/Engine/Draw/Text/SkiaLabel.cs index 2ad1dee5..16642254 100644 --- a/src/Engine/Draw/Text/SkiaLabel.cs +++ b/src/Engine/Draw/Text/SkiaLabel.cs @@ -313,9 +313,6 @@ public void MergeSpansForLines( public List Glyphs { get; protected set; } = new(); - //todo - bool AutoFindFont = false; - public override ScaledSize Measure(float widthConstraint, float heightConstraint, float scale) { if (IsDisposed || IsDisposing) @@ -369,20 +366,25 @@ public override ScaledSize Measure(float widthConstraint, float heightConstraint Glyphs = GetGlyphs(Text, PaintDefault.Typeface); - if (AutoFindFont) + if (AutoFont) { if (Glyphs != null && Glyphs.Count > 0) { - if (UnicodeNeedsShaping(Glyphs[0].Symbol)) + var first = Glyphs[0].Symbol; + var typeFace = SkiaFontManager.Manager.MatchCharacter(first); + if (typeFace != null) { - needsShaping = true; + //FontDetectedWith = glyph.Symbol; + needsShaping = SkiaLabel.UnicodeNeedsShaping(first); + _replaceFont = typeFace; + ReplaceFont(); } } text = Text; } else { - //replace unprintable symbols + //replace unprintable symbols with fallback if (Glyphs.Count > 0) { var textFiltered = ""; @@ -1438,6 +1440,8 @@ protected virtual void UpdateFont() } + + protected void ReplaceFont() { var newFont = _replaceFont; @@ -2676,6 +2680,21 @@ public int FontWeight set { SetValue(FontWeightProperty, value); } } + public static readonly BindableProperty AutoFontProperty = BindableProperty.Create( + nameof(AutoFont), + typeof(bool), + typeof(SkiaLabel), + false, propertyChanged: NeedUpdateFont); + + /// + /// Find and set system font where the first glyph in text is present + /// + public bool AutoFont + { + get { return (bool)GetValue(AutoFontProperty); } + set { SetValue(AutoFontProperty, value); } + } + public static readonly BindableProperty TypeFaceProperty = BindableProperty.Create( nameof(TypeFace), typeof(SKTypeface), diff --git a/src/Engine/DrawnUi.Maui.csproj b/src/Engine/DrawnUi.Maui.csproj index 2c047ef7..c503e4ba 100644 --- a/src/Engine/DrawnUi.Maui.csproj +++ b/src/Engine/DrawnUi.Maui.csproj @@ -9,7 +9,6 @@ true - 14.2 14.0 21.0 @@ -62,6 +61,7 @@ + @@ -92,11 +92,12 @@ + - + @@ -104,38 +105,39 @@ - - + - + + + + + + + - - + @@ -163,8 +165,6 @@ - - - + diff --git a/src/Engine/Features/Gestures/GesturesMode.cs b/src/Engine/Features/Gestures/GesturesMode.cs index bda7b733..9ec77da0 100644 --- a/src/Engine/Features/Gestures/GesturesMode.cs +++ b/src/Engine/Features/Gestures/GesturesMode.cs @@ -19,9 +19,4 @@ public enum GesturesMode /// Lock input for self, useful inside scroll view, panning controls like slider etc /// Lock, - - /// - /// Tries to let other views consume the touch event if this view doesn't handle it - /// - Share, -} \ No newline at end of file +} diff --git a/src/Engine/Views/Canvas.cs b/src/Engine/Views/Canvas.cs index 4de3da69..24fd1da2 100644 --- a/src/Engine/Views/Canvas.cs +++ b/src/Engine/Views/Canvas.cs @@ -366,9 +366,9 @@ protected virtual void OnGesturesAttachChanged() else if (this.Gestures == GesturesMode.Lock) TouchEffect.SetShareTouch(this, TouchHandlingStyle.Lock); - else - if (this.Gestures == GesturesMode.Share) - TouchEffect.SetShareTouch(this, TouchHandlingStyle.Share); + //else + //if (this.Gestures == GesturesMode.Share) + // TouchEffect.SetShareTouch(this, TouchHandlingStyle.Share); } } @@ -379,14 +379,21 @@ protected virtual void OnGesturesAttachChanged() bool _isPanning; - protected SkiaSvg DebugPointer = new() + + protected virtual SkiaSvg CreateDebugPointer() { - HeightRequest = 32, - UseCache = SkiaCacheType.Operations, - LockRatio = 1, - //https://freesvg.org/hand-pointer - SvgString = "\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n image/svg+xml\n \n \n \n \n Openclipart\n \n \n pointer\n 2011-01-04T07:30:40\n \n https://openclipart.org/detail/103567/pointer-by-3dline\n \n \n 3Dline\n \n \n \n \n Graphical\n Hand\n Icon\n colored\n point\n \n \n \n \n \n \n \n \n \n \n" - }; + return new() + { + HeightRequest = 32, + UseCache = SkiaCacheType.Operations, + LockRatio = 1, + //https://freesvg.org/hand-pointer + SvgString = + "\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n image/svg+xml\n \n \n \n \n Openclipart\n \n \n pointer\n 2011-01-04T07:30:40\n \n https://openclipart.org/detail/103567/pointer-by-3dline\n \n \n 3Dline\n \n \n \n \n Graphical\n Hand\n Icon\n colored\n point\n \n \n \n \n \n \n \n \n \n \n" + }; + } + + protected SkiaSvg DebugPointer { get; set; } public override void OnDisposing() { @@ -484,7 +491,7 @@ protected virtual void ProcessGestures(SkiaGesturesParameters args) /// public virtual void OnGestureEvent(TouchActionType type, TouchActionEventArgs args1, TouchActionResult touchAction) { - Super.Log($"[Touch] Canvas got {args1.Type} {type} => {touchAction}"); + //Super.Log($"[Touch] Canvas got {args1.Type} {type} => {touchAction}"); #if ANDROID if (touchAction == TouchActionResult.Panning) @@ -526,21 +533,16 @@ public virtual void OnGestureEvent(TouchActionType type, TouchActionEventArgs ar #endif - //lock fix: - if (this.Gestures == GesturesMode.Lock) - { - if (touchAction == TouchActionResult.Up - && (args1.Type == TouchActionType.Moved && type == TouchActionType.Cancelled)) - { - return; - //touchAction = TouchActionResult.Panning; - } - } - var args = SkiaGesturesParameters.Create(touchAction, args1); if (GesturesDebugColor.Alpha > 0) { + + if (DebugPointer == null) + { + DebugPointer = CreateDebugPointer(); + } + if (args.Type == TouchActionResult.Down) { _debugIsPressed = true; @@ -565,9 +567,6 @@ public virtual void OnGestureEvent(TouchActionType type, TouchActionEventArgs ar } - ProcessGestures(args); - return; - //this is intended to not lose gestures when fps drops and avoid crashes in double-buffering PostponeExecutionBeforeDraw(() => { diff --git a/src/Engine/Views/DrawnView.cs b/src/Engine/Views/DrawnView.cs index f3b5cf7e..1284f019 100644 --- a/src/Engine/Views/DrawnView.cs +++ b/src/Engine/Views/DrawnView.cs @@ -1327,11 +1327,19 @@ SkiaDrawingContext CreateContext(SKSurface surface) /// public event EventHandler WillFirstTimeDraw; + protected SKRect LastDrawnRect; + private bool OnDrawSurface(SKSurface surface, SKRect rect) { lock (LockDraw) { + if (LastDrawnRect.Size != rect.Size) + { + LastDrawnRect = rect; + NeedMeasure = true; + } + if (!OnStartRendering(surface.Canvas)) return UpdateMode == UpdateMode.Constant; @@ -1747,6 +1755,10 @@ protected virtual void Draw(SkiaDrawingContext context, SKRect destination, floa destination.Top + (float)Math.Round((Padding.Top) * scale), destination.Right - (float)Math.Round((Padding.Right) * scale), destination.Bottom - (float)Math.Round((Padding.Bottom) * scale)); + if (NeedMeasure) + { + child.NeedMeasure = true; + } child.Render(context, rectForChild, (float)scale); } } diff --git a/src/samples/Sandbox/AppShell.xaml b/src/samples/Sandbox/AppShell.xaml index 3227a5b1..3c003f81 100644 --- a/src/samples/Sandbox/AppShell.xaml +++ b/src/samples/Sandbox/AppShell.xaml @@ -11,7 +11,7 @@ diff --git a/src/samples/Sandbox/MainPageShapes.xaml b/src/samples/Sandbox/MainPageShapes.xaml deleted file mode 100644 index 8995e07d..00000000 --- a/src/samples/Sandbox/MainPageShapes.xaml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/samples/Sandbox/MainPageTestImage.cs b/src/samples/Sandbox/MainPageTestImage.cs new file mode 100644 index 00000000..4e95c605 --- /dev/null +++ b/src/samples/Sandbox/MainPageTestImage.cs @@ -0,0 +1,98 @@ +using Sandbox.Views; +using Canvas = DrawnUi.Maui.Views.Canvas; + +namespace Sandbox +{ + + + public class MainPageTestImage : BasePage, IDisposable + { + Canvas Canvas; + + public void Dispose() + { + this.Content = null; + Canvas?.Dispose(); + } + + + public MainPageTestImage() + { +#if DEBUG + HotReloadService.UpdateApplicationEvent += ReloadUI; +#endif + Build(); + } + + private int _reloads; + + void Build() + { + Canvas?.Dispose(); + + Canvas = new Canvas() + { + Gestures = GesturesMode.Enabled, + HardwareAcceleration = HardwareAccelerationMode.Disabled, + + VerticalOptions = LayoutOptions.Fill, + HorizontalOptions = LayoutOptions.Fill, + BackgroundColor = Colors.LightGray, + + Content = new SkiaLayout() + { + VerticalOptions = LayoutOptions.Fill, + HorizontalOptions = LayoutOptions.Fill, + Children = new List() + { + new SkiaLayout() + { + Children = new List() + { + new SkiaShape() + { + VerticalOptions = LayoutOptions.Center, + HorizontalOptions = LayoutOptions.Center, + WidthRequest = 150, + HeightRequest = 150, + Type = ShapeType.Polygon, + StrokeColor = Colors.Black, + StrokeWidth = 3, + BackgroundColor = Colors.Red, + Points = new List() + { + new (0.1f, 0.1f), + new (0.9f, 0.1f), + new (0.1f, 0.5f), + }, + Content = new SkiaImage() + { + Source = "cap.png", + Aspect = TransformAspect.AspectFit, + VerticalOptions = LayoutOptions.Center, + HorizontalOptions = LayoutOptions.Center + } + } + } + } + } + } + + + }; + + _reloads++; + + this.Content = Canvas; + } + + private void ReloadUI(Type[] obj) + { + MainThread.BeginInvokeOnMainThread(() => + { + Build(); + }); + } + + } +} diff --git a/src/samples/Sandbox/MauiProgram.cs b/src/samples/Sandbox/MauiProgram.cs index cc9fbacb..9ab9c4f2 100644 --- a/src/samples/Sandbox/MauiProgram.cs +++ b/src/samples/Sandbox/MauiProgram.cs @@ -12,6 +12,14 @@ public static class MauiProgram public static string Testing = "1\r\n2\r\n3"; + public static List PolygonStar + { + get + { + return SkiaShape.CreateStarPoints(5); + } + } + public static MauiApp CreateMauiApp() { //SkiaImageManager.CacheLongevitySecs = 10; diff --git a/src/samples/Sandbox/Sandbox.csproj b/src/samples/Sandbox/Sandbox.csproj index 0094c5b9..e936bd60 100644 --- a/src/samples/Sandbox/Sandbox.csproj +++ b/src/samples/Sandbox/Sandbox.csproj @@ -213,7 +213,7 @@ - + MainPageShapes.xaml @@ -370,7 +370,7 @@ - + MSBuild:Compile diff --git a/src/samples/Sandbox/TestPage.xaml b/src/samples/Sandbox/TestPage.xaml index 7d7f5033..825cfeb4 100644 --- a/src/samples/Sandbox/TestPage.xaml +++ b/src/samples/Sandbox/TestPage.xaml @@ -27,9 +27,8 @@ HorizontalOptions="Fill" Tag="Wrapper" VerticalOptions="Fill"> - + + UseCache="None" + VerticalOptions="Center"> - + diff --git a/src/samples/Sandbox/TestPage2.xaml b/src/samples/Sandbox/TestPage2.xaml index 6bc5f36d..b43cb54f 100644 --- a/src/samples/Sandbox/TestPage2.xaml +++ b/src/samples/Sandbox/TestPage2.xaml @@ -16,69 +16,68 @@ - - - - - - - - - - - - White - Yellow - Orange - Red - DarkRed - - - - - - - - + HorizontalOptions="Fill"> - + + + + + + + + + + + White + Yellow + Orange + Red + DarkRed + + + + + - - - - - + + + + + + + + + + diff --git a/src/samples/Sandbox/Views/MainPageShapes.xaml b/src/samples/Sandbox/Views/MainPageShapes.xaml new file mode 100644 index 00000000..d02bdd2a --- /dev/null +++ b/src/samples/Sandbox/Views/MainPageShapes.xaml @@ -0,0 +1,266 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #777777 + Gray + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pin + + + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/samples/Sandbox/MainPageShapes.xaml.cs b/src/samples/Sandbox/Views/MainPageShapes.xaml.cs similarity index 100% rename from src/samples/Sandbox/MainPageShapes.xaml.cs rename to src/samples/Sandbox/Views/MainPageShapes.xaml.cs