/** * Constructor. * * @param fontDictionary the corresponding dictionary * @throws IOException it something went wrong */ public PdfType1CFont(PdfDirectObject fontDictionary) : base(fontDictionary) { FontDescriptor fd = FontDescriptor; byte[] bytes = null; if (fd != null) { var ff3Stream = fd.FontFile3; if (ff3Stream != null) { bytes = ff3Stream.BaseDataObject.ExtractBody(true).GetBuffer(); if (bytes.Length == 0) { Debug.WriteLine($"error: Invalid data for embedded Type1C font {Name}"); bytes = null; } } } bool fontIsDamaged = false; CFFType1Font cffEmbedded = null; try { if (bytes != null) { // note: this could be an OpenType file, fortunately CFFParser can handle that CFFParser cffParser = new CFFParser(); cffEmbedded = (CFFType1Font)cffParser.Parse(bytes, new FF3ByteSource(fd, bytes))[0]; } } catch (Exception e) { Debug.WriteLine($"error: Can't read the embedded Type1C font {Name} {e}"); fontIsDamaged = true; } isDamaged = fontIsDamaged; cffFont = cffEmbedded; if (cffFont != null) { genericFont = cffFont; isEmbedded = true; } else { FontMapping <BaseFont> mapping = FontMappers.Instance.GetBaseFont(BaseFont, fd); genericFont = mapping.Font; if (mapping.IsFallback) { Debug.WriteLine($"warn: Using fallback font {genericFont.Name} for {BaseFont}"); } isEmbedded = false; } ReadEncoding(); fontMatrixTransform = FontMatrix; fontMatrixTransform = fontMatrixTransform.PreConcat(SKMatrix.CreateScale(1000, 1000)); }
protected override void OnDrawSample(SKCanvas canvas, int width, int height) { canvas.Clear(SKColors.White); var blockSize = 30; // create the path var path = new SKPath(); // the rect must be offset as the path uses the center var rect = SKRect.Create(blockSize / -2, blockSize / -2, blockSize, blockSize); path.AddRect(rect); // move the path around: across 1 block var offsetMatrix = SKMatrix.CreateScale(2 * blockSize, blockSize); // each row, move across a bit / offset offsetMatrix = SKMatrix.Concat(offsetMatrix, SKMatrix.CreateSkew(0.5f, 0)); // create the paint var paint = new SKPaint { PathEffect = SKPathEffect.Create2DPath(offsetMatrix, path), Color = SKColors.LightGray }; // draw a rectangle canvas.DrawRect(SKRect.Create(width + blockSize, height + blockSize), paint); }
protected override void Draw(SKCanvas canvas) { var transformationMatrix = SKMatrix.CreateTranslation(Position.X - 266.75f, Position.Y - 272.15f); var scale = Size.Width / 200.0f; transformationMatrix = transformationMatrix.PostConcat(SKMatrix.CreateScale(scale, scale, Position.X, Position.Y)); var red = SKPath.ParseSvgPathData("M272.1 107.7c38.8-.6 76.3 14 104.4 40.8l77.7-77.7C405 24.6 339.7-.8 272.1 0 169.2 0 75.1 58 28.9 150l90.4 70.1c21.5-64.5 81.8-112.4 152.8-112.4z"); red.Transform(transformationMatrix); var green = SKPath.ParseSvgPathData("M272.1 544.3c73.4 0 135.3-24.1 180.4-65.7l-87.7-68c-24.4 16.6-55.9 26-92.6 26-71 0-131.2-47.9-152.8-112.3H28.9v70.1c46.2 91.9 140.3 149.9 243.2 149.9z"); green.Transform(transformationMatrix); var blue = SKPath.ParseSvgPathData("M533.5 278.4c0-18.5-1.5-37.1-4.7-55.3H272.1v104.8h147c-6.1 33.8-25.7 63.7-54.4 82.7v68h87.7c51.5-47.4 81.1-117.4 81.1-200.2z"); blue.Transform(transformationMatrix); var yellow = SKPath.ParseSvgPathData("M119.3 324.3c-11.4-33.8-11.4-70.4 0-104.2V150H28.9c-38.6 76.9-38.6 167.5 0 244.4l90.4-70.1z"); yellow.Transform(transformationMatrix); canvas.DrawPath(red, _r); canvas.DrawPath(green, _g); canvas.DrawPath(blue, _b); canvas.DrawPath(yellow, _y); }
public void Pinch(GestureState state, float scale, SKPoint origin) { switch (state) { case GestureState.Started: startPinchMatrix = Matrix; startPinchOrigin = origin; totalPinchScale = 1f; break; case GestureState.Running: totalPinchScale *= scale; var pinchTranslation = origin - startPinchOrigin; var canvasTranslation = SKMatrix.CreateTranslation(pinchTranslation.X, pinchTranslation.Y); var canvasScaling = SKMatrix.CreateScale(totalPinchScale, totalPinchScale, origin.X, origin.Y); var canvasCombined = SKMatrix.Identity; SKMatrix.Concat(ref canvasCombined, ref canvasScaling, ref canvasTranslation); SKMatrix.Concat(ref Matrix, ref canvasCombined, ref startPinchMatrix); break; default: startPinchMatrix = SKMatrix.Identity; startPinchOrigin = SKPoint.Empty; totalPinchScale = 1f; break; } }
private static SKMatrix CreateRotationMatrix(IReadOnlyViewport viewport, MRect rect, SKMatrix priorMatrix) { // The front-end sets up the canvas with a matrix based on screen scaling (e.g. retina). // We need to retain that effect by combining our matrix with the incoming matrix. // We'll create four matrices in addition to the incoming matrix. They perform the // zoom scale, focal point offset, user rotation and finally, centering in the screen. var userRotation = SKMatrix.CreateRotationDegrees((float)viewport.Rotation); var focalPointOffset = SKMatrix.CreateTranslation( (float)(rect.Left - viewport.Center.X), (float)(viewport.Center.Y - rect.Top)); var zoomScale = SKMatrix.CreateScale((float)(1.0 / viewport.Resolution), (float)(1.0 / viewport.Resolution)); var centerInScreen = SKMatrix.CreateTranslation((float)(viewport.Width / 2.0), (float)(viewport.Height / 2.0)); // We'll concatenate them like so: incomingMatrix * centerInScreen * userRotation * zoomScale * focalPointOffset var matrix = SKMatrix.Concat(zoomScale, focalPointOffset); matrix = SKMatrix.Concat(userRotation, matrix); matrix = SKMatrix.Concat(centerInScreen, matrix); matrix = SKMatrix.Concat(priorMatrix, matrix); return(matrix); }
protected override void Draw(SKCanvas canvas) { var transformationMatrix = SKMatrix.CreateTranslation(Position.X - 11.5f, Position.Y - 11.5f); var scale = 6.0f / Size.Width; transformationMatrix = transformationMatrix.PostConcat(SKMatrix.CreateScale(scale, scale, Position.X, Position.Y)); var backgroundPath = SKPath.ParseSvgPathData("M0 0h23v23H0z"); backgroundPath.Transform(transformationMatrix); var redSquarePath = SKPath.ParseSvgPathData("M1 1h10v10H1z"); redSquarePath.Transform(transformationMatrix); var greenSquarePath = SKPath.ParseSvgPathData("M12 1h10v10H12z"); greenSquarePath.Transform(transformationMatrix); var blueSquarePath = SKPath.ParseSvgPathData("M1 12h10v10H1z"); blueSquarePath.Transform(transformationMatrix); var yellowSquarePath = SKPath.ParseSvgPathData("M12 12h10v10H12z"); yellowSquarePath.Transform(transformationMatrix); canvas.DrawPath(backgroundPath, _background); canvas.DrawPath(redSquarePath, _r); canvas.DrawPath(greenSquarePath, _g); canvas.DrawPath(blueSquarePath, _b); canvas.DrawPath(yellowSquarePath, _y); }
internal override void Render(SKSurface surface) { foreach (var shape in Shapes) { surface.Canvas.Save(); var visualMatrix = surface.Canvas.TotalMatrix; visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateTranslation(shape.Offset.X, shape.Offset.Y)); if (shape.Scale != new Vector2(1, 1)) { visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateScale(shape.Scale.X, shape.Scale.Y)); } if (shape.RotationAngleInDegrees != 0) { visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateRotationDegrees(shape.RotationAngleInDegrees, shape.CenterPoint.X, shape.CenterPoint.Y)); } if (shape.TransformMatrix != Matrix3x2.Identity) { visualMatrix = visualMatrix.PreConcat(shape.TransformMatrix.ToSKMatrix44().Matrix); } surface.Canvas.SetMatrix(visualMatrix); shape.Render(surface); surface.Canvas.Restore(); } }
internal PdfType1Font(PdfDirectObject baseObject) : base(baseObject) { codeToBytesMap = new Dictionary <int, byte[]>(); var fd = FontDescriptor; Type1Font t1 = null; bool fontIsDamaged = false; if (fd != null) { // a Type1 font may contain a Type1C font var fontFile3 = fd.FontFile3; if (fontFile3 != null) { throw new ArgumentException("Use PDType1CFont for FontFile3"); } // or it may contain a PFB var fontFile = fd.FontFile; if (fontFile != null) { try { t1 = LoadType1Font(fontFile); } catch (DamagedFontException e) { Debug.WriteLine($"warn: Can't read damaged embedded Type1 font {fd.FontName} {e}"); fontIsDamaged = true; } catch (IOException e) { Debug.WriteLine($"error: Can't read the embedded Type1 font {fd.FontName} {e}"); fontIsDamaged = true; } } } isEmbedded = t1 != null; isDamaged = fontIsDamaged; type1font = t1; // find a generic font to use for rendering, could be a .pfb, but might be a .ttf if (type1font != null) { genericFont = type1font; } else { FontMapping <BaseFont> mapping = FontMappers.Instance.GetBaseFont(BaseFont, fd); genericFont = mapping.Font; if (mapping.IsFallback) { Debug.WriteLine($"warn Using fallback font {genericFont.Name} for {BaseFont}"); } } ReadEncoding(); fontMatrixTransform = FontMatrix; fontMatrixTransform = fontMatrixTransform.PreConcat(SKMatrix.CreateScale(1000, 1000)); }
/// <summary> /// Configure paint wrapper for using tile brush. /// </summary> /// <param name="paintWrapper">Paint wrapper.</param> /// <param name="targetSize">Target size.</param> /// <param name="tileBrush">Tile brush to use.</param> /// <param name="tileBrushImage">Tile brush image.</param> private void ConfigureTileBrush(ref PaintWrapper paintWrapper, Size targetSize, ITileBrush tileBrush, IDrawableBitmapImpl tileBrushImage) { var calc = new TileBrushCalculator(tileBrush, tileBrushImage.PixelSize.ToSizeWithDpi(_dpi), targetSize); var intermediate = CreateRenderTarget(calc.IntermediateSize); paintWrapper.AddDisposable(intermediate); using (var context = intermediate.CreateDrawingContext(null)) { var sourceRect = new Rect(tileBrushImage.PixelSize.ToSizeWithDpi(96)); var targetRect = new Rect(tileBrushImage.PixelSize.ToSizeWithDpi(_dpi)); context.Clear(Colors.Transparent); context.PushClip(calc.IntermediateClip); context.Transform = calc.IntermediateTransform; context.DrawBitmap( RefCountable.CreateUnownedNotClonable(tileBrushImage), 1, sourceRect, targetRect, tileBrush.BitmapInterpolationMode); context.PopClip(); } var tileTransform = tileBrush.TileMode != TileMode.None ? SKMatrix.CreateTranslation(-(float)calc.DestinationRect.X, -(float)calc.DestinationRect.Y) : SKMatrix.CreateIdentity(); SKShaderTileMode tileX = tileBrush.TileMode == TileMode.None ? SKShaderTileMode.Clamp : tileBrush.TileMode == TileMode.FlipX || tileBrush.TileMode == TileMode.FlipXY ? SKShaderTileMode.Mirror : SKShaderTileMode.Repeat; SKShaderTileMode tileY = tileBrush.TileMode == TileMode.None ? SKShaderTileMode.Clamp : tileBrush.TileMode == TileMode.FlipY || tileBrush.TileMode == TileMode.FlipXY ? SKShaderTileMode.Mirror : SKShaderTileMode.Repeat; var image = intermediate.SnapshotImage(); paintWrapper.AddDisposable(image); var paintTransform = default(SKMatrix); SKMatrix.Concat( ref paintTransform, tileTransform, SKMatrix.CreateScale((float)(96.0 / _dpi.X), (float)(96.0 / _dpi.Y))); using (var shader = image.ToShader(tileX, tileY, paintTransform)) { paintWrapper.Paint.Shader = shader; } }
private void OnPainting(object sender, SKPaintSurfaceEventArgs e) { var surface = e.Surface; var canvas = surface.Canvas; var width = e.Info.Width; var height = e.Info.Height; // clear the surface canvas.Clear(SKColors.White); // the page is not visible yet if (svg == null) { return; } // calculate the scaling need to fit to screen float canvasMin = Math.Min(width, height); float svgMax = Math.Max(svg.Picture.CullRect.Width, svg.Picture.CullRect.Height); float scale = canvasMin / svgMax; var matrix = SKMatrix.CreateScale(scale, scale); // draw the svg canvas.DrawPicture(svg.Picture, ref matrix); }
public static SKData EncodeSvg(FsPath svgFile, int maxWidht, int maxHeight, SKEncodedImageFormat format = SKEncodedImageFormat.Png) { var svg = new SKSvg(); svg.Load(svgFile.ToString()); if (svg.Picture == null) { return(SKData.Empty); } SKRect svgSize = svg.Picture.CullRect; (int renderWidth, int renderHeight, float scale)sizeData = CalcNewSize(svgSize, maxWidht, maxHeight); var matrix = SKMatrix.CreateScale(sizeData.scale, sizeData.scale); using (SKBitmap bitmap = new SKBitmap(sizeData.renderWidth, sizeData.renderHeight)) { using (SKCanvas canvas = new SKCanvas(bitmap)) { canvas.DrawPicture(svg.Picture, ref matrix); canvas.Flush(); } using (SKImage image = SKImage.FromBitmap(bitmap)) { return(image.Encode(format, 100)); } } }
public void ScaleToMatrixIsCorrect() { var m = SKMatrix.CreateScale(3.5f, 3.5f); var rsm = SKRotationScaleMatrix.CreateScale(3.5f).ToMatrix(); Assert.Equal(m.Values, rsm.Values); }
/// <summary> /// Transform the images ready for download, optionally adding a watermark. /// </summary> /// <param name="input"></param> /// <param name="output"></param> /// <param name="waterMarkText"></param> public void TransformDownloadImageSync(string input, Stream output, IExportSettings config) { using SKImage img = SKImage.FromEncodedData(input); using var bitmap = SKBitmap.FromImage(img); float maxSize = config.MaxImageSize; var resizeFactor = 1f; if (bitmap.Width > maxSize) { resizeFactor = maxSize / bitmap.Width; } else if (bitmap.Height > maxSize) { resizeFactor = maxSize / bitmap.Height; } var targetWidth = (int)Math.Round(bitmap.Width * resizeFactor); var targetHeight = (int)Math.Round(bitmap.Height * resizeFactor); // First create a bitmap the right size. using var toBitmap = new SKBitmap(targetWidth, targetHeight, bitmap.ColorType, bitmap.AlphaType); using var canvas = new SKCanvas(toBitmap); // Draw a bitmap rescaled canvas.SetMatrix(SKMatrix.CreateScale(resizeFactor, resizeFactor)); canvas.DrawBitmap(bitmap, 0, 0); canvas.ResetMatrix(); if (!string.IsNullOrEmpty(config.WatermarkText)) { using var font = SKTypeface.FromFamilyName("Arial"); using var brush = new SKPaint { Typeface = font, TextSize = 64.0f, IsAntialias = true, Color = new SKColor(255, 255, 255, 255) }; var textWidth = brush.MeasureText(config.WatermarkText); var textTargetWidth = targetWidth / 6f; var fontScale = textTargetWidth / textWidth; brush.TextSize *= fontScale; // Offset by text width + 10% var rightOffSet = (textTargetWidth * 1.1f); canvas.DrawText(config.WatermarkText, targetWidth - rightOffSet, targetHeight - brush.TextSize, brush); } canvas.Flush(); using var image = SKImage.FromBitmap(toBitmap); using var data = image.Encode(SKEncodedImageFormat.Jpeg, 90); data.SaveTo(output); }
/// <summary> /// Transform the images ready for download, optionally adding a watermark. /// </summary> /// <param name="input"></param> /// <param name="output"></param> /// <param name="waterMarkText"></param> public void TransformDownloadImage(string input, Stream output, string waterMarkText = null) { float maxSize = 1600f; var resizeFactor = 1f; using var codec = SKCodec.Create(input); using var original = SKBitmap.Decode(codec); // TODO: Use LoadOrientedBitmap here. // First, auto-orient the bitmap using var bitmap = AutoOrient(original, codec.EncodedOrigin); if (bitmap.Width > maxSize) { resizeFactor = maxSize / bitmap.Width; } else if (bitmap.Height > maxSize) { resizeFactor = maxSize / bitmap.Height; } var targetWidth = (int)Math.Round(bitmap.Width * resizeFactor); var targetHeight = (int)Math.Round(bitmap.Height * resizeFactor); // First create a bitmap the right size. using var toBitmap = new SKBitmap(targetWidth, targetHeight, bitmap.ColorType, bitmap.AlphaType); using var canvas = new SKCanvas(toBitmap); // Draw a bitmap rescaled canvas.SetMatrix(SKMatrix.CreateScale(resizeFactor, resizeFactor)); canvas.DrawBitmap(bitmap, 0, 0); canvas.ResetMatrix(); using var font = SKTypeface.FromFamilyName("Arial"); using var brush = new SKPaint { Typeface = font, TextSize = 64.0f, IsAntialias = true, Color = new SKColor(255, 255, 255, 255) }; var textWidth = brush.MeasureText(waterMarkText); var textTargetWidth = targetWidth / 6f; var fontScale = textTargetWidth / textWidth; brush.TextSize *= fontScale; // Offset by text width + 10% var rightOffSet = (textTargetWidth * 1.1f); canvas.DrawText(waterMarkText, targetWidth - rightOffSet, targetHeight - brush.TextSize, brush); canvas.Flush(); using var image = SKImage.FromBitmap(toBitmap); using var data = image.Encode(SKEncodedImageFormat.Jpeg, 90); data.SaveTo(output); }
protected override void OnDrawSample(SKCanvas canvas, int width, int height) { const float textSize = 40; var alignments = new[] { SKTextAlign.Left, SKTextAlign.Center, SKTextAlign.Right }; var warpings = new[] { false, true }; var hOffsets = new[] { 0f, -textSize, textSize }; var vOffsets = new[] { 0f, textSize / 2, textSize }; var text = @"The quick brown fox jumps over the lazy dog!"; canvas.Clear(SKColors.White); var index = animationIndex; // create a circular path using var path = SKPath.ParseSvgPathData("M 32 128 A 64 64 0 1 1 224 128 A 64 64 0 1 1 32 128"); using var paint = new SKPaint { IsAntialias = true, TextAlign = SKTextAlign.Center, TextSize = textSize, StrokeWidth = 2 }; // Fit path in window. path.Transform(SKMatrix.CreateScale(width / 256f, height / 256f)); // Pick text-on-path parameters. var alignment = Pick(alignments, ref index); var hOffset = Pick(hOffsets, ref index); var vOffset = Pick(vOffsets, ref index); var warping = Pick(warpings, ref index); // make sure the canvas is blank canvas.Clear(SKColors.SkyBlue); // draw the parameters paint.TextSize = 16; paint.Color = SKColors.White; paint.TextAlign = SKTextAlign.Left; canvas.DrawText($" Alignment: {alignment}", 0, paint.TextSize, paint); paint.TextAlign = SKTextAlign.Center; canvas.DrawText($"Warping: {(warping ? "on" : "off")}", width / 2f, paint.TextSize, paint); paint.TextAlign = SKTextAlign.Right; canvas.DrawText($"Offset: ({hOffset}, {vOffset}) ", width, paint.TextSize, paint); // draw the path paint.Color = SKColors.Blue; paint.Style = SKPaintStyle.Stroke; paint.TextSize = textSize; canvas.DrawPath(path, paint); // draw the text on the path paint.TextAlign = alignment; paint.Color = SKColors.Black; paint.Style = SKPaintStyle.Fill; canvas.DrawTextOnPath(text, path, new SKPoint(hOffset, vOffset), warping, paint); }
public override void Resize(int width, int height, bool zoomContent = true) { Canvas.ResetMatrix(); base.Resize(width, height, zoomContent); Canvas.SetMatrix( SKMatrix.CreateScale( width / (float)IconsConstants.RenderSize, height / (float)IconsConstants.RenderSize)); }
/// <summary> /// Updates the particle's position and orientation based on the given time /// </summary> /// <para>Call this method first and then <see cref="Paint"/></para> /// <para>This method doesn't need to be called on the UI/Main thread</para> /// <param name="absoluteElapsedMillis"></param> public virtual void Update(long absoluteElapsedMillis, SKSize scale) { // Determine elapsed time since this particles was created var elapsedMillis = absoluteElapsedMillis - _absoluteElapsedMillisPrevious; if (_absoluteElapsedMillisPrevious == 0) { _absoluteElapsedMillisPrevious = absoluteElapsedMillis; return; } _internalAbsoluteMillis += elapsedMillis; _absoluteElapsedMillisPrevious = absoluteElapsedMillis; // Traversed distance = speed x time var dist = TranslationSpeed * _internalAbsoluteMillis * 0.001; // New position var deg2radFactor = 0.0174533; var angle = Direction * deg2radFactor; Position = InitialPosition + new SKPoint { X = (float)(dist * Math.Cos(angle)), Y = (float)(dist * Math.Sin(angle)) }; TransformationMatrix = SKMatrix.CreateTranslation(-Position.X, -Position.Y); // New Scale TransformationMatrix = TransformationMatrix.PostConcat(SKMatrix.CreateScale(scale.Width, scale.Height)); // New Orientation Orientation = InitialOrientation + new SKPoint3 { X = _internalAbsoluteMillis * 0.001f * RotationSpeed.X, Y = _internalAbsoluteMillis * 0.001f * RotationSpeed.Y, Z = _internalAbsoluteMillis * 0.001f * RotationSpeed.Z }; _totalRotationMatrix.SetIdentity(); _xAxisRotationMatrix.SetRotationAboutDegrees(1, 0, 0, Orientation.X); _totalRotationMatrix.PostConcat(_xAxisRotationMatrix); _yAxisRotationMatrix.SetRotationAboutDegrees(0, 1, 0, Orientation.Y); _totalRotationMatrix.PostConcat(_yAxisRotationMatrix); _zAxisRotationMatrix.SetRotationAboutDegrees(0, 0, 1, Orientation.Z); _totalRotationMatrix.PostConcat(_zAxisRotationMatrix); TransformationMatrix = TransformationMatrix.PostConcat(_totalRotationMatrix.Matrix); // Translate back TransformationMatrix = TransformationMatrix.PostConcat(SKMatrix.CreateTranslation(Position.X, Position.Y)); }
SKMatrix CreateMatrix() { SKMatrix matrix = SKMatrix.CreateIdentity(); SKRect drawableBounds = _drawableBounds; float halfStrokeWidth = _skPaint.StrokeWidth / 2; drawableBounds.Left += halfStrokeWidth; drawableBounds.Top += halfStrokeWidth; drawableBounds.Right -= halfStrokeWidth; drawableBounds.Bottom -= halfStrokeWidth; float widthScale = drawableBounds.Width / _pathFillBounds.Width; float heightScale = drawableBounds.Height / _pathFillBounds.Height; switch (_stretch) { case Stretch.None: drawableBounds = _drawableBounds; float adjustX = Math.Min(0, _pathStrokeBounds.Left); float adjustY = Math.Min(0, _pathStrokeBounds.Top); if (adjustX < 0 || adjustY < 0) { matrix = SKMatrix.CreateTranslation(-adjustX, -adjustY); } break; case Stretch.Fill: matrix = SKMatrix.CreateScale(widthScale, heightScale); matrix = matrix.PostConcat( SKMatrix.CreateTranslation(drawableBounds.Left - widthScale * _pathFillBounds.Left, drawableBounds.Top - heightScale * _pathFillBounds.Top)); break; case Stretch.Uniform: float minScale = Math.Min(widthScale, heightScale); matrix = SKMatrix.CreateScale(minScale, minScale); matrix = matrix.PostConcat( SKMatrix.CreateTranslation(drawableBounds.Left - (minScale * _pathFillBounds.Left) + (drawableBounds.Width - (minScale * _pathFillBounds.Width)) / 2, drawableBounds.Top - (minScale * _pathFillBounds.Top) + (drawableBounds.Height - (minScale * _pathFillBounds.Height)) / 2)); break; case Stretch.UniformToFill: float maxScale = Math.Max(widthScale, heightScale); matrix = SKMatrix.CreateScale(maxScale, maxScale); matrix = matrix.PostConcat( SKMatrix.CreateTranslation(drawableBounds.Left - (maxScale * _pathFillBounds.Left), drawableBounds.Top - (maxScale * _pathFillBounds.Top))); break; } return(matrix); }
/** * <summary>Expands the size of this quad stretching around its center.</summary> * <param name="valueX">Expansion's horizontal extent.</param> * <param name="valueY">Expansion's vertical extent.</param> * <returns>This quad.</returns> */ public Quad Inflate(float valueX, float valueY) { SKRect oldBounds = GetBounds(); var matrix = SKMatrix.CreateTranslation(oldBounds.MidX, oldBounds.MidY); matrix = matrix.PreConcat(SKMatrix.CreateScale(1 + valueX * 2 / oldBounds.Width, 1 + valueY * 2 / oldBounds.Height)); matrix = matrix.PreConcat(SKMatrix.CreateTranslation(-(oldBounds.MidX), -(oldBounds.MidY))); pointTopLeft = matrix.MapPoint(pointTopLeft); pointTopRight = matrix.MapPoint(pointTopRight); pointBottomRight = matrix.MapPoint(pointBottomRight); pointBottomLeft = matrix.MapPoint(pointBottomLeft); return(this); }
private protected SKMatrix CreateTransformMatrix(SKRect bounds) { var transform = SKMatrix.Identity; // Translate to origin if (CenterPoint != Vector2.Zero) { transform = SKMatrix.CreateTranslation(-CenterPoint.X, -CenterPoint.Y); } // Scaling if (Scale != Vector2.One) { transform = transform.PostConcat(SKMatrix.CreateScale(Scale.X, Scale.Y)); } // Rotating if (RotationAngle != 0) { transform = transform.PostConcat(SKMatrix.CreateRotation(RotationAngle)); } // Translating if (Offset != Vector2.Zero) { transform = transform.PostConcat(SKMatrix.CreateTranslation(Offset.X, Offset.Y)); } // Translate back if (CenterPoint != Vector2.Zero) { transform = transform.PostConcat(SKMatrix.CreateTranslation(CenterPoint.X, CenterPoint.Y)); } if (!TransformMatrix.IsIdentity) { transform = transform.PostConcat(TransformMatrix.ToSKMatrix()); } var relativeTransform = RelativeTransformMatrix.IsIdentity ? SKMatrix.Identity : RelativeTransformMatrix.ToSKMatrix(); if (!relativeTransform.IsIdentity) { relativeTransform.TransX *= bounds.Width; relativeTransform.TransY *= bounds.Height; transform = transform.PostConcat(relativeTransform); } return(transform); }
private SKMatrix ComputeMatrix(SKSize size, SKPoint ptUL, SKPoint ptUR, SKPoint ptLL, SKPoint?ptLR = null) { // Scale transform SKMatrix S = SKMatrix.CreateScale(1 / size.Width, 1 / size.Height); // Affine transform SKMatrix A = new SKMatrix { ScaleX = ptUR.X - ptUL.X, SkewY = ptUR.Y - ptUL.Y, SkewX = ptLL.X - ptUL.X, ScaleY = ptLL.Y - ptUL.Y, TransX = ptUL.X, TransY = ptUL.Y, Persp2 = 1 }; // Non-Affine transform SKMatrix N = SKMatrix.CreateIdentity(); if (ptLR.HasValue) { SKMatrix inverseA; A.TryInvert(out inverseA); SKPoint abPoint = inverseA.MapPoint(ptLR.Value); float a = abPoint.X; float b = abPoint.Y; float scaleX = a / (a + b - 1); float scaleY = b / (a + b - 1); N = new SKMatrix { ScaleX = scaleX, ScaleY = scaleY, Persp0 = scaleX - 1, Persp1 = scaleY - 1, Persp2 = 1 }; } // Multiply S * N * A SKMatrix result = SKMatrix.CreateIdentity(); SKMatrix.PostConcat(ref result, S); SKMatrix.PostConcat(ref result, N); SKMatrix.PostConcat(ref result, A); return(result); }
public override void PrepareMatrixOffset(bool inverted) { if (!inverted) { MatrixOffset = SKMatrix.Identity.PostConcat(SKMatrix.CreateTranslation(ViewPortHandler.OffsetLeft, ViewPortHandler.ChartHeight - ViewPortHandler.OffsetBottom)); } else { MatrixOffset = SKMatrix .CreateTranslation(ViewPortHandler.OffsetRight - ViewPortHandler.ChartWidth, ViewPortHandler.ChartHeight - ViewPortHandler.OffsetTop) .PostConcat(SKMatrix.CreateScale(-1f, 1f)); } }
private SKMatrix GetScaleMatrix(SKPoint center, float radiusX, float radiusY) { if (radiusX > radiusY) { return(SKMatrix.CreateScale(radiusX / radiusY, 1f, center.X, center.Y)); } if (radiusY > radiusX) { return(SKMatrix.CreateScale(1f, radiusY / radiusX, center.X, center.Y)); } return(SKMatrix.CreateIdentity()); }
protected override void Draw(SKCanvas canvas) { var transformationMatrix = SKMatrix.CreateTranslation(Position.X - 8.0f, Position.Y - 8.0f); var scale = 6.0f / Size.Width; transformationMatrix = transformationMatrix.PostConcat(SKMatrix.CreateScale(scale, scale, Position.X, Position.Y)); var backgroundPath = SKPath.ParseSvgPathData( "M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z"); backgroundPath.Transform(transformationMatrix); canvas.DrawPath(backgroundPath, _paint); }
/// <summary> /// 单指操纵 /// </summary> /// <param name="prevPoint"></param> /// <param name="newPoint"></param> /// <param name="pivotPoint"></param> /// <returns></returns> public SKMatrix OneFingerManipulate(SKPoint prevPoint, SKPoint newPoint, SKPoint pivotPoint) { if (Mode == TouchManipulationMode.None) { return(SKMatrix.CreateIdentity()); } SKMatrix touchMatrix = SKMatrix.CreateIdentity(); SKPoint delta = newPoint - prevPoint; if (Mode == TouchManipulationMode.ScaleDualRotate) // One-finger rotation { SKPoint oldVector = prevPoint - pivotPoint; SKPoint newVector = newPoint - pivotPoint; float scale = Magnitude(newVector) / Magnitude(oldVector); // Avoid rotation if fingers are too close to center if (Magnitude(newVector) > 30 && Magnitude(oldVector) > 30) { float prevAngle = (float)Math.Atan2(oldVector.Y, oldVector.X); float newAngle = (float)Math.Atan2(newVector.Y, newVector.X); // Calculate rotation matrix float angle = newAngle - prevAngle; touchMatrix = SKMatrix.CreateRotation(angle, pivotPoint.X, pivotPoint.Y); // Effectively rotate the old vector float magnitudeRatio = Magnitude(oldVector) / Magnitude(newVector); oldVector.X = magnitudeRatio * newVector.X; oldVector.Y = magnitudeRatio * newVector.Y; // Recalculate delta delta = newVector - oldVector; } if (!float.IsNaN(scale) && !float.IsInfinity(scale)) { var tm = SKMatrix.CreateScale(scale, scale, pivotPoint.X, pivotPoint.Y); touchMatrix.PostConcat(tm); } } // Multiply the rotation matrix by a translation matrix touchMatrix.PostConcat(SKMatrix.CreateTranslation(delta.X, delta.Y)); return(touchMatrix); }
public static MaskDrawable Create(SvgMask svgMask, SKRect skViewport, DrawableBase?parent, IAssetLoader assetLoader, HashSet <Uri>?references, DrawAttributes ignoreAttributes = DrawAttributes.None) { var drawable = new MaskDrawable(assetLoader, references) { Element = svgMask, Parent = parent, IgnoreAttributes = ignoreAttributes, IsDrawable = true }; if (!drawable.IsDrawable) { return(drawable); } var maskUnits = svgMask.MaskUnits; var maskContentUnits = svgMask.MaskContentUnits; var xUnit = svgMask.X; var yUnit = svgMask.Y; var widthUnit = svgMask.Width; var heightUnit = svgMask.Height; // TODO: Pass correct skViewport var skRectTransformed = SvgExtensions.CalculateRect(xUnit, yUnit, widthUnit, heightUnit, maskUnits, skViewport, skViewport, svgMask); if (skRectTransformed is null) { drawable.IsDrawable = false; return(drawable); } var skMatrix = SKMatrix.CreateIdentity(); if (maskContentUnits == SvgCoordinateUnits.ObjectBoundingBox) { var skBoundsTranslateTransform = SKMatrix.CreateTranslation(skViewport.Left, skViewport.Top); skMatrix = skMatrix.PreConcat(skBoundsTranslateTransform); var skBoundsScaleTransform = SKMatrix.CreateScale(skViewport.Width, skViewport.Height); skMatrix = skMatrix.PreConcat(skBoundsScaleTransform); } drawable.CreateChildren(svgMask, skViewport, drawable, assetLoader, references, ignoreAttributes); drawable.Initialize(skRectTransformed.Value, skMatrix); return(drawable); }
/// <summary> /// 2本指での操作 /// </summary> /// <param name="prevPoint"></param> /// <param name="newPoint"></param> /// <param name="pivotPoint"></param> /// <returns></returns> public SKMatrix TwoFingerManipulate(SKPoint prevPoint, SKPoint newPoint, SKPoint pivotPoint) { SKMatrix touchMatrix = SKMatrix.CreateIdentity(); SKPoint oldVector = prevPoint - pivotPoint; SKPoint newVector = newPoint - pivotPoint; if (Mode == TouchManipulationMode.ScaleRotate || Mode == TouchManipulationMode.ScaleDualRotate) { // Find angles from pivot point to touch points float oldAngle = (float)Math.Atan2(oldVector.Y, oldVector.X); float newAngle = (float)Math.Atan2(newVector.Y, newVector.X); // Calculate rotation matrix float angle = newAngle - oldAngle; touchMatrix = SKMatrix.CreateRotation(angle, pivotPoint.X, pivotPoint.Y); // Effectively rotate the old vector float magnitudeRatio = Magnitude(oldVector) / Magnitude(newVector); oldVector.X = magnitudeRatio * newVector.X; oldVector.Y = magnitudeRatio * newVector.Y; } float scaleX = 1; float scaleY = 1; if (Mode == TouchManipulationMode.AnisotropicScale) { scaleX = newVector.X / oldVector.X; scaleY = newVector.Y / oldVector.Y; } else if (Mode == TouchManipulationMode.IsotropicScale || Mode == TouchManipulationMode.ScaleRotate || Mode == TouchManipulationMode.ScaleDualRotate) { scaleX = scaleY = Magnitude(newVector) / Magnitude(oldVector); } if (!float.IsNaN(scaleX) && !float.IsInfinity(scaleX) && !float.IsNaN(scaleY) && !float.IsInfinity(scaleY)) { //SKMatrix.PostConcat(ref touchMatrix, // SKMatrix.CreateScale(scaleX, scaleY, pivotPoint.X, pivotPoint.Y)); touchMatrix = touchMatrix.PostConcat(SKMatrix.CreateScale(scaleX, scaleY, pivotPoint.X, pivotPoint.Y)); } return(touchMatrix); }
public static SKMatrix ToSKMatrix(this IViewport viewport) { var mapCenterX = (float)viewport.Width * 0.5f; var mapCenterY = (float)viewport.Height * 0.5f; var invertedResolution = 1f / (float)viewport.Resolution; var matrix = SKMatrix.CreateScale(invertedResolution, invertedResolution, mapCenterX, mapCenterY); matrix = SKMatrix.Concat(matrix, SKMatrix.CreateScale(1, -1, 0, -mapCenterY)); // As a consequence images will be up side down :( if (viewport.IsRotated) { matrix = SKMatrix.Concat(matrix, SKMatrix.CreateRotationDegrees((float)-viewport.Rotation)); } matrix = SKMatrix.Concat(matrix, SKMatrix.CreateTranslation((float)-viewport.Center.X, (float)-viewport.Center.Y)); return(matrix); }
private void DrawGrid(SKCanvas canvas, double dx, double dy, double zx, double zy) { float gw = (float)_view.Width; float gh = (float)_view.Height; float cw = 15.0f; float ch = 15.0f; canvas.Save(); canvas.Translate((float)dx, (float)dy); canvas.Scale((float)zx, (float)zy); var hlattice = SKMatrix.CreateScale(cw, ch); hlattice = hlattice.PreConcat(SKMatrix.CreateRotation((float)(Math.PI * 0.0 / 180.0))); var vlattice = SKMatrix.CreateScale(cw, ch); vlattice = vlattice.PreConcat(SKMatrix.CreateRotation((float)(Math.PI * 90.0 / 180.0))); using (var heffect = SKPathEffect.Create2DLine((float)(1.0 / zx), hlattice)) using (var veffect = SKPathEffect.Create2DLine((float)(1.0 / zx), vlattice)) using (var hpaint = new SKPaint()) using (var vpaint = new SKPaint()) { hpaint.IsAntialias = false; hpaint.Color = SKColors.LightGray; hpaint.PathEffect = heffect; canvas.DrawRect(SKRect.Create(0.0f, ch, gw, gh - ch), hpaint); vpaint.IsAntialias = false; vpaint.Color = SKColors.LightGray; vpaint.PathEffect = veffect; canvas.DrawRect(SKRect.Create(cw, 0.0f, gw - cw, gh), vpaint); } using (SKPaint strokePaint = new SKPaint()) { strokePaint.IsAntialias = false; strokePaint.StrokeWidth = (float)(1.0 / zx); strokePaint.Color = SKColors.Red; strokePaint.Style = SKPaintStyle.Stroke; canvas.DrawRect(SKRect.Create(0.0f, 0.0f, gw, gh), strokePaint); } canvas.Restore(); }
public static void RenderSvg(SKSvg svg, Stream outStream, SKEncodedImageFormat skFormat, int minSize, int multiplier) { SKRect svgSize = svg.Picture.CullRect; float svgMax = Math.Max(svgSize.Width, svgSize.Height); float canvasMin = minSize * multiplier; float scale = canvasMin / svgMax; var matrix = SKMatrix.CreateScale(scale, scale); var bitmap = new SKBitmap((int)(svgSize.Width * scale), (int)(svgSize.Height * scale)); var canvas = new SKCanvas(bitmap); canvas.Clear(); canvas.DrawPicture(svg.Picture, ref matrix); canvas.Flush(); var image = SKImage.FromBitmap(bitmap); SKData data = image.Encode(skFormat, 100); data.SaveTo(outStream); }