public static SKMatrix Scale(this SKMatrix m, float sx, float sy) { return(m.Concat(SKMatrix.MakeScale(sx, sy))); }
public override void Resize(string sourceFile, string destinationFile, ImageAsset asset, OutputConfig outputConfig) { int sourceNominalWidth = asset.Width; int sourceNominalHeight = asset.Height; double resizeRatio = outputConfig.Ratio; var fillColor = asset.FillColor; if (string.IsNullOrEmpty(fillColor)) { fillColor = outputConfig.FillColor; } // For SVG's we can optionally change the fill color on all paths if (!string.IsNullOrEmpty(fillColor)) { var svgText = File.ReadAllText(sourceFile); foreach (var rxPattern in rxFillPatterns) { var matches = Regex.Matches(svgText, rxPattern); foreach (Match match in matches) { var fillGroup = match.Groups?["fill"]; if (fillGroup != null) { // Replace the matched rx group with our override fill color var a = svgText.Substring(0, fillGroup.Index); var b = svgText.Substring(fillGroup.Index + fillGroup.Length); svgText = a + outputConfig.FillColor.TrimEnd(';') + ";" + b; } } } // Write our changes out to a temp file so we don't alter the original var tempFile = Path.GetTempFileName(); File.WriteAllText(tempFile, svgText); sourceFile = tempFile; } var svg = new SKSvg(); svg.Load(sourceFile); // Find the actual size of the SVG var sourceActualWidth = svg.Picture.CullRect.Width; var sourceActualHeight = svg.Picture.CullRect.Height; // Figure out what the ratio to convert the actual image size to the nominal size is var nominalRatio = Math.Max((double)sourceNominalWidth / (double)sourceActualWidth, (double)sourceNominalHeight / (double)sourceActualHeight); // Multiply nominal ratio by the resize ratio to get our final ratio we actually adjust by var adjustRatio = nominalRatio * resizeRatio; // Figure out our scaled width and height to make a new canvas for var scaledWidth = sourceActualWidth * adjustRatio; var scaledHeight = sourceActualHeight * adjustRatio; // Make a canvas of the target size to draw the svg onto var bmp = new SKBitmap((int)scaledWidth, (int)scaledHeight); var canvas = new SKCanvas(bmp); // Make a matrix to scale the SVG var matrix = SKMatrix.MakeScale((float)adjustRatio, (float)adjustRatio); canvas.Clear(SKColors.Transparent); // Draw the svg onto the canvas with our scaled matrix canvas.DrawPicture(svg.Picture, ref matrix); // Save the op canvas.Save(); // Export the canvas var img = SKImage.FromBitmap(bmp); var data = img.Encode(SKImageEncodeFormat.Png, 100); using (var fs = File.Open(destinationFile, FileMode.Create)) { data.SaveTo(fs); } }
private SKMatrix ReadTransform(string raw) { var t = SKMatrix.MakeIdentity(); if (string.IsNullOrWhiteSpace(raw)) { return(t); } var calls = raw.Trim().Split(new[] { ')' }, StringSplitOptions.RemoveEmptyEntries); foreach (var c in calls) { var args = c.Split(new[] { '(', ',', ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); var nt = SKMatrix.MakeIdentity(); switch (args[0]) { case "matrix": if (args.Length == 7) { nt.Values = new float[] { ReadNumber(args[1]), ReadNumber(args[3]), ReadNumber(args[5]), ReadNumber(args[2]), ReadNumber(args[4]), ReadNumber(args[6]), 0, 0, 1 }; } else { LogOrThrow($"Matrices are expected to have 6 elements, this one has {args.Length - 1}"); } break; case "translate": if (args.Length >= 3) { nt = SKMatrix.MakeTranslation(ReadNumber(args[1]), ReadNumber(args[2])); } else if (args.Length >= 2) { nt = SKMatrix.MakeTranslation(ReadNumber(args[1]), 0); } break; case "scale": if (args.Length >= 3) { nt = SKMatrix.MakeScale(ReadNumber(args[1]), ReadNumber(args[2])); } else if (args.Length >= 2) { var sx = ReadNumber(args[1]); nt = SKMatrix.MakeScale(sx, sx); } break; case "rotate": var a = ReadNumber(args[1]); if (args.Length >= 4) { var x = ReadNumber(args[2]); var y = ReadNumber(args[3]); var t1 = SKMatrix.MakeTranslation(x, y); var t2 = SKMatrix.MakeRotationDegrees(a); var t3 = SKMatrix.MakeTranslation(-x, -y); SKMatrix.Concat(ref nt, ref t1, ref t2); SKMatrix.Concat(ref nt, ref nt, ref t3); } else { nt = SKMatrix.MakeRotationDegrees(a); } break; default: LogOrThrow($"Can't transform {args[0]}"); break; } SKMatrix.Concat(ref t, ref t, ref nt); } return(t); }
public static SKMatrix ToSKMatrix(this SvgTransformCollection svgTransformCollection) { var skMatrixTotal = SKMatrix.MakeIdentity(); if (svgTransformCollection == null) { return(skMatrixTotal); } foreach (var svgTransform in svgTransformCollection) { switch (svgTransform) { case SvgMatrix svgMatrix: { var skMatrix = svgMatrix.ToSKMatrix(); SKMatrix.PreConcat(ref skMatrixTotal, ref skMatrix); } break; case SvgRotate svgRotate: { var skMatrixRotate = SKMatrix.MakeRotationDegrees(svgRotate.Angle, svgRotate.CenterX, svgRotate.CenterY); SKMatrix.PreConcat(ref skMatrixTotal, ref skMatrixRotate); } break; case SvgScale svgScale: { var skMatrixScale = SKMatrix.MakeScale(svgScale.X, svgScale.Y); SKMatrix.PreConcat(ref skMatrixTotal, ref skMatrixScale); } break; case SvgShear svgShear: { // Not in the svg specification. } break; case SvgSkew svgSkew: { float sx = (float)Math.Tan(Math.PI * svgSkew.AngleX / 180); float sy = (float)Math.Tan(Math.PI * svgSkew.AngleY / 180); var skMatrixSkew = SKMatrix.MakeSkew(sx, sy); SKMatrix.PreConcat(ref skMatrixTotal, ref skMatrixSkew); } break; case SvgTranslate svgTranslate: { var skMatrixTranslate = SKMatrix.MakeTranslation(svgTranslate.X, svgTranslate.Y); SKMatrix.PreConcat(ref skMatrixTotal, ref skMatrixTranslate); } break; default: break; } } return(skMatrixTotal); }
public ImageDrawable(SvgImage svgImage, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes = Attributes.None) : base(svgImage, root, parent) { IgnoreAttributes = ignoreAttributes; IsDrawable = CanDraw(svgImage, IgnoreAttributes) && HasFeatures(svgImage, IgnoreAttributes); if (!IsDrawable) { return; } float width = svgImage.Width.ToDeviceValue(UnitRenderingType.Horizontal, svgImage, skOwnerBounds); float height = svgImage.Height.ToDeviceValue(UnitRenderingType.Vertical, svgImage, skOwnerBounds); float x = svgImage.Location.X.ToDeviceValue(UnitRenderingType.Horizontal, svgImage, skOwnerBounds); float y = svgImage.Location.Y.ToDeviceValue(UnitRenderingType.Vertical, svgImage, skOwnerBounds); var location = new SKPoint(x, y); if (width <= 0f || height <= 0f || svgImage.Href == null) { IsDrawable = false; return; } // TODO: Check for image recursive references. //if (SkiaUtil.HasRecursiveReference(svgImage, (e) => e.Href)) //{ // _canDraw = false; // return; //} var image = SvgImageExtensions.GetImage(svgImage.Href, svgImage.OwnerDocument); var skImage = image as SKImage; var svgFragment = image as SvgFragment; if (skImage == null && svgFragment == null) { IsDrawable = false; return; } if (skImage != null) { _disposable.Add(skImage); } SrcRect = default; if (skImage != null) { SrcRect = SKRect.Create(0f, 0f, skImage.Width, skImage.Height); } if (svgFragment != null) { var skSize = SvgExtensions.GetDimensions(svgFragment); SrcRect = SKRect.Create(0f, 0f, skSize.Width, skSize.Height); } var destClip = SKRect.Create(location.X, location.Y, width, height); var aspectRatio = svgImage.AspectRatio; if (aspectRatio.Align != SvgPreserveAspectRatio.none) { var fScaleX = destClip.Width / SrcRect.Width; var fScaleY = destClip.Height / SrcRect.Height; var xOffset = 0f; var yOffset = 0f; if (aspectRatio.Slice) { fScaleX = Math.Max(fScaleX, fScaleY); fScaleY = Math.Max(fScaleX, fScaleY); } else { fScaleX = Math.Min(fScaleX, fScaleY); fScaleY = Math.Min(fScaleX, fScaleY); } switch (aspectRatio.Align) { case SvgPreserveAspectRatio.xMinYMin: break; case SvgPreserveAspectRatio.xMidYMin: xOffset = (destClip.Width - SrcRect.Width * fScaleX) / 2; break; case SvgPreserveAspectRatio.xMaxYMin: xOffset = (destClip.Width - SrcRect.Width * fScaleX); break; case SvgPreserveAspectRatio.xMinYMid: yOffset = (destClip.Height - SrcRect.Height * fScaleY) / 2; break; case SvgPreserveAspectRatio.xMidYMid: xOffset = (destClip.Width - SrcRect.Width * fScaleX) / 2; yOffset = (destClip.Height - SrcRect.Height * fScaleY) / 2; break; case SvgPreserveAspectRatio.xMaxYMid: xOffset = (destClip.Width - SrcRect.Width * fScaleX); yOffset = (destClip.Height - SrcRect.Height * fScaleY) / 2; break; case SvgPreserveAspectRatio.xMinYMax: yOffset = (destClip.Height - SrcRect.Height * fScaleY); break; case SvgPreserveAspectRatio.xMidYMax: xOffset = (destClip.Width - SrcRect.Width * fScaleX) / 2; yOffset = (destClip.Height - SrcRect.Height * fScaleY); break; case SvgPreserveAspectRatio.xMaxYMax: xOffset = (destClip.Width - SrcRect.Width * fScaleX); yOffset = (destClip.Height - SrcRect.Height * fScaleY); break; } DestRect = SKRect.Create( destClip.Left + xOffset, destClip.Top + yOffset, SrcRect.Width * fScaleX, SrcRect.Height * fScaleY); } else { DestRect = destClip; } Clip = destClip; var skClipRect = SvgClippingExtensions.GetClipRect(svgImage, destClip); if (skClipRect != null) { Clip = skClipRect; } if (skImage != null) { Image = skImage; } if (svgFragment != null) { FragmentDrawable = new FragmentDrawable(svgFragment, skOwnerBounds, root, this, ignoreAttributes); _disposable.Add(FragmentDrawable); } IsAntialias = SvgPaintingExtensions.IsAntialias(svgImage); if (Image != null) { TransformedBounds = DestRect; } if (FragmentDrawable != null) { //_skBounds = _fragmentDrawable._skBounds; TransformedBounds = DestRect; } Transform = SvgTransformsExtensions.ToSKMatrix(svgImage.Transforms); FragmentTransform = SKMatrix.MakeIdentity(); if (FragmentDrawable != null) { float dx = DestRect.Left; float dy = DestRect.Top; float sx = DestRect.Width / SrcRect.Width; float sy = DestRect.Height / SrcRect.Height; var skTranslationMatrix = SKMatrix.MakeTranslation(dx, dy); var skScaleMatrix = SKMatrix.MakeScale(sx, sy); FragmentTransform = FragmentTransform.PreConcat(skTranslationMatrix); FragmentTransform = FragmentTransform.PreConcat(skScaleMatrix); } Fill = null; Stroke = null; // TODO: Transform _skBounds using _skMatrix. TransformedBounds = Transform.MapRect(TransformedBounds); }
public void DrawImage(SvgImage svgImage, bool ignoreDisplay) { if (!CanDraw(svgImage, ignoreDisplay)) { return; } float width = svgImage.Width.ToDeviceValue(null, UnitRenderingType.Horizontal, svgImage); float height = svgImage.Height.ToDeviceValue(null, UnitRenderingType.Vertical, svgImage); var location = svgImage.Location.ToDeviceValue(null, svgImage); if (width <= 0f || height <= 0f || svgImage.Href == null) { return; } var image = SkiaUtil.GetImage(svgImage, svgImage.Href); var skImage = image as SKImage; var svgFragment = image as SvgFragment; if (skImage == null && svgFragment == null) { return; } if (skImage != null) { _disposable.Add(skImage); } SKRect srcRect = default; if (skImage != null) { srcRect = SKRect.Create(0f, 0f, skImage.Width, skImage.Height); } if (svgFragment != null) { var skSize = SkiaUtil.GetDimensions(svgFragment); srcRect = SKRect.Create(0f, 0f, skSize.Width, skSize.Height); } var destClip = SKRect.Create(location.X, location.Y, width, height); var destRect = destClip; var aspectRatio = svgImage.AspectRatio; if (aspectRatio.Align != SvgPreserveAspectRatio.none) { var fScaleX = destClip.Width / srcRect.Width; var fScaleY = destClip.Height / srcRect.Height; var xOffset = 0f; var yOffset = 0f; if (aspectRatio.Slice) { fScaleX = Math.Max(fScaleX, fScaleY); fScaleY = Math.Max(fScaleX, fScaleY); } else { fScaleX = Math.Min(fScaleX, fScaleY); fScaleY = Math.Min(fScaleX, fScaleY); } switch (aspectRatio.Align) { case SvgPreserveAspectRatio.xMinYMin: break; case SvgPreserveAspectRatio.xMidYMin: xOffset = (destClip.Width - srcRect.Width * fScaleX) / 2; break; case SvgPreserveAspectRatio.xMaxYMin: xOffset = (destClip.Width - srcRect.Width * fScaleX); break; case SvgPreserveAspectRatio.xMinYMid: yOffset = (destClip.Height - srcRect.Height * fScaleY) / 2; break; case SvgPreserveAspectRatio.xMidYMid: xOffset = (destClip.Width - srcRect.Width * fScaleX) / 2; yOffset = (destClip.Height - srcRect.Height * fScaleY) / 2; break; case SvgPreserveAspectRatio.xMaxYMid: xOffset = (destClip.Width - srcRect.Width * fScaleX); yOffset = (destClip.Height - srcRect.Height * fScaleY) / 2; break; case SvgPreserveAspectRatio.xMinYMax: yOffset = (destClip.Height - srcRect.Height * fScaleY); break; case SvgPreserveAspectRatio.xMidYMax: xOffset = (destClip.Width - srcRect.Width * fScaleX) / 2; yOffset = (destClip.Height - srcRect.Height * fScaleY); break; case SvgPreserveAspectRatio.xMaxYMax: xOffset = (destClip.Width - srcRect.Width * fScaleX); yOffset = (destClip.Height - srcRect.Height * fScaleY); break; } destRect = SKRect.Create( destClip.Left + xOffset, destClip.Top + yOffset, srcRect.Width * fScaleX, srcRect.Height * fScaleY); } _skCanvas.Save(); var skMatrix = SkiaUtil.GetSKMatrix(svgImage.Transforms); SetTransform(skMatrix); SetClipPath(svgImage, _disposable); var skPaintOpacity = SetOpacity(svgImage, _disposable); var skPaintFilter = SetFilter(svgImage, _disposable); _skCanvas.ClipRect(destClip, SKClipOperation.Intersect); SetClip(svgImage, destClip); if (skImage != null) { _skCanvas.DrawImage(skImage, srcRect, destRect); } if (svgFragment != null) { _skCanvas.Save(); float dx = destRect.Left; float dy = destRect.Top; float sx = destRect.Width / srcRect.Width; float sy = destRect.Height / srcRect.Height; var skTranslationMatrix = SKMatrix.MakeTranslation(dx, dy); var skScaleMatrix = SKMatrix.MakeScale(sx, sy); SKMatrix.PreConcat(ref skTranslationMatrix, ref skScaleMatrix); SetTransform(skTranslationMatrix); DrawFragment(svgFragment, ignoreDisplay); _skCanvas.Restore(); } if (skPaintFilter != null) { _skCanvas.Restore(); } if (skPaintOpacity != null) { _skCanvas.Restore(); } _skCanvas.Restore(); }
private static void ExtractImageFromStream(string url, Size desiredSize, Stream inputStream, Stream imageStream) { if (IsSvg(url)) { using (var svg = new SKSvg()) { try { svg.Load(inputStream); } catch (Exception exception) { Logger.Warning(exception, $"Something is wrong with: \"{url}\"."); } var skPicture = svg.Picture; var imageInfo = new SKImageInfo((int)desiredSize.Width, (int)desiredSize.Height); using (var surface = SKSurface.Create(imageInfo)) { using (var canvas = surface.Canvas) { // calculate the scaling need to fit to desired size var scaleX = desiredSize.Width / skPicture.CullRect.Width; var scaleY = desiredSize.Height / skPicture.CullRect.Height; var matrix = SKMatrix.MakeScale((float)scaleX, (float)scaleY); // draw the svg canvas.Clear(SKColors.Transparent); canvas.DrawPicture(skPicture, ref matrix); canvas.Flush(); using (var data = surface.Snapshot()) { using (var pngImage = data.Encode(SKEncodedImageFormat.Png, 100)) { pngImage.SaveTo(imageStream); } } } } } } else { var bitmap = SKBitmap.Decode(inputStream); if (bitmap != null) { var resizeInfo = GetResizeSkImageInfo(desiredSize, bitmap); using (var resizedBitmap = bitmap.Resize(resizeInfo, SKFilterQuality.High)) { bitmap.Dispose(); using (var image = SKImage.FromBitmap(resizedBitmap)) { using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) { data.SaveTo(imageStream); } } } } } }
/// <summary> /// Constructor /// </summary> public RotaryEventPage() { // NOTICE: IRotaryEventReceiver object MUST set 'RotaryFocusObject' to get the event. RotaryFocusObject = this; // Initialize variables to set the state to rotating right currentState = ONGOING_EVENT_STATE.RIGHT_DIRECTION_ROTATE; instruction = "Rotate the bezel to the right."; angle = 0; // Initialize gradient to draw arrows // Create the main canvas new canvasView = new SKCanvasView(); // Need to set heightRequest and WidthReques to SkiaSharp canvas canvasView.HeightRequest = 360; canvasView.WidthRequest = 360; // Add tap gesture recognizer var tapGestureRecognizer = new TapGestureRecognizer(); // Show a toast when tapped. tapGestureRecognizer.Tapped += (s, e) => { Toast.DisplayText("Tapped !!!"); }; // Add to GestureRecognizers in canvas view canvasView.GestureRecognizers.Add(tapGestureRecognizer); // This event handler actually draws in SkiaSharp canvas canvasView.PaintSurface += (sender, e) => { // Right arrow svg data SKPath rightDirectionArrow = SKPath.ParseSvgPathData("M2.5,4.375l1.5625,-1.25h-1.25a8,8,0,0,0,-6,-6.25a2,2,0,0,1,-0.625,3.125a4.6,4.6,0,0,1,5.875,3.125h-1.25Z"); // Left arrow svg data SKPath leftDirectionArrow = SKPath.ParseSvgPathData("M-2.5,4.375L-4.0625,3.125H-2.8125A8,8,0,0,1,3.1875,-3.125A2,2,0,0,0,3.8125,0A4.6,4.6,0,0,0,-2.0625,3.125H-0.8125Z"); // Get surface SKSurface canvasSurface = e.Surface; // Get canvas of surface SKCanvas canvas = canvasSurface.Canvas; // Save canvas here to later retrieve canvas.Save(); // Initialize canvase before drawing canvas.Clear(SKColors.Black); // Handling for the right rotation state if (currentState == ONGOING_EVENT_STATE.RIGHT_DIRECTION_ROTATE) { // To draw arrow for rotating direction, move canvas point canvas.Translate(e.Info.Width * 3 / 4, e.Info.Height / 4); // Set scale for the path SKMatrix matrix = SKMatrix.MakeScale(15, 15); // Adjust scale before drawing rightDirectionArrow.Transform(matrix); // Set a shader for gradient var colors = new SKColor[] { SKColors.White, SKColors.Blue }; // Points needed for gradient SKPoint startPoint = new SKPoint(0, 0); SKPoint endPoint = new SKPoint(20, 20); var shader = SKShader.CreateLinearGradient(startPoint, endPoint, colors, null, SKShaderTileMode.Clamp); // Add the shader to paint to present gradient effect blackStrokePaint.Shader = shader; // Draw SVG path for right rotate direction arrow canvas.DrawPath(rightDirectionArrow, blackStrokePaint); } else if (currentState == ONGOING_EVENT_STATE.LEFT_DIRECTION_ROTATE) { // Move the canvas translate point canvas.Translate(e.Info.Width * 1 / 4, e.Info.Height / 4); // Set scale for the path SKMatrix matrix = SKMatrix.MakeScale(15, 15); // Set a shader for gradient leftDirectionArrow.Transform(matrix); // Colors for gradient var colors = new SKColor[] { SKColors.White, SKColors.Blue }; // Points for gradient SKPoint startPoint = new SKPoint(20, 0); SKPoint endPoint = new SKPoint(0, 20); // Define a shader for left rotate arrow var shader = SKShader.CreateLinearGradient(startPoint, endPoint, colors, null, SKShaderTileMode.Clamp); blackStrokePaint.Shader = shader; // Draw SVG path for left rotate direction arrow canvas.DrawPath(leftDirectionArrow, blackStrokePaint); } // Need to reset canvas which were changed by Translate canvas.Restore(); // Text drawing SKPaint textPaint = new SKPaint { // Text color white Color = SKColors.White, // Text size 10 TextSize = 10, // Antialiasing true IsAntialias = true }; string str = instruction; // Before draw a text, need to calculate total width of a text to locate in the middle float textWidth = textPaint.MeasureText(str); textPaint.TextSize = 0.7f * e.Info.Width * textPaint.TextSize / textWidth; // Draw instruction SKRect textBounds = new SKRect(); textPaint.MeasureText(str, ref textBounds); float xText = e.Info.Width / 2 - textBounds.MidX; float yText = e.Info.Height / 2 - textBounds.MidY; canvas.DrawText(str, xText, yText, textPaint); }; Content = new StackLayout { Children = { canvasView } }; }
/// <summary> /// Delete folder and icons within /// </summary> /// <param name="currentIcon"></param> public async void ConfirmDeleteFolder(Icon currentIcon) { var response = await Acr.UserDialogs.UserDialogs.Instance.ConfirmAsync("Delete this folder and the icons within?"); if (response && currentIcon != null) { new Xamarin.Forms.Animation((value) => { try { if (currentIcon != null) { currentIcon.Transformation = SKMatrix.MakeScale(1 - (float)value, 1 - (float)value); } } catch (System.Exception e) { System.Diagnostics.Debug.WriteLineIf(App.OutputVerbose, e.ToString()); } }).Commit(Xamarin.Forms.Application.Current.MainPage, "Anim", length: Constants.DeviceLayout.AnimationShrinkMillis, finished: async(v2, c2) => { try { var containedIconColl = canvasRef.Icons.Where(elem => elem.IsStoredInAFolder && elem.StoredFolderTag == currentIcon.Text); if (containedIconColl != null && containedIconColl.Any() && containedIconColl.Count() > 0) { System.Collections.Generic.List <int> indicesToRemove = new System.Collections.Generic.List <int>(); // Build a list of items to remove foreach (var storedIcon in containedIconColl) { indicesToRemove.Add(canvasRef.Icons.IndexOf(storedIcon)); } indicesToRemove = indicesToRemove.Where(i => i != -1) .OrderByDescending(i => i) .ToList(); foreach (var index in indicesToRemove) { canvasRef.Icons.RemoveAt(index); } } if (currentIcon != null) { canvasRef.Icons.Remove(currentIcon); canvasRef.Controller.PromptResave(); #pragma warning disable CS0618 // Type or member is obsolete await PopupNavigation.PopAsync(); #pragma warning restore CS0618 // Type or member is obsolete } } catch (System.Exception e) { System.Diagnostics.Debug.WriteLineIf(App.OutputVerbose, e.ToString()); } }); } }
public MainPage() { InitializeComponent(); //AbsoluteLayout.SetLayoutFlags(CanvasView, AbsoluteLayoutFlags.All); //AbsoluteLayout.SetLayoutBounds(CanvasView, new Rectangle(0, 0, 1, 1)); var bluetoothManager = DependencyService.Get <IManagerManager>().BluetoothManager; var deviceInfomationService = new DeviceInfomationServiceBuilder(bluetoothManager).Build(); bluetoothManager.GattSever.AddService(new DeviceInfomationServiceBuilder(bluetoothManager).Build()); //bluetoothManager.GattSever.AddService(new BatteryServiceWrapper(bluetoothManager).GattServerService); bluetoothManager.GattSever.AddService(new RfcommServerServiceWrapper(bluetoothManager).GattServerService); KeyboardServiceWrapper = new KeyboardServiceWrapper(bluetoothManager); bluetoothManager.GattSever.AddService(KeyboardServiceWrapper.GattServerService); bluetoothManager.GattSever.StartAdvertising(); var createServiceProviderTask = bluetoothManager.CreateRfcommServiceProviderAsync(GyroscopeRfcommServiceConnectionWrapper.RfcommServiceId); createServiceProviderTask.Wait(); var gyroRfcommServiceProvider = createServiceProviderTask.Result; gyroRfcommServiceProvider.OnConnectionReceived += GyroRfcommServiceProvider_OnConnectionReceived; gyroRfcommServiceProvider.StartAdvertising(); Sketch = new Sketch(); Sketch.SkiaManager.Init(CanvasView.InvalidateSurface, SKMatrix.MakeScale(1, -1)); Sketch.SketchEngine.Instantiate <GridRenderer>(); Sketch.SketchEngine.Instantiate <PointerInfoBoard>(); Sketch.SkiaManager.BeforePaint += SkiaManager_BeforePaint; ManagerManager = DependencyService.Get <IManagerManager>(); SketchInputManager = Sketch.SketchEngine.Instantiate <SketchInputManager>(); Sketch.Start(); SketchInputManager.Init(ManagerManager.InputManager); /* * var joystick = Sketch.SketchEngine.Instantiate<ColorJoystick>(); * joystick.RectTransform.AnchorMax = new Vector2(1, 1); * joystick.RectTransform.AnchorMin = new Vector2(0, 0); * joystick.RectTransform.OffsetMax = new Vector2(-800, -800); * joystick.RectTransform.OffsetMin = new Vector2(10, 10); * joystick.Level = 2; */ var joystick2 = Sketch.SketchEngine.Instantiate <LineAreaJoystick <byte> >(); joystick2.RectTransform.AnchorMax = new Vector2(0, 0); joystick2.RectTransform.AnchorMin = new Vector2(0, 0); joystick2.RectTransform.OffsetMax = new Vector2(600, 600); joystick2.RectTransform.OffsetMin = new Vector2(500, 500); joystick2.Level = 3; joystick2.AddArea(AreaJoystick <byte> .Area <byte> .CreateFromAngle((byte)VirtualKeyCode.VK_D, -60, 60, 0, float.PositiveInfinity)); joystick2.AddArea(AreaJoystick <byte> .Area <byte> .CreateFromAngle((byte)VirtualKeyCode.VK_W, 30, 150, 0, float.PositiveInfinity)); joystick2.AddArea(AreaJoystick <byte> .Area <byte> .CreateFromAngle((byte)VirtualKeyCode.VK_A, 120, 240, 0, float.PositiveInfinity)); joystick2.AddArea(AreaJoystick <byte> .Area <byte> .CreateFromAngle((byte)VirtualKeyCode.VK_S, 210, 330, 0, float.PositiveInfinity)); joystick2.AddArea(AreaJoystick <byte> .Area <byte> .CreateFromAngle((byte)VirtualKeyCode.LSHIFT, 0, 360, 0.7f, float.PositiveInfinity)); joystick2.OnAreaStatusChanged += Joystick2_OnAreaStatusChanged; var keyboardButton = Sketch.SketchEngine.Instantiate <KeyboardKeyButton>(); keyboardButton.RectTransform.AnchorMax = new Vector2(0, 0); keyboardButton.RectTransform.AnchorMin = new Vector2(0, 0); keyboardButton.RectTransform.OffsetMin = new Vector2(50, 50); keyboardButton.RectTransform.OffsetMax = new Vector2(150, 150); keyboardButton.Level = 2; ExampleSketchObject = Sketch.SketchEngine.Instantiate <ExampleSketchObject>(); Sketch.SketchEngine.Instantiate <SketchBorderRenderer>(); Sketch.SketchEngine.Instantiate <RectTransformFrameRenderer>(); CanvasView.InvalidateSurface(); ExampleSketchObject.Position = new SKPoint(Sketch.Width / 2, Sketch.Height / 2); SensorSpeed speed = SensorSpeed.Game; Gyroscope.ReadingChanged += Gyroscope_ReadingChanged; Gyroscope.Start(speed); Device.StartTimer(TimeSpan.FromSeconds(1 / 60f), () => { CanvasView.InvalidateSurface(); return(!true); }); }
public MainPage() { this.InitializeComponent(); InputManager inputManager = new InputManager(InputLayerRect); Sketch = new Sketch(); Sketch.SkiaManager.Init(SKCanvasView.Invalidate, SKMatrix.MakeScale(1, -1)); System.Diagnostics.Debug.WriteLine("MainPageThread:" + Thread.CurrentThread.ManagedThreadId); BluetoothManager = new BluetoothManager(); ExampleSketchObject = Sketch.SketchEngine.Instantiate <ExampleSketchObject>(); Sketch.SketchEngine.Instantiate <GridRenderer>(); Sketch.SketchEngine.Instantiate <PointerInfoBoard>(); Sketch.SketchEngine.Instantiate <SketchBorderRenderer>(); sketchInputManager = Sketch.SketchEngine.Instantiate <SketchInputManager>(); sketchInputManager.Init(inputManager); Sketch.Start(); var joystick = Sketch.SketchEngine.Instantiate <ColorJoystick>(); joystick.RectTransform.AnchorMax = new Vector2(0, 0); joystick.RectTransform.AnchorMin = new Vector2(0, 0); joystick.RectTransform.OffsetMax = new Vector2(-100, -100); joystick.RectTransform.OffsetMin = new Vector2(100, 100); joystick.Level = 3; var joystick2 = Sketch.SketchEngine.Instantiate <LineAreaJoystick <byte> >(); joystick2.RectTransform.AnchorMax = new Vector2(0, 0); joystick2.RectTransform.AnchorMin = new Vector2(0, 0); joystick2.RectTransform.OffsetMax = new Vector2(-10, -10); joystick2.RectTransform.OffsetMin = new Vector2(-2000, 2000); joystick2.Level = 2; //InputLayerRect.TransformMatrix; Matrix3x2 matrix = Matrix3x2.CreateScale(0.2f, -0.2f); sketchInputManager.InputSpaceToSketchSpaceMatrix = matrix; Sketch.SkiaManager.BeforePaint += SkiaManager_BeforePaint; /* * var characteristicDict = new Dictionary<Guid, List<CharacteristicProfile>>(); * characteristicDict.Add(KeyboardServiceWrapper.Guid, new List<CharacteristicProfile>() * { * new CharacteristicProfile * { * Notified = true, * Guid = Constants.KeyActionCharacteristicWrapper * } * }); * var serviceId = new List<Guid> * { * GyroscopeRfcommServiceConnectionWrapper.RfcommServiceId * }; * ConnectionProfile profile = new ConnectionProfile() * { * RequiredCharacteristicGuids = characteristicDict, * RequiredServiceGuids = serviceId * }; * * TestJitterFixer.DataEmited += TestJitterFixer_DataEmited; * var dialog = new BleDeviceSelectorDialog(BluetoothManager, profile); * dialog.Closed += Dialog_Closed; * dialog.ShowAsync(); */ }
public async Task <Tuple <Stream, LoadingResult, ImageInformation> > Resolve(string identifier, TaskParameter parameters, CancellationToken token) { ImageSource source = parameters.Source; if (!string.IsNullOrWhiteSpace(parameters.LoadingPlaceholderPath) && parameters.LoadingPlaceholderPath == identifier) { source = parameters.LoadingPlaceholderSource; } else if (!string.IsNullOrWhiteSpace(parameters.ErrorPlaceholderPath) && parameters.ErrorPlaceholderPath == identifier) { source = parameters.ErrorPlaceholderSource; } var resolvedData = await(Configuration.DataResolverFactory ?? new DataResolverFactory()) .GetResolver(identifier, source, parameters, Configuration) .Resolve(identifier, parameters, token).ConfigureAwait(false); if (resolvedData?.Item1 == null) { throw new FileNotFoundException(identifier); } var svg = new SKSvg() { ThrowOnUnsupportedElement = false, }; SKPicture picture; using (var svgStream = resolvedData.Item1) { picture = svg.Load(resolvedData?.Item1); } float sizeX = 0; float sizeY = 0; if (VectorWidth == 0 && VectorHeight == 0) { if (picture.CullRect.Width > 0) { sizeX = picture.CullRect.Width; } else { sizeX = 300; } if (picture.CullRect.Height > 0) { sizeY = picture.CullRect.Height; } else { sizeY = 300; } } else if (VectorWidth > 0 && VectorHeight > 0) { sizeX = VectorWidth; sizeY = VectorHeight; } else if (VectorWidth > 0) { sizeX = VectorWidth; sizeY = (VectorWidth / picture.CullRect.Width) * picture.CullRect.Height; } else { sizeX = (VectorHeight / picture.CullRect.Height) * picture.CullRect.Width; sizeY = VectorHeight; } using (var bitmap = new SKBitmap((int)sizeX, (int)sizeY)) using (var canvas = new SKCanvas(bitmap)) using (var paint = new SKPaint()) { canvas.Clear(SKColors.Transparent); float scaleX = sizeX / picture.CullRect.Width; float scaleY = sizeY / picture.CullRect.Height; var matrix = SKMatrix.MakeScale(scaleX, scaleY); canvas.DrawPicture(picture, ref matrix, paint); canvas.Flush(); using (var image = SKImage.FromBitmap(bitmap)) using (var data = image.Encode(SKImageEncodeFormat.Png, 80)) { var stream = new MemoryStream(); data.SaveTo(stream); stream.Position = 0; //var stream = data?.AsStream(); return(new Tuple <Stream, LoadingResult, ImageInformation>(stream, resolvedData.Item2, resolvedData.Item3)); } } }
void OnTouchEffectAction(object sender, TouchActionEventArgs args) { // Convert Xamarin.Forms point to pixels var pt = args.Location; SKPoint point = new SKPoint((float)(canvasView.CanvasSize.Width * pt.X / canvasView.Width), (float)(canvasView.CanvasSize.Height * pt.Y / canvasView.Height)); switch (args.Type) { case TouchActionType.Pressed: // Find transformed bitmap rectangle SKRect rect = new SKRect(0, 0, bitmap.Width, bitmap.Height); rect = matrix.MapRect(rect); // Determine if the touch was within that rectangle //if (rect.Contains(point)) //{ // // touchId = args.Id; // // previousPoint = point; // touchDictionary.Add(args.Id, point); //} if (rect.Contains(point) && !touchDictionary.ContainsKey(args.Id)) { touchDictionary.Add(args.Id, point); } break; case TouchActionType.Moved: if (touchDictionary.ContainsKey(args.Id)) { //if (touchId == args.Id) if (touchDictionary.Count == 1) { // Adjust the matrix for the new position //matrix.TransX += point.X - previousPoint.X; //matrix.TransY += point.Y - previousPoint.Y; //previousPoint = point; SKPoint prevPoint = touchDictionary[args.Id]; matrix.TransX += point.X - prevPoint.X; matrix.TransY += point.Y - prevPoint.Y; // Move within canvas limits //if (matrix.TransX > 0) matrix.TransX = 0; //if (matrix.TransX < - bitmap.Width + (int)canvasView.CanvasSize.Width) matrix.TransX = - bitmap.Width + (int)canvasView.CanvasSize.Width; //if (matrix.TransY > 0) matrix.TransY = 0; //if (matrix.TransY < -bitmap.Height + (int)canvasView.CanvasSize.Height) matrix.TransY = -bitmap.Height + (int)canvasView.CanvasSize.Height; canvasView.InvalidateSurface(); } else if (touchDictionary.Count >= 2) { // Copy two dictionary keys into array long[] keys = new long[touchDictionary.Count]; touchDictionary.Keys.CopyTo(keys, 0); // Find index of non-moving (pivot) finger int pivotIndex = (keys[0] == args.Id) ? 1 : 0; // Get the three points involved in the transform SKPoint pivotPoint = touchDictionary[keys[pivotIndex]]; SKPoint prevPoint = touchDictionary[args.Id]; SKPoint newPoint = point; // Calculate two vectors SKPoint oldVector = prevPoint - pivotPoint; SKPoint newVector = newPoint - pivotPoint; // Scaling factors are ratios of those scaleX = newVector.X / oldVector.X; scaleY = newVector.Y / oldVector.Y; //if (!float.IsNaN(scaleX) && !float.IsInfinity(scaleX) && // !float.IsNaN(scaleY) && !float.IsInfinity(scaleY)) if (!float.IsNaN(scaleX) && !float.IsInfinity(scaleX)) { // If something bad hasn't happened, calculate a scale and translation matrix SKMatrix scaleMatrix = SKMatrix.MakeScale(scaleX, scaleX, pivotPoint.X, pivotPoint.Y); SKMatrix.PostConcat(ref matrix, scaleMatrix); canvasView.InvalidateSurface(); } } // Store the new point in the dictionary touchDictionary[args.Id] = point; } break; case TouchActionType.Released: case TouchActionType.Cancelled: // touchId = -1; if (touchDictionary.ContainsKey(args.Id)) { touchDictionary.Remove(args.Id); } break; } }
private void FolderCanvas_PaintSurface(object sender, SkiaSharp.Views.Forms.SKPaintSurfaceEventArgs e) { SKImageInfo info = e.Info; SKSurface surface = e.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(); float scaleFactor = 0.67f; float density = scaleFactor * info.Size.Height / (float)this.Height; canvas.Save(); using (SKPath backPath = SKPath.ParseSvgPathData( "M87.909,9.917V4.02A4.032,4.032,0,0,0,83.889,0H23.72A4.032,4.032,0,0,0,19.7,4.02v5.9H13.338a4.529,4.529,0,0,0-3.822,4.02l.27,112.7a3.954,3.954,0,0,0,3.951,4.024H167.344a3.963,3.963,0,0,0,3.97-4.011l-.6-112.71a4.092,4.092,0,0,0-4.07-4.02Z")) { backPath.Transform(SKMatrix.MakeScale(density, density)); backPath.GetTightBounds(out var backPathTightBounds); var translateXBackPath = info.Width * 0.5f - backPathTightBounds.MidX; var translateYbackPath = info.Height - backPathTightBounds.Bottom - 20f; canvas.Translate(translateXBackPath, translateYbackPath); fillPaint.Shader = SKShader.CreateLinearGradient( new SKPoint(info.Width * 0.5f, 0), new SKPoint(info.Width * 0.5f, info.Height), new SKColor[] { SKColor.Parse(Color1), SKColor.Parse(Color2), SKColor.Parse(Color2) }, new float[] { 0, 0.37f, 1 }, SKShaderTileMode.Clamp ); canvas.DrawPath(backPath, fillPaint); } canvas.Restore(); canvas.Save(); using (SKPath backFilePath = SKPath.ParseSvgPathData("M174.079,150.908H29.155l-.4-114.144H174.481Z")) { backFilePath.Transform(SKMatrix.MakeScale(density, density)); backFilePath.GetTightBounds(out var backFilePathTightBounds); var translateXBackFilePath = info.Width * 0.5f - backFilePathTightBounds.MidX; var translateYbackFilePath = info.Height - backFilePathTightBounds.Bottom - 20f; canvas.Translate(translateXBackFilePath, translateYbackFilePath); fillPaint.Shader = SKShader.CreateLinearGradient( new SKPoint(info.Width * 0.5f, 0), new SKPoint(info.Width * 0.5f, info.Height), new SKColor[] { SKColor.Parse("#e6e6e6"), SKColor.Parse("#e8e8e8"), SKColor.Parse("#f0f0f0"), SKColor.Parse("#f2f2f2") }, new float[] { 0, 0.633f, 0.949f, 1 }, SKShaderTileMode.Clamp ); canvas.DrawPath(backFilePath, fillPaint); } canvas.Restore(); canvas.Save(); using (SKPath frontFilePath = SKPath.ParseSvgPathData("M170.491,158.681H25.567L22.753,49.764H173.3Z")) { frontFilePath.Transform(SKMatrix.MakeScale(density, density)); frontFilePath.GetTightBounds(out var frontFilePathTightBounds); var translateXFrontFilePath = info.Width * 0.5f - frontFilePathTightBounds.MidX; var translateYFrontFilePath = info.Height - frontFilePathTightBounds.Bottom - 20f; canvas.Translate(translateXFrontFilePath, translateYFrontFilePath); fillPaint.Shader = SKShader.CreateLinearGradient( new SKPoint(info.Width * 0.5f, 0), new SKPoint(info.Width * 0.5f, info.Height), new SKColor[] { SKColor.Parse("#cccccc"), SKColor.Parse("#cecece"), SKColor.Parse("#d6d6d6"), SKColor.Parse("#e3e3e3"), SKColor.Parse("#f6f6f6"), SKColor.Parse("#ffffff") }, new float[] { 0, 0.427f, 0.64f, 0.806f, 0.947f, 1 }, SKShaderTileMode.Clamp ); canvas.DrawPath(frontFilePath, fillPaint); } canvas.Restore(); canvas.Save(); using (SKPath frontPath = SKPath.ParseSvgPathData("M165.433,164.917a4.106,4.106,0,0,1-4.089,4.011H7.735a4.578,4.578,0,0,1-4.325-4.292L0,68.019A3.948,3.948,0,0,1,3.95,64H164.895a3.948,3.948,0,0,1,3.95,4.02Z")) { frontPath.Transform(SKMatrix.MakeScale(density, density)); frontPath.GetTightBounds(out var frontPathTightBounds); fillPaint.Shader = SKShader.CreateLinearGradient( new SKPoint(info.Width * 0.5f, 0), new SKPoint(info.Width * 0.5f, info.Height), new SKColor[] { SKColor.Parse(Color3), SKColor.Parse(Color4), SKColor.Parse(Color5), SKColor.Parse(Color6) }, new float[] { 0, 0.595f, 0.957f, 1 }, SKShaderTileMode.Clamp ); SKMatrix matrix = SKMatrix.MakeTranslation(-frontPathTightBounds.Right, -frontPathTightBounds.Bottom); SKMatrix44 matrix44 = SKMatrix44.CreateIdentity(); matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(1, 0, 0, -FrontPathDegree)); matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(0, 1, 0, -0.5f * FrontPathDegree)); matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(0, 0, 1, 0)); SKMatrix.PostConcat(ref matrix, matrix44.Matrix); SKMatrix.PostConcat(ref matrix, SKMatrix.MakeTranslation(frontPathTightBounds.Right, frontPathTightBounds.Bottom)); canvas.SetMatrix(matrix); var translateXFrontPath = info.Width * 0.5f - frontPathTightBounds.MidX; var translateYFrontPath = info.Height - frontPathTightBounds.Bottom - 20f; canvas.Translate(translateXFrontPath, translateYFrontPath); canvas.DrawPath(frontPath, fillPaint); } canvas.Restore(); }
public static List <MGLPaint> ConvertFillLayer(JsonStyleLayer jsonStyleLayer, MGLSpriteAtlas spriteAtlas) { var layout = jsonStyleLayer?.Layout; var paint = jsonStyleLayer?.Paint; var area = new MGLPaint(); var line = new MGLPaint(); // Set defaults area.SetFixColor(new SKColor(0, 0, 0, 0)); area.SetFixOpacity(1); area.SetFixStyle(SKPaintStyle.Fill); line.SetFixColor(new SKColor(0, 0, 0, 0)); line.SetFixOpacity(1); line.SetFixStyle(SKPaintStyle.Stroke); line.SetFixStrokeWidth(0); // If we don't have a paint, than there isn't anything that we could do if (paint == null) { return(new List <MGLPaint>() { area, line }); } // fill-color // Optional color. Defaults to #000000. Disabled by fill-pattern. Exponential. // The color of the filled part of this layer. This color can be specified as // rgba with an alpha component and the color's opacity will not affect the // opacity of the 1px stroke, if it is used. if (paint.FillColor != null) { if (paint.FillColor.Stops != null) { area.SetVariableColor((context) => jsonStyleLayer.Paint.FillColor.Evaluate(context.Zoom)); line.SetVariableColor((context) => jsonStyleLayer.Paint.FillColor.Evaluate(context.Zoom)); } else { area.SetFixColor(jsonStyleLayer.Paint.FillColor.SingleVal); line.SetFixColor(jsonStyleLayer.Paint.FillColor.SingleVal); } } // fill-outline-color // Optional color. Disabled by fill-pattern. Requires fill-antialias = true. Exponential. // The outline color of the fill. Matches the value of fill-color if unspecified. if (paint.FillOutlineColor != null && paint.FillAntialias != null) { if (paint.FillOutlineColor.Stops != null) { line.SetVariableColor((context) => jsonStyleLayer.Paint.FillOutlineColor.Evaluate(context.Zoom)); } else { line.SetFixColor(jsonStyleLayer.Paint.FillOutlineColor.SingleVal); } } // fill-opacity // Optional number. Defaults to 1. Exponential. // The opacity of the entire fill layer. In contrast to the fill-color, this // value will also affect the 1px stroke around the fill, if the stroke is used. if (paint.FillOpacity != null) { if (paint.FillOpacity.Stops != null) { area.SetVariableOpacity((context) => jsonStyleLayer.Paint.FillOpacity.Evaluate(context.Zoom)); line.SetVariableOpacity((context) => jsonStyleLayer.Paint.FillOpacity.Evaluate(context.Zoom)); } else { area.SetFixOpacity(jsonStyleLayer.Paint.FillOpacity.SingleVal); line.SetFixOpacity(jsonStyleLayer.Paint.FillOpacity.SingleVal); } } // fill-antialias // Optional boolean. Defaults to true. Interval. // Whether or not the fill should be antialiased. if (paint.FillAntialias != null) { if (paint.FillAntialias.Stops != null) { area.SetVariableAntialias((context) => jsonStyleLayer.Paint.FillAntialias.Evaluate(context.Zoom)); line.SetVariableAntialias((context) => jsonStyleLayer.Paint.FillAntialias.Evaluate(context.Zoom)); } else { area.SetFixAntialias(jsonStyleLayer.Paint.FillAntialias.SingleVal == null ? false : (bool)jsonStyleLayer.Paint.FillAntialias.SingleVal); line.SetFixAntialias(jsonStyleLayer.Paint.FillAntialias.SingleVal == null ? false : (bool)jsonStyleLayer.Paint.FillAntialias.SingleVal); } } // fill-translate // Optional array. Units in pixels. Defaults to 0,0. Exponential. // The geometry's offset. Values are [x, y] where negatives indicate left and up, // respectively. // TODO: Use matrix of paint object for this // fill-translate-anchor // Optional enum. One of map, viewport. Defaults to map. Requires fill-translate. Interval. // Control whether the translation is relative to the map (north) or viewport (screen) // TODO: Use matrix of paint object for this // fill-pattern // Optional string. Interval. // Name of image in sprite to use for drawing image fills. For seamless patterns, // image width and height must be a factor of two (2, 4, 8, …, 512). if (paint.FillPattern != null) { // FillPattern needs a color. Instead no pattern is drawn. area.SetFixColor(SKColors.Black); if (paint.FillPattern.Stops == null && !paint.FillPattern.SingleVal.Contains("{")) { area.SetVariableShader((context) => { var name = paint.FillPattern.SingleVal; var sprite = spriteAtlas.GetSprite(name); if (sprite != null && sprite.Image != null) { return(sprite.Image.ToShader(SKShaderTileMode.Repeat, SKShaderTileMode.Repeat, SKMatrix.MakeScale(context.Scale, context.Scale))); } else { // Log information, that no sprite is found // TODO // Logging.Logger.Log(Logging.LogLevel.Information, $"Fill pattern {name} not found"); return(null); } }); } else { area.SetVariableShader((context) => { var name = ReplaceFields(jsonStyleLayer.Paint.FillPattern.Evaluate(context.Zoom), context.Tags); var sprite = spriteAtlas.GetSprite(name); if (sprite != null && sprite.Image != null) { return(sprite.Image.ToShader(SKShaderTileMode.Repeat, SKShaderTileMode.Repeat, SKMatrix.MakeScale(context.Scale, context.Scale))); } else { // Log information, that no sprite is found // TODO // Logging.Logger.Log(Logging.LogLevel.Information, $"Fill pattern {name} not found"); return(null); } }); } } return(new List <MGLPaint>() { area, line }); }
/// <summary> /// Insert an icon into a specific folder /// </summary> /// <param name="_currentIcon"></param> /// <param name="folderOfInterest"></param> public void InsertIntoFolder(Icon _currentIcon, System.Collections.Generic.IEnumerable <Icon> folderOfInterest) { if (folderOfInterest != null && _currentIcon != null && folderOfInterest.Count() > 0) { System.Diagnostics.Debug.WriteLineIf(App.OutputVerbose, "In Completed: Insertable into folder: " + _currentIcon.Tag); var folderToInsertInto = folderOfInterest.First(); var startPoint = _currentIcon.Location; float xDiff = (folderToInsertInto.Location.X + folderToInsertInto.Bounds.Width / 2f) - (startPoint.X + _currentIcon.Bounds.Width / 2f); float yDiff = (folderToInsertInto.Location.Y + folderToInsertInto.Bounds.Height / 2f) - (startPoint.Y + _currentIcon.Bounds.Height / 2f); new Xamarin.Forms.Animation((value) => { if (_currentIcon != null) { try { _currentIcon.Location = new SKPoint((startPoint.X) + (xDiff * (float)value), (startPoint.Y) + (yDiff * (float)value)); } catch (System.Exception e) { System.Diagnostics.Debug.WriteLineIf(App.OutputVerbose, e.ToString()); } } }).Commit(Xamarin.Forms.Application.Current.MainPage, "Anim", length: Constants.DeviceLayout.AnimationMoveMillis, finished: (v, c) => { new Xamarin.Forms.Animation((value) => { try { if (_currentIcon != null) { _currentIcon.Transformation = SKMatrix.MakeScale(1 - (float)value, 1 - (float)value); } } catch (System.Exception e) { System.Diagnostics.Debug.WriteLineIf(App.OutputVerbose, e.ToString()); } }).Commit(Xamarin.Forms.Application.Current.MainPage, "Anim", length: Constants.DeviceLayout.AnimationShrinkMillis, finished: (v2, c2) => { try { if (_currentIcon != null) { _currentIcon.IsStoredInAFolder = true; _currentIcon.Transformation = SKMatrix.MakeScale(1, 1); _currentIcon.StoredFolderTag = folderToInsertInto.Text; canvasRef.Icons.SendToBack(_currentIcon); canvasRef.Controller.PromptResave(); } } catch (System.Exception e) { System.Diagnostics.Debug.WriteLineIf(App.OutputVerbose, e.ToString()); } }); }); } }
internal void DrawMarker(SvgMarker svgMarker, SvgVisualElement pOwner, SKPoint pMarkerPoint, float fAngle) { var markerElement = GetMarkerElement(svgMarker); if (markerElement == null) { return; } var skMarkerMatrix = SKMatrix.MakeIdentity(); var skMatrixMarkerPoint = SKMatrix.MakeTranslation(pMarkerPoint.X, pMarkerPoint.Y); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixMarkerPoint); var skMatrixAngle = SKMatrix.MakeRotationDegrees(svgMarker.Orient.IsAuto ? fAngle : svgMarker.Orient.Angle); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixAngle); var strokeWidth = pOwner.StrokeWidth.ToDeviceValue(null, UnitRenderingType.Other, svgMarker); var refX = svgMarker.RefX.ToDeviceValue(null, UnitRenderingType.Horizontal, svgMarker); var refY = svgMarker.RefY.ToDeviceValue(null, UnitRenderingType.Horizontal, svgMarker); float markerWidth = svgMarker.MarkerWidth; float markerHeight = svgMarker.MarkerHeight; float viewBoxToMarkerUnitsScaleX = 1f; float viewBoxToMarkerUnitsScaleY = 1f; switch (svgMarker.MarkerUnits) { case SvgMarkerUnits.StrokeWidth: { var skMatrixStrokeWidth = SKMatrix.MakeScale(strokeWidth, strokeWidth); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixStrokeWidth); var viewBoxWidth = svgMarker.ViewBox.Width; var viewBoxHeight = svgMarker.ViewBox.Height; var scaleFactorWidth = (viewBoxWidth <= 0) ? 1 : (markerWidth / viewBoxWidth); var scaleFactorHeight = (viewBoxHeight <= 0) ? 1 : (markerHeight / viewBoxHeight); viewBoxToMarkerUnitsScaleX = Math.Min(scaleFactorWidth, scaleFactorHeight); viewBoxToMarkerUnitsScaleY = Math.Min(scaleFactorWidth, scaleFactorHeight); var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX * viewBoxToMarkerUnitsScaleX, -refY * viewBoxToMarkerUnitsScaleY); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixTranslateRefXY); var skMatrixScaleXY = SKMatrix.MakeScale(viewBoxToMarkerUnitsScaleX, viewBoxToMarkerUnitsScaleY); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixScaleXY); } break; case SvgMarkerUnits.UserSpaceOnUse: { var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX, -refY); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixTranslateRefXY); } break; } _skCanvas.Save(); var skMatrix = SkiaUtil.GetSKMatrix(svgMarker.Transforms); SKMatrix.PreConcat(ref skMatrix, ref skMarkerMatrix); SetTransform(skMatrix); SetClipPath(svgMarker, _disposable); var skPaintOpacity = SetOpacity(svgMarker, _disposable); var skPaintFilter = SetFilter(svgMarker, _disposable); switch (svgMarker.Overflow) { case SvgOverflow.Auto: case SvgOverflow.Visible: case SvgOverflow.Inherit: break; default: var skClipRect = SKRect.Create( svgMarker.ViewBox.MinX, svgMarker.ViewBox.MinY, markerWidth / viewBoxToMarkerUnitsScaleX, markerHeight / viewBoxToMarkerUnitsScaleY); _skCanvas.ClipRect(skClipRect, SKClipOperation.Intersect); break; } Draw(markerElement, true); if (skPaintFilter != null) { _skCanvas.Restore(); } if (skPaintOpacity != null) { _skCanvas.Restore(); } _skCanvas.Restore(); }
public override void Execute() { JsConfig.IncludeNullValues = false; JsConfig.EmitCamelCaseNames = true; foreach (var platform in Configuration.Platforms) { var fileName = Path.Combine(WorkingDirectory, platform.IconFileName); var fileInfo = new FileInfo(fileName); if (!File.Exists(fileInfo.FullName)) { Log.Error($"Icon not found ({fileInfo.FullName})"); continue; } var svg = SkiaHelper.Load(fileInfo.FullName); var sourceActualWidth = svg.Picture.CullRect.Width; var sourceActualHeight = svg.Picture.CullRect.Height; var assets = new List <ExportAsset>(); var platformPath = new DirectoryInfo(Path.Combine(WorkingDirectory, platform.ProjectPath)); if (!platformPath.Exists) { Log.Error($"Platform path for {platform.Type} not found ({platformPath.FullName})"); continue; } switch (platform.Type) { case Platforms.iOS: { var targetPath = Path.Combine(platformPath.FullName, "Assets.xcassets", "AppIcon.appiconset"); var sizes = new[] { 20, 29, 40, 58, 60, 76, 80, 87, 120, 152, 167, 180, 1024 }; assets.AddRange(sizes.Select(size => new ExportAsset(fileInfo.FullName, targetPath, $"Icon-App-{size}x{size}.png", sourceActualWidth, sourceActualHeight, size, size))); break; } case Platforms.AppleWatch: { var targetPath = Path.Combine(platformPath.FullName, "Assets.xcassets", "AppIcon.appiconset"); var sizes = new[] { 48, 55, 58, 80, 87, 88, 172, 196 }; assets.AddRange(sizes.Select(size => new ExportAsset(fileInfo.FullName, targetPath, $"Icon-App-{size}x{size}.png", sourceActualWidth, sourceActualHeight, size, size))); break; } case Platforms.MacOs: { var targetPath = Path.Combine(platformPath.FullName, "Assets.xcassets", "AppIcon.appiconset"); var sizes = new[] { 16, 32, 64, 128, 256, 512, 1024 }; assets.AddRange(sizes.Select(size => new ExportAsset(fileInfo.FullName, targetPath, $"Icon-App-{size}x{size}.png", sourceActualWidth, sourceActualHeight, size, size))); break; } case Platforms.Android: { var folderPrefix = "mipmap"; if (platform.AndroidOptions != null && !string.IsNullOrEmpty(platform.AndroidOptions.AssetFolderPrefix.ToString())) { folderPrefix = platform.AndroidOptions.AssetFolderPrefix.ToString(); } assets.Add(new ExportAsset(fileInfo.FullName, Path.Combine(platformPath.FullName, "Resources", $"{folderPrefix}-mdpi"), "Icon.png", sourceActualWidth, sourceActualHeight, 48, 48)); assets.Add(new ExportAsset(fileInfo.FullName, Path.Combine(platformPath.FullName, "Resources", $"{folderPrefix}-hdpi"), "Icon.png", sourceActualWidth, sourceActualHeight, 72, 72)); assets.Add(new ExportAsset(fileInfo.FullName, Path.Combine(platformPath.FullName, "Resources", $"{folderPrefix}-xhdpi"), "Icon.png", sourceActualWidth, sourceActualHeight, 96, 96)); assets.Add(new ExportAsset(fileInfo.FullName, Path.Combine(platformPath.FullName, "Resources", $"{folderPrefix}-xxhdpi"), "Icon.png", sourceActualWidth, sourceActualHeight, 144, 144)); assets.Add(new ExportAsset(fileInfo.FullName, Path.Combine(platformPath.FullName, "Resources", $"{folderPrefix}-xxxhdpi"), "Icon.png", sourceActualWidth, sourceActualHeight, 192, 192)); break; } case Platforms.UWP: { // https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/app-assets#asset-size-tables var targetPath = Path.Combine(platformPath.FullName, "Assets"); var sizes = new[] { 71, 150, 310, 44 }; var scales = new[] { 100, 125, 150, 200, 400 }; foreach (var size in sizes) { assets.AddRange(scales.Select(scale => new ExportAsset(fileInfo.FullName, targetPath, $"Square{size}x{size}Logo.scale-{scale}.png", sourceActualWidth, sourceActualHeight, size, size))); } break; } default: throw new ArgumentOutOfRangeException(); } foreach (var asset in assets) { var bmp = new SKBitmap((int)asset.ScaledWidth, (int)asset.ScaledHeight); var canvas = new SKCanvas(bmp); var matrix = SKMatrix.MakeScale((float)asset.Ratio, (float)asset.Ratio); canvas.Clear(SKColors.Transparent); canvas.DrawPicture(svg.Picture, ref matrix); canvas.Save(); // Export the canvas var img = SKImage.FromBitmap(bmp); var data = img.Encode(SKEncodedImageFormat.Png, 100); asset.FileName.EnsureFolderExists(); using (var fs = File.Open(asset.FileName, FileMode.Create)) { Log.Information($"Writing {asset.FileName}"); data.SaveTo(fs); } var platformProjectFolder = Path.Combine(WorkingDirectory, platform.ProjectPath); var destinationFolder = "Resources"; if (platform.Type == Platforms.UWP) { destinationFolder = "Assets"; } var destinationFile = Path.Combine(WorkingDirectory, platform.ProjectPath, destinationFolder, asset.FileName); switch (platform.Type) { case Platforms.iOS: case Platforms.AppleWatch: case Platforms.MacOs: FluentMSBuild.Use(destinationFile).WithBuildAction(BuildAction.ImageAsset).AddToProject(); break; case Platforms.Android: FluentMSBuild.Use(destinationFile).WithBuildAction(BuildAction.AndroidResource).AddToProject(); break; case Platforms.UWP: FluentMSBuild.Use(destinationFile).WithBuildAction(BuildAction.Content).AddToProject(); break; } } if (platform.Type == Platforms.iOS || platform.Type == Platforms.AppleWatch || platform.Type == Platforms.MacOs) { var contentsFile = Path.Combine(platformPath.FullName, "Assets.xcassets", "AppIcon.appiconset", "Contents.json"); Log.Information($"Writing {contentsFile}"); var contents = File.ReadAllText(contentsFile).FromJson <XcodeContents>(); foreach (var contentsImage in contents.Images) { var process = false; switch (platform.Type) { case Platforms.iOS when contentsImage.Idiom == "iphone" || contentsImage.Idiom == "ipad" || contentsImage.Idiom == "ios-marketing": case Platforms.AppleWatch when contentsImage.Idiom == "watch": case Platforms.MacOs when contentsImage.Idiom == "mac": process = true; break; } if (process) { // calculate needed size var size = double.Parse(contentsImage.Size.Split('x')[0], NumberStyles.Float, new CultureInfo("en-US")); var scale = double.Parse(contentsImage.Scale.Substring(0, 1)); var foundSize = assets.FirstOrDefault(a => a.ScaledWidth == size * scale); if (foundSize != null) { contentsImage.Filename = new FileInfo(foundSize.FileName).Name; } } } File.WriteAllText(contentsFile, contents.ToJson().IndentJson()); } } }
public MultiPhotoSelectioControlsOverlayView(Context context) : base(context) { PaintSurface += Handle_PaintSurface; SetBackgroundColor(graphics.Color.Transparent); paint.IsAntialias = true; closeButton = new SvgButton("close_button.svg", "close_button_touched.svg", SKMatrix.MakeScale(0.8f, 0.8f), context); trashButton = new SvgButton("trash_button.svg", "trash_button_touched.svg", SKMatrix.MakeScale(0.8f, 0.8f), context); sendButton = new SvgButton("send_button.svg", "send_button_touched.svg", SKMatrix.MakeScale(2.5f, 2.5f), context); buttons.AddRange(new[] { closeButton, trashButton, sendButton }); Device.StartTimer(TimeSpan.FromMilliseconds(1000 / 60), () => { Invalidate(); return(timerActive); }); }
public MarkerDrawable(SvgMarker svgMarker, SvgVisualElement pOwner, SKPoint pMarkerPoint, float fAngle, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes = Attributes.None) : base(svgMarker, root, parent) { IgnoreAttributes = Attributes.Display | ignoreAttributes; IsDrawable = true; if (!IsDrawable) { return; } var markerElement = GetMarkerElement(svgMarker); if (markerElement == null) { IsDrawable = false; return; } var skMarkerMatrix = SKMatrix.MakeIdentity(); var skMatrixMarkerPoint = SKMatrix.MakeTranslation(pMarkerPoint.X, pMarkerPoint.Y); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixMarkerPoint); var skMatrixAngle = SKMatrix.MakeRotationDegrees(svgMarker.Orient.IsAuto ? fAngle : svgMarker.Orient.Angle); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixAngle); var strokeWidth = pOwner.StrokeWidth.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds); var refX = svgMarker.RefX.ToDeviceValue(UnitRenderingType.Horizontal, svgMarker, skOwnerBounds); var refY = svgMarker.RefY.ToDeviceValue(UnitRenderingType.Vertical, svgMarker, skOwnerBounds); float markerWidth = svgMarker.MarkerWidth.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds); float markerHeight = svgMarker.MarkerHeight.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds); float viewBoxToMarkerUnitsScaleX = 1f; float viewBoxToMarkerUnitsScaleY = 1f; switch (svgMarker.MarkerUnits) { case SvgMarkerUnits.StrokeWidth: { var skMatrixStrokeWidth = SKMatrix.MakeScale(strokeWidth, strokeWidth); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixStrokeWidth); var viewBoxWidth = svgMarker.ViewBox.Width; var viewBoxHeight = svgMarker.ViewBox.Height; var scaleFactorWidth = (viewBoxWidth <= 0) ? 1 : (markerWidth / viewBoxWidth); var scaleFactorHeight = (viewBoxHeight <= 0) ? 1 : (markerHeight / viewBoxHeight); viewBoxToMarkerUnitsScaleX = Math.Min(scaleFactorWidth, scaleFactorHeight); viewBoxToMarkerUnitsScaleY = Math.Min(scaleFactorWidth, scaleFactorHeight); var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX * viewBoxToMarkerUnitsScaleX, -refY * viewBoxToMarkerUnitsScaleY); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixTranslateRefXY); var skMatrixScaleXY = SKMatrix.MakeScale(viewBoxToMarkerUnitsScaleX, viewBoxToMarkerUnitsScaleY); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixScaleXY); } break; case SvgMarkerUnits.UserSpaceOnUse: { var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX, -refY); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixTranslateRefXY); } break; } switch (svgMarker.Overflow) { case SvgOverflow.Auto: case SvgOverflow.Visible: case SvgOverflow.Inherit: break; default: MarkerClipRect = SKRect.Create( svgMarker.ViewBox.MinX, svgMarker.ViewBox.MinY, markerWidth / viewBoxToMarkerUnitsScaleX, markerHeight / viewBoxToMarkerUnitsScaleY); break; } var drawable = DrawableFactory.Create(markerElement, skOwnerBounds, root, this, Attributes.Display); if (drawable != null) { MarkerElementDrawable = drawable; _disposable.Add(MarkerElementDrawable); } else { IsDrawable = false; return; } IsAntialias = SvgPaintingExtensions.IsAntialias(svgMarker); TransformedBounds = MarkerElementDrawable.TransformedBounds; Transform = SvgTransformsExtensions.ToSKMatrix(svgMarker.Transforms); SKMatrix.PreConcat(ref Transform, ref skMarkerMatrix); Fill = null; Stroke = null; // TODO: Transform _skBounds using _skMatrix. SKMatrix.MapRect(ref Transform, out TransformedBounds, ref TransformedBounds); }
public async Task <DataResolverResult> Resolve(string identifier, TaskParameter parameters, CancellationToken token) { var source = parameters.Source; if (!string.IsNullOrWhiteSpace(parameters.LoadingPlaceholderPath) && parameters.LoadingPlaceholderPath == identifier) { source = parameters.LoadingPlaceholderSource; } else if (!string.IsNullOrWhiteSpace(parameters.ErrorPlaceholderPath) && parameters.ErrorPlaceholderPath == identifier) { source = parameters.ErrorPlaceholderSource; } var resolvedData = await(Configuration.DataResolverFactory ?? new DataResolverFactory()) .GetResolver(identifier, source, parameters, Configuration) .Resolve(identifier, parameters, token).ConfigureAwait(false); if (resolvedData?.Stream == null) { throw new FileNotFoundException(identifier); } var svg = new SKSvg() { ThrowOnUnsupportedElement = false, }; SKPicture picture; if (ReplaceStringMap == null || ReplaceStringMap.Count == 0) { using (var svgStream = resolvedData.Stream) { picture = svg.Load(svgStream, token); } } else { using (var svgStream = resolvedData.Stream) using (var reader = new StreamReader(svgStream)) { var inputString = await reader.ReadToEndAsync().ConfigureAwait(false); foreach (var map in ReplaceStringMap .Where(v => v.Key.StartsWith("regex:", StringComparison.OrdinalIgnoreCase))) { inputString = Regex.Replace(inputString, map.Key.Substring(6), map.Value); } var builder = new StringBuilder(inputString); foreach (var map in ReplaceStringMap .Where(v => !v.Key.StartsWith("regex:", StringComparison.OrdinalIgnoreCase))) { builder.Replace(map.Key, map.Value); } token.ThrowIfCancellationRequested(); using (var svgFinalStream = new MemoryStream(Encoding.UTF8.GetBytes(builder.ToString()))) { picture = svg.Load(svgFinalStream); } } } token.ThrowIfCancellationRequested(); double sizeX = VectorWidth; double sizeY = VectorHeight; if (UseDipUnits) { sizeX = VectorWidth.DpToPixels(); sizeY = VectorHeight.DpToPixels(); } if (sizeX <= 0 && sizeY <= 0) { if (picture.CullRect.Width > 0) { sizeX = picture.CullRect.Width; } else { sizeX = 400; } if (picture.CullRect.Height > 0) { sizeY = picture.CullRect.Height; } else { sizeY = 400; } } else if (sizeX > 0 && sizeY <= 0) { sizeY = (int)(sizeX / picture.CullRect.Width * picture.CullRect.Height); } else if (sizeX <= 0 && sizeY > 0) { sizeX = (int)(sizeY / picture.CullRect.Height * picture.CullRect.Width); } resolvedData.ImageInformation.SetType(ImageInformation.ImageType.SVG); using (var bitmap = new SKBitmap(new SKImageInfo((int)sizeX, (int)sizeY))) using (var canvas = new SKCanvas(bitmap)) using (var paint = new SKPaint()) { canvas.Clear(SKColors.Transparent); var scaleX = (float)sizeX / picture.CullRect.Width; var scaleY = (float)sizeY / picture.CullRect.Height; var matrix = SKMatrix.MakeScale(scaleX, scaleY); canvas.DrawPicture(picture, ref matrix, paint); canvas.Flush(); token.ThrowIfCancellationRequested(); return(await Decode(picture, bitmap, resolvedData).ConfigureAwait(false)); } }
public void WriteToStream(MemoryStream output) { var converter = new Converter(PakSupplier.Index); StoreItem[] weekly = new StoreItem[Store.Weekly.Length]; for (int i = 0; i < weekly.Length; i++) { try { weekly[i] = converter.ConvertItem(Store.Weekly[i]); } catch (Exception e) { Console.WriteLine(e); } } StoreItem[] daily = new StoreItem[Store.Daily.Length]; for (int i = 0; i < daily.Length; i++) { try { daily[i] = converter.ConvertItem(Store.Daily[i]); } catch (Exception e) { Console.WriteLine(e); throw e; } } // number of featured categories var weeklies = Converter.GetCategorySlots(weekly, out var count, out var sizes, out var size); Config.SelectedCategory = count; var gc = new GlobalCache(converter.Index); // TODO: making it any larger doesn't affect the text or icon resolution :( // might have to do with the canvas only writing 1080p pixels on a 4k (e.g) image const int w = 1280; const int h = 720; using var ret = new SKBitmap(w, h, SKColorType.Rgba8888, SKAlphaType.Opaque); using var stream = new VideoOutputStream(ret, 30, 1024 * 1024 * 5, output, true); using (var c = new SKCanvas(ret)) { if (!string.IsNullOrWhiteSpace(Background) && File.Exists(Background)) { try { // TODO: make this permanent or part of drawing the cache (maybe?) just do something using var bmp = SKBitmap.Decode(Background); c.DrawBitmap(bmp, new SKRect(0, 0, w, h), new SKPaint { FilterQuality = SKFilterQuality.High, IsAntialias = true }); } catch (Exception e) { Console.WriteLine(e); } } c.SetMatrix(SKMatrix.MakeScale(w / 1920f, h / 1080f)); for (int i = 0; i < size; i++) { gc.GetSection(DrawType.DAILY).Draw(c, daily); gc.GetSection(DrawType.FEATURED).Draw(c, weeklies[i]); gc.GetSection(DrawType.FEATURED).InitializeCategory(c, weeklies[i], sizes, i + 1, 0); float tickAmt = 1 / 150f; for (int j = 0; j < 150; j++) { gc.GetSection(DrawType.DAILY).DrawBorder(c, daily, j); gc.GetSection(DrawType.FEATURED).DrawBorder(c, weeklies[i], j + i * 150); stream.EncodeFrame(); gc.GetSection(DrawType.FEATURED).TickCategory(c, weeklies[i], sizes, j * tickAmt, tickAmt); } } } /* * using var bmp = new SKBitmap(1280, 720, SKColorType.Rgba8888, SKAlphaType.Opaque); * using var stream = new VideoOutputStream(bmp, 30, 1024 * 1024 * 4, output, true); * using var c = new SKCanvas(bmp); */ }
public static SKMatrix ToSKMatrix(this SvgViewBox svgViewBox, SvgAspectRatio svgAspectRatio, float x, float y, float width, float height) { if (svgViewBox.Equals(SvgViewBox.Empty)) { return(SKMatrix.MakeTranslation(x, y)); } float fScaleX = width / svgViewBox.Width; float fScaleY = height / svgViewBox.Height; float fMinX = -svgViewBox.MinX * fScaleX; float fMinY = -svgViewBox.MinY * fScaleY; if (svgAspectRatio == null) { svgAspectRatio = new SvgAspectRatio(SvgPreserveAspectRatio.xMidYMid); } if (svgAspectRatio.Align != SvgPreserveAspectRatio.none) { if (svgAspectRatio.Slice) { fScaleX = Math.Max(fScaleX, fScaleY); fScaleY = Math.Max(fScaleX, fScaleY); } else { fScaleX = Math.Min(fScaleX, fScaleY); fScaleY = Math.Min(fScaleX, fScaleY); } float fViewMidX = (svgViewBox.Width / 2) * fScaleX; float fViewMidY = (svgViewBox.Height / 2) * fScaleY; float fMidX = width / 2; float fMidY = height / 2; fMinX = -svgViewBox.MinX * fScaleX; fMinY = -svgViewBox.MinY * fScaleY; switch (svgAspectRatio.Align) { case SvgPreserveAspectRatio.xMinYMin: break; case SvgPreserveAspectRatio.xMidYMin: fMinX += fMidX - fViewMidX; break; case SvgPreserveAspectRatio.xMaxYMin: fMinX += width - svgViewBox.Width * fScaleX; break; case SvgPreserveAspectRatio.xMinYMid: fMinY += fMidY - fViewMidY; break; case SvgPreserveAspectRatio.xMidYMid: fMinX += fMidX - fViewMidX; fMinY += fMidY - fViewMidY; break; case SvgPreserveAspectRatio.xMaxYMid: fMinX += width - svgViewBox.Width * fScaleX; fMinY += fMidY - fViewMidY; break; case SvgPreserveAspectRatio.xMinYMax: fMinY += height - svgViewBox.Height * fScaleY; break; case SvgPreserveAspectRatio.xMidYMax: fMinX += fMidX - fViewMidX; fMinY += height - svgViewBox.Height * fScaleY; break; case SvgPreserveAspectRatio.xMaxYMax: fMinX += width - svgViewBox.Width * fScaleX; fMinY += height - svgViewBox.Height * fScaleY; break; default: break; } } var skMatrixTotal = SKMatrix.MakeIdentity(); var skMatrixXY = SKMatrix.MakeTranslation(x, y); SKMatrix.PreConcat(ref skMatrixTotal, ref skMatrixXY); var skMatrixMinXY = SKMatrix.MakeTranslation(fMinX, fMinY); SKMatrix.PreConcat(ref skMatrixTotal, ref skMatrixMinXY); var skMatrixScale = SKMatrix.MakeScale(fScaleX, fScaleY); SKMatrix.PreConcat(ref skMatrixTotal, ref skMatrixScale); return(skMatrixTotal); }
public void DrawPath(SKPath path, Point point, SKPaint paint) { path.Transform(SKMatrix.MakeScale(Scale, Scale)); Canvas.DrawPath(path, paint); }
private SKBitmap BuildThumbCollageBitmap(string[] paths, int width, int height) { var bitmap = new SKBitmap(width, height); using (var canvas = new SKCanvas(bitmap)) { canvas.Clear(SKColors.Black); // determine sizes for each image that will composited into the final image var iSlice = Convert.ToInt32(width * 0.23475); int iTrans = Convert.ToInt32(height * .25); int iHeight = Convert.ToInt32(height * .70); var horizontalImagePadding = Convert.ToInt32(width * 0.0125); var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111); int imageIndex = 0; for (int i = 0; i < 4; i++) { SKCodecOrigin origin; using (var currentBitmap = SkiaEncoder.Decode(paths[imageIndex], false, _fileSystem, out origin)) { // resize to the same aspect as the original int iWidth = (int)Math.Abs(iHeight * currentBitmap.Width / currentBitmap.Height); using (var resizeBitmap = new SKBitmap(iWidth, iHeight, currentBitmap.ColorType, currentBitmap.AlphaType)) { currentBitmap.Resize(resizeBitmap, SKBitmapResizeMethod.Lanczos3); // determine how much to crop int ix = (int)Math.Abs((iWidth - iSlice) / 2); using (var image = SKImage.FromBitmap(resizeBitmap)) { // crop image using (var subset = image.Subset(SKRectI.Create(ix, 0, iSlice, iHeight))) { // draw image onto canvas canvas.DrawImage(subset, (horizontalImagePadding * (i + 1)) + (iSlice * i), verticalSpacing); using (var croppedBitmap = SKBitmap.FromImage(subset)) { // create reflection of image below the drawn image using (var reflectionBitmap = new SKBitmap(croppedBitmap.Width, croppedBitmap.Height / 2, croppedBitmap.ColorType, croppedBitmap.AlphaType)) { // resize to half height croppedBitmap.Resize(reflectionBitmap, SKBitmapResizeMethod.Lanczos3); using (var flippedBitmap = new SKBitmap(reflectionBitmap.Width, reflectionBitmap.Height, reflectionBitmap.ColorType, reflectionBitmap.AlphaType)) { using (var flippedCanvas = new SKCanvas(flippedBitmap)) { // flip image vertically var matrix = SKMatrix.MakeScale(1, -1); matrix.SetScaleTranslate(1, -1, 0, flippedBitmap.Height); flippedCanvas.SetMatrix(matrix); flippedCanvas.DrawBitmap(reflectionBitmap, 0, 0); flippedCanvas.ResetMatrix(); // create gradient to make image appear as a reflection var remainingHeight = height - (iHeight + (2 * verticalSpacing)); flippedCanvas.ClipRect(SKRect.Create(reflectionBitmap.Width, remainingHeight)); using (var gradient = new SKPaint()) { gradient.IsAntialias = true; gradient.BlendMode = SKBlendMode.SrcOver; gradient.Shader = SKShader.CreateLinearGradient(new SKPoint(0, 0), new SKPoint(0, remainingHeight), new[] { new SKColor(0, 0, 0, 128), new SKColor(0, 0, 0, 208), new SKColor(0, 0, 0, 240), new SKColor(0, 0, 0, 255) }, null, SKShaderTileMode.Clamp); flippedCanvas.DrawPaint(gradient); } // finally draw reflection onto canvas canvas.DrawBitmap(flippedBitmap, (horizontalImagePadding * (i + 1)) + (iSlice * i), iHeight + (2 * verticalSpacing)); } } } } } } } } imageIndex++; if (imageIndex >= paths.Length) { imageIndex = 0; } } } return(bitmap); }
public async Task <DataResolverResult> Resolve(string identifier, TaskParameter parameters, CancellationToken token) { ImageSource source = parameters.Source; if (!string.IsNullOrWhiteSpace(parameters.LoadingPlaceholderPath) && parameters.LoadingPlaceholderPath == identifier) { source = parameters.LoadingPlaceholderSource; } else if (!string.IsNullOrWhiteSpace(parameters.ErrorPlaceholderPath) && parameters.ErrorPlaceholderPath == identifier) { source = parameters.ErrorPlaceholderSource; } var resolvedData = await(Configuration.DataResolverFactory ?? new DataResolverFactory()) .GetResolver(identifier, source, parameters, Configuration) .Resolve(identifier, parameters, token).ConfigureAwait(false); if (resolvedData?.Stream == null) { throw new FileNotFoundException(identifier); } var svg = new SKSvg() { ThrowOnUnsupportedElement = false, }; SKPicture picture; if (ReplaceStringMap == null || ReplaceStringMap.Count == 0) { using (var svgStream = resolvedData.Stream) { picture = svg.Load(svgStream); } } else { using (var svgStream = resolvedData.Stream) using (var reader = new StreamReader(svgStream)) { var inputString = await reader.ReadToEndAsync(); foreach (var map in ReplaceStringMap .Where(v => v.Key.StartsWith("regex:"))) { inputString = Regex.Replace(inputString, map.Key.Substring(6), map.Value); } var builder = new StringBuilder(inputString); foreach (var map in ReplaceStringMap .Where(v => !v.Key.StartsWith("regex:", StringComparison.OrdinalIgnoreCase))) { builder.Replace(map.Key, map.Value); } using (var svgFinalStream = new MemoryStream(Encoding.UTF8.GetBytes(builder.ToString()))) { picture = svg.Load(svgFinalStream); } } } double sizeX = 0; double sizeY = 0; if (VectorWidth <= 0 && VectorHeight <= 0) { if (picture.CullRect.Width > 0) { sizeX = picture.CullRect.Width; } else { sizeX = 300; } if (picture.CullRect.Height > 0) { sizeY = picture.CullRect.Height; } else { sizeY = 300; } } else if (VectorWidth > 0 && VectorHeight > 0) { sizeX = VectorWidth; sizeY = VectorHeight; } else if (VectorWidth > 0) { sizeX = VectorWidth; sizeY = (VectorWidth / picture.CullRect.Width) * picture.CullRect.Height; } else { sizeX = (VectorHeight / picture.CullRect.Height) * picture.CullRect.Width; sizeY = VectorHeight; } if (UseDipUnits) { sizeX = sizeX.DpToPixels(); sizeY = sizeY.DpToPixels(); } resolvedData.ImageInformation.SetType(ImageInformation.ImageType.SVG); using (var bitmap = new SKBitmap(new SKImageInfo((int)sizeX, (int)sizeY))) using (var canvas = new SKCanvas(bitmap)) using (var paint = new SKPaint()) { canvas.Clear(SKColors.Transparent); float scaleX = (float)sizeX / picture.CullRect.Width; float scaleY = (float)sizeY / picture.CullRect.Height; var matrix = SKMatrix.MakeScale(scaleX, scaleY); canvas.DrawPicture(picture, ref matrix, paint); canvas.Flush(); #if __IOS__ var info = bitmap.Info; CGImage cgImage; IntPtr size; using (var provider = new CGDataProvider(bitmap.GetPixels(out size), size.ToInt32())) using (var colorSpace = CGColorSpace.CreateDeviceRGB()) using (cgImage = new CGImage(info.Width, info.Height, 8, info.BitsPerPixel, info.RowBytes, colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big, provider, null, false, CGColorRenderingIntent.Default)) { IDecodedImage <object> container = new DecodedImage <object>() { Image = new UIImage(cgImage), }; return(new DataResolverResult(container, resolvedData.LoadingResult, resolvedData.ImageInformation)); } #elif __MACOS__ var info = bitmap.Info; CGImage cgImage; IntPtr size; using (var provider = new CGDataProvider(bitmap.GetPixels(out size), size.ToInt32())) using (var colorSpace = CGColorSpace.CreateDeviceRGB()) using (cgImage = new CGImage(info.Width, info.Height, 8, info.BitsPerPixel, info.RowBytes, colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big, provider, null, false, CGColorRenderingIntent.Default)) { IDecodedImage <object> container = new DecodedImage <object>() { Image = new NSImage(cgImage, CGSize.Empty), }; return(new DataResolverResult(container, resolvedData.LoadingResult, resolvedData.ImageInformation)); } #elif __ANDROID__ using (var skiaPixmap = bitmap.PeekPixels()) { var info = skiaPixmap.Info; // destination values var config = Bitmap.Config.Argb8888; var dstInfo = new SKImageInfo(info.Width, info.Height); // try keep the pixel format if we can switch (info.ColorType) { case SKColorType.Alpha8: config = Bitmap.Config.Alpha8; dstInfo.ColorType = SKColorType.Alpha8; break; case SKColorType.Rgb565: config = Bitmap.Config.Rgb565; dstInfo.ColorType = SKColorType.Rgb565; dstInfo.AlphaType = SKAlphaType.Opaque; break; case SKColorType.Argb4444: config = Bitmap.Config.Argb4444; dstInfo.ColorType = SKColorType.Argb4444; break; } // destination bitmap var bmp = Bitmap.CreateBitmap(info.Width, info.Height, config); var ptr = bmp.LockPixels(); // copy var success = skiaPixmap.ReadPixels(dstInfo, ptr, dstInfo.RowBytes); // confirm bmp.UnlockPixels(); if (!success) { bmp.Recycle(); bmp.Dispose(); bmp = null; } IDecodedImage <object> container = new DecodedImage <object>() { Image = bmp, }; return(new DataResolverResult(container, resolvedData.LoadingResult, resolvedData.ImageInformation)); } #elif __WINDOWS__ if (parameters.Transformations == null || parameters.Transformations.Count == 0) { WriteableBitmap writeableBitmap = null; await Configuration.MainThreadDispatcher.PostAsync(async() => { using (var skiaImage = SKImage.FromPixels(bitmap.PeekPixels())) { var info = new SKImageInfo(skiaImage.Width, skiaImage.Height); writeableBitmap = new WriteableBitmap(info.Width, info.Height); var buffer = writeableBitmap.PixelBuffer as IBufferByteAccess; if (buffer == null) { throw new InvalidCastException("Unable to convert WriteableBitmap.PixelBuffer to IBufferByteAccess."); } IntPtr ptr; var hr = buffer.Buffer(out ptr); if (hr < 0) { throw new InvalidCastException("Unable to retrieve pixel address from WriteableBitmap.PixelBuffer."); } using (var pixmap = new SKPixmap(info, ptr)) { skiaImage.ReadPixels(pixmap, 0, 0); } writeableBitmap.Invalidate(); } }); IDecodedImage <object> container = new DecodedImage <object>() { Image = writeableBitmap, }; return(new DataResolverResult(container, resolvedData.LoadingResult, resolvedData.ImageInformation)); } #endif lock (_encodingLock) { using (var image = SKImage.FromBitmap(bitmap)) //using (var data = image.Encode(SKImageEncodeFormat.Png, 100)) //TODO disabled because of https://github.com/mono/SkiaSharp/issues/285 using (var data = image.Encode()) { var stream = new MemoryStream(); data.SaveTo(stream); stream.Position = 0; return(new DataResolverResult(stream, resolvedData.LoadingResult, resolvedData.ImageInformation)); } } } }
public override void PostLayout(bool IsTall, Grid grid, Controller GameController, IPlatformFoundry GameFoundry, IPage SourcePage) { Player PC = GameController.CurrentState.Player; // Calories if (GameController.GetCurrentPage().SubType == GameState.PageSubType.Dinner) { grid.Children.Add(_Text("Calories"), 1, 10, 4, 6); View CalorieView = ImageGradient.AsView( 0, PC.TargetCalories, PC.TargetCalories * 2, PC.Calories, true, false ); grid.Children.Add(CalorieView, 10, 29, 4, 6); SortedDictionary <float, SKColor> MicroNutrients = new SortedDictionary <float, SKColor>(); SortedDictionary <float, SKColor> MicroPotential = new SortedDictionary <float, SKColor>(); SortedDictionary <float, SKColor> MacroNutrients = new SortedDictionary <float, SKColor>(); float microNut = 0f; float microPot = 0f; float macroNut = 0f; foreach (KeyValuePair <Nutrient, NutrientAmount> kvp in PC.Nutrients) { FlorineSkiaNutrient AdjNut = new FlorineSkiaNutrient(kvp.Key); float curRatio = kvp.Key.RatioRDV(kvp.Value); switch (kvp.Key.Class) { case Nutrient.NutrientType.Macro: if (curRatio > 2f) { curRatio = 2f; } if (curRatio <= 0f) { continue; } curRatio /= 8f; macroNut += curRatio; MacroNutrients.Add(macroNut, AdjNut.RingColor); break; case Nutrient.NutrientType.Mineral: case Nutrient.NutrientType.Vitamin: if (curRatio > 1f) { curRatio = 1f; } float fRestRatio = float.NaN; if (curRatio < 1f) { fRestRatio = 1f - curRatio; fRestRatio /= 7f; } curRatio /= 7f; microPot += 1f / 7f; if (curRatio > float.Epsilon) { microNut += curRatio; MicroNutrients.Add(microNut, AdjNut.RingColor); } if (!float.IsNaN(fRestRatio)) { microNut += fRestRatio; MicroNutrients.Add(microNut, SKColors.Transparent); } SKColor newCol = new SKColor( AdjNut.RingColor.Red, AdjNut.RingColor.Green, AdjNut.RingColor.Blue, 80 ); MicroPotential.Add(microPot, newCol); break; } } grid.Children.Add(_Text("Vitamins"), 1, 10, 6, 8); //grid.Children.Add(ImageGradient.AsDivBar(WhiteBar), 20, 29, 6, 8); grid.Children.Add(ImageGradient.AsDivBar(MicroPotential), 10, 29, 6, 8); float gridSize = 5; grid.Children.Add(ImageGradient.AsDivBar(MicroPotential, new SKPaint() { PathEffect = SKPathEffect.Create2DLine(1, MatrixMultiply(SKMatrix.MakeScale(gridSize, gridSize), SKMatrix.MakeRotationDegrees(45))), Style = SKPaintStyle.Stroke, StrokeWidth = 1, Color = new SKColor(0, 0, 0, 20) }), 10, 29, 6, 8); grid.Children.Add(ImageGradient.AsDivBar(MicroPotential, new SKPaint() { PathEffect = SKPathEffect.Create2DLine(1, MatrixMultiply(SKMatrix.MakeScale(gridSize, gridSize), SKMatrix.MakeRotationDegrees(-45))), Style = SKPaintStyle.Stroke, StrokeWidth = 1, Color = new SKColor(0, 0, 0, 20) }), 10, 29, 6, 8); grid.Children.Add(ImageGradient.AsDivBar(MicroNutrients), 10, 29, 6, 8); grid.Children.Add(_Text("Nutrients"), 1, 10, 8, 10); grid.Children.Add(ImageGradient.AsDivBar(MacroNutrients), 10, 29, 8, 10); } if (GameController.GetCurrentPage().SubType == GameState.PageSubType.Lunch) { IGameOptionSet iActivities = GameController.GetCurrentPage().AppliedOptions; int Amount = 0; foreach (IGameOption act in iActivities) { Activity mainAct = act as Activity; if (null != mainAct) { Amount += mainAct.Pay; } if (null != act.SubOptions) { foreach (IGameOption subopt in act.SubOptions) { Activity subAct = subopt as Activity; if (subAct != null) { Amount += subAct.Pay; } } } } if (Amount != 0) { View moneyGrid = MoneyView.RenderView(Amount); grid.Children.Add(moneyGrid, 10, 20, 15, 18); } } else if (GameController.GetCurrentPage().SubType == GameState.PageSubType.Dinner) { View BackView = new FlorineSkiaCVWrap(new FlOval() { backgroundColor = new SKPaint() { Color = new SKColor(0, 80, 190, 230) }, Shape = FlOval.OvalType.Rectangle, ovalRatio = float.NaN, innerHighlight = new SKColor(100, 250, 250, 255), }); View moneyGrid = MoneyView.RenderView(PC.Money, false); View HappinessGrid = Happiness.RenderView(PC.Happiness, false); View TotalText = new FlorineSkiaCVWrap(new ImageText("Total") { FontSize = 48f, Overflow = ImageText.WrapType.None }); View tdBackView = new FlorineSkiaCVWrap(new FlOval() { backgroundColor = new SKPaint() { Color = new SKColor(0, 80, 190, 230) }, Shape = FlOval.OvalType.Rectangle, ovalRatio = float.NaN, innerHighlight = new SKColor(100, 250, 250, 255), }); View tdmoneyGrid = MoneyView.RenderView(PC.MoneyToDate, false); View tdHappinessGrid = Happiness.RenderView(PC.HappinessToDate, false); View tdTotalText = new FlorineSkiaCVWrap(new ImageText("Today") { FontSize = 48f, Overflow = ImageText.WrapType.None }); int TotalY = 13; int TodayY = 10; //grid.Children.Add(BackView, 0, 30, 10, 14); grid.Children.Add(TotalText, 2, 9, TotalY + 1, TotalY + 3); grid.Children.Add(moneyGrid, 8, 17, TotalY, TotalY + 3); grid.Children.Add(HappinessGrid, 17, 28, TotalY, TotalY + 3); //grid.Children.Add(tdBackView, 0, 30, 14, 18); grid.Children.Add(tdTotalText, 2, 9, TodayY + 1, TodayY + 3); grid.Children.Add(tdmoneyGrid, 8, 17, TodayY, TodayY + 3); grid.Children.Add(tdHappinessGrid, 17, 28, TodayY, TodayY + 3); } int EnergyY = 20; int FocusY = EnergyY + 3; grid.Children.Add(_Text("Energy"), 15, 20, EnergyY, EnergyY + 2); grid.Children.Add( ImageGradient.AsView( 0.0, 100.0, 100.0, PC.Energy, false, true ), 20, 29, EnergyY, EnergyY + 2 ); grid.Children.Add(_Text("Focus"), 15, 20, FocusY, FocusY + 2); grid.Children.Add( ImageGradient.AsView( 0.0, 100.0, 100.0, PC.Focus, false, true ), 20, 29, FocusY, FocusY + 2 ); base.PostLayout(IsTall, grid, GameController, GameFoundry, SourcePage); }
public static void Draw(SKCanvas canvas, IViewport viewport, IStyle style, IFeature feature, IGeometry geometry, float opacity, SymbolCache symbolCache = null) { if (style is LabelStyle) { var worldCenter = geometry.GetBoundingBox().GetCentroid(); var center = viewport.WorldToScreen(worldCenter); LabelRenderer.Draw(canvas, (LabelStyle)style, feature, (float)center.X, (float)center.Y, opacity); } else if (style is StyleCollection styleCollection) { foreach (var s in styleCollection) { Draw(canvas, viewport, s, feature, geometry, opacity, symbolCache); } } else { var polygon = (Polygon)geometry; float lineWidth = 1; var lineColor = Color.Black; // default var fillColor = Color.Gray; // default var strokeCap = PenStrokeCap.Butt; // default var strokeJoin = StrokeJoin.Miter; // default var strokeMiterLimit = 4f; // default var strokeStyle = PenStyle.Solid; // default float[] dashArray = null; // default var vectorStyle = style as VectorStyle; if (vectorStyle != null) { lineWidth = (float)vectorStyle.Outline.Width; lineColor = vectorStyle.Outline.Color; strokeCap = vectorStyle.Outline.PenStrokeCap; strokeJoin = vectorStyle.Outline.StrokeJoin; strokeMiterLimit = vectorStyle.Outline.StrokeMiterLimit; strokeStyle = vectorStyle.Outline.PenStyle; dashArray = vectorStyle.Outline.DashArray; fillColor = vectorStyle.Fill?.Color; } using (var path = polygon.ToSkiaPath(viewport, canvas.LocalClipBounds, lineWidth)) { // Is there a FillStyle? if (vectorStyle.Fill?.FillStyle == FillStyle.Solid) { PaintFill.StrokeWidth = lineWidth; PaintFill.Style = SKPaintStyle.Fill; PaintFill.PathEffect = null; PaintFill.Shader = null; PaintFill.Color = fillColor.ToSkia(opacity); canvas.DrawPath(path, PaintFill); } else { PaintFill.StrokeWidth = 1; PaintFill.Style = SKPaintStyle.Stroke; PaintFill.Shader = null; PaintFill.Color = fillColor.ToSkia(opacity); float scale = 10.0f; SKPath fillPath = new SKPath(); SKMatrix matrix = SKMatrix.MakeScale(scale, scale); switch (vectorStyle.Fill?.FillStyle) { case FillStyle.Cross: fillPath.MoveTo(scale * 0.8f, scale * 0.8f); fillPath.LineTo(0, 0); fillPath.MoveTo(0, scale * 0.8f); fillPath.LineTo(scale * 0.8f, 0); PaintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.DiagonalCross: fillPath.MoveTo(scale, scale); fillPath.LineTo(0, 0); fillPath.MoveTo(0, scale); fillPath.LineTo(scale, 0); PaintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.BackwardDiagonal: fillPath.MoveTo(0, scale); fillPath.LineTo(scale, 0); PaintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.ForwardDiagonal: fillPath.MoveTo(scale, scale); fillPath.LineTo(0, 0); PaintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.Dotted: PaintFill.Style = SKPaintStyle.StrokeAndFill; fillPath.AddCircle(scale * 0.5f, scale * 0.5f, scale * 0.35f); PaintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.Horizontal: fillPath.MoveTo(0, scale * 0.5f); fillPath.LineTo(scale, scale * 0.5f); PaintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.Vertical: fillPath.MoveTo(scale * 0.5f, 0); fillPath.LineTo(scale * 0.5f, scale); PaintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.Bitmap: PaintFill.Style = SKPaintStyle.Fill; var image = GetImage(symbolCache, vectorStyle.Fill.BitmapId); if (image != null) { PaintFill.Shader = image.ToShader(SKShaderTileMode.Repeat, SKShaderTileMode.Repeat); } break; case FillStyle.BitmapRotated: PaintFill.Style = SKPaintStyle.Fill; image = GetImage(symbolCache, vectorStyle.Fill.BitmapId); if (image != null) { PaintFill.Shader = image.ToShader(SKShaderTileMode.Repeat, SKShaderTileMode.Repeat, SKMatrix.MakeRotation((float)(viewport.Rotation * System.Math.PI / 180.0f), image.Width >> 1, image.Height >> 1)); } break; default: PaintFill.PathEffect = null; break; } // Do this, because if not, path isn't filled complete using (new SKAutoCanvasRestore(canvas)) { canvas.ClipPath(path); var bounds = path.Bounds; // Make sure, that the brush starts with the correct position var inflate = ((int)path.Bounds.Width * 0.3f / scale) * scale; bounds.Inflate(inflate, inflate); // Draw rect with bigger size, which is clipped by path canvas.DrawRect(bounds, PaintFill); } } PaintStroke.Style = SKPaintStyle.Stroke; PaintStroke.StrokeWidth = lineWidth; PaintStroke.Color = lineColor.ToSkia(opacity); PaintStroke.StrokeCap = strokeCap.ToSkia(); PaintStroke.StrokeJoin = strokeJoin.ToSkia(); PaintStroke.StrokeMiter = strokeMiterLimit; if (strokeStyle != PenStyle.Solid) { PaintStroke.PathEffect = strokeStyle.ToSkia(lineWidth, dashArray); } else { PaintStroke.PathEffect = null; } canvas.DrawPath(path, PaintStroke); } } }
public async Task <Tuple <Stream, LoadingResult, ImageInformation> > Resolve(string identifier, TaskParameter parameters, CancellationToken token) { ImageSource source = parameters.Source; if (!string.IsNullOrWhiteSpace(parameters.LoadingPlaceholderPath) && parameters.LoadingPlaceholderPath == identifier) { source = parameters.LoadingPlaceholderSource; } else if (!string.IsNullOrWhiteSpace(parameters.ErrorPlaceholderPath) && parameters.ErrorPlaceholderPath == identifier) { source = parameters.ErrorPlaceholderSource; } var resolvedData = await(Configuration.DataResolverFactory ?? new DataResolverFactory()) .GetResolver(identifier, source, parameters, Configuration) .Resolve(identifier, parameters, token).ConfigureAwait(false); if (resolvedData?.Item1 == null) { throw new FileNotFoundException(identifier); } var svg = new SKSvg() { ThrowOnUnsupportedElement = false, }; SKPicture picture; if (ReplaceStringMap == null || ReplaceStringMap.Count == 0) { using (var svgStream = resolvedData.Item1) { picture = svg.Load(resolvedData?.Item1); } } else { using (var svgStream = resolvedData.Item1) using (var reader = new StreamReader(svgStream)) { var builder = new StringBuilder(await reader.ReadToEndAsync()); foreach (var map in ReplaceStringMap) { builder.Replace(map.Key, map.Value); } using (var svgFinalStream = new MemoryStream(Encoding.UTF8.GetBytes(builder.ToString()))) { picture = svg.Load(svgFinalStream); } } } double sizeX = 0; double sizeY = 0; if (VectorWidth == 0 && VectorHeight == 0) { if (picture.CullRect.Width > 0) { sizeX = picture.CullRect.Width; } else { sizeX = 300; } if (picture.CullRect.Height > 0) { sizeY = picture.CullRect.Height; } else { sizeY = 300; } } else if (VectorWidth > 0 && VectorHeight > 0) { sizeX = VectorWidth; sizeY = VectorHeight; } else if (VectorWidth > 0) { sizeX = VectorWidth; sizeY = (VectorWidth / picture.CullRect.Width) * picture.CullRect.Height; } else { sizeX = (VectorHeight / picture.CullRect.Height) * picture.CullRect.Width; sizeY = VectorHeight; } if (UseDipUnits) { #if __ANDROID__ sizeX = sizeX.DpToPixels(); sizeY = sizeY.DpToPixels(); #else sizeX = sizeX.PointsToPixels(); sizeY = sizeY.PointsToPixels(); #endif } using (var bitmap = new SKBitmap(new SKImageInfo((int)sizeX, (int)sizeY))) //using (var bitmap = new SKBitmap((int)sizeX, (int)sizeY)) using (var canvas = new SKCanvas(bitmap)) using (var paint = new SKPaint()) { canvas.Clear(SKColors.Transparent); float scaleX = (float)sizeX / picture.CullRect.Width; float scaleY = (float)sizeY / picture.CullRect.Height; var matrix = SKMatrix.MakeScale(scaleX, scaleY); canvas.DrawPicture(picture, ref matrix, paint); canvas.Flush(); using (var image = SKImage.FromBitmap(bitmap)) //using (var data = image.Encode(SKImageEncodeFormat.Png, 100)) //TODO disabled because of https://github.com/mono/SkiaSharp/issues/285 using (var data = image.Encode()) { var stream = new MemoryStream(); data.SaveTo(stream); stream.Position = 0; resolvedData.Item3.SetType(ImageInformation.ImageType.SVG); return(new Tuple <Stream, LoadingResult, ImageInformation>(stream, resolvedData.Item2, resolvedData.Item3)); } } }
public MaskDrawable(SvgMask svgMask, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes = Attributes.None) : base(svgMask, root, parent) { IgnoreAttributes = ignoreAttributes; IsDrawable = true; if (!IsDrawable) { return; } var maskUnits = svgMask.MaskUnits; var maskContentUnits = svgMask.MaskContentUnits; var xUnit = svgMask.X; var yUnit = svgMask.Y; var widthUnit = svgMask.Width; var heightUnit = svgMask.Height; float x = xUnit.ToDeviceValue(UnitRenderingType.Horizontal, svgMask, skOwnerBounds); float y = yUnit.ToDeviceValue(UnitRenderingType.Vertical, svgMask, skOwnerBounds); float width = widthUnit.ToDeviceValue(UnitRenderingType.Horizontal, svgMask, skOwnerBounds); float height = heightUnit.ToDeviceValue(UnitRenderingType.Vertical, svgMask, skOwnerBounds); if (width <= 0 || height <= 0) { IsDrawable = false; return; } if (maskUnits == SvgCoordinateUnits.ObjectBoundingBox) { if (xUnit.Type != SvgUnitType.Percentage) { x *= skOwnerBounds.Width; } if (yUnit.Type != SvgUnitType.Percentage) { y *= skOwnerBounds.Height; } if (widthUnit.Type != SvgUnitType.Percentage) { width *= skOwnerBounds.Width; } if (heightUnit.Type != SvgUnitType.Percentage) { height *= skOwnerBounds.Height; } x += skOwnerBounds.Left; y += skOwnerBounds.Top; } SKRect skRectTransformed = SKRect.Create(x, y, width, height); var skMatrix = SKMatrix.MakeIdentity(); if (maskContentUnits == SvgCoordinateUnits.ObjectBoundingBox) { var skBoundsTranslateTransform = SKMatrix.MakeTranslation(skOwnerBounds.Left, skOwnerBounds.Top); SKMatrix.PreConcat(ref skMatrix, ref skBoundsTranslateTransform); var skBoundsScaleTransform = SKMatrix.MakeScale(skOwnerBounds.Width, skOwnerBounds.Height); SKMatrix.PreConcat(ref skMatrix, ref skBoundsScaleTransform); } CreateChildren(svgMask, skOwnerBounds, root, this, ignoreAttributes); Overflow = skRectTransformed; IsAntialias = SvgPaintingExtensions.IsAntialias(svgMask); TransformedBounds = skRectTransformed; Transform = skMatrix; Fill = null; Stroke = null; // TODO: Transform _skBounds using _skMatrix. SKMatrix.MapRect(ref Transform, out TransformedBounds, ref TransformedBounds); }