public void Render(SKImage [] images, ColorLinesNG skiaView, SKCanvas canvas) { var destRect = CLReEntity.VirtualToSkiaCoords(this.Verticies, skiaView); SKRect?srcRect = null; // if (this.textureCoords != null) // srcRect = CLReEntity.VirtualToSkiaCoords(this.Verticies, skiaView, this.textureCoords); if (this.Angle != 0.0f) { canvas.Save(); canvas.RotateDegrees(this.Angle, destRect.MidX, destRect.MidY); } if (this.TextureId >= 0) { if (images[this.TextureId] == null) { if (!loadingTextures.Contains(this.TextureId)) { loadingTextures.Add(this.TextureId); Task.Run(async() => { images[this.TextureId] = await skiaView.LoadTexture(this.TextureId); // loadingTextures.Remove(this.TextureId); }); } if (this.Angle != 0.0f) { canvas.Restore(); } return; } if (this.Grayscale) { CLReEntity.CanvasDrawImage(canvas, images[this.TextureId], destRect, srcRect, paintGrayscale); } else if (this.Fill != null) { using (texturePaint.ColorFilter = SKColorFilter.CreateBlendMode(CLReEntity.ColorToSKColor((Color)this.Fill), SKBlendMode.Modulate)) { CLReEntity.CanvasDrawImage(canvas, images[this.TextureId], destRect, srcRect, texturePaint); } } else { CLReEntity.CanvasDrawImage(canvas, images[this.TextureId], destRect); } } else { rectPaint.Color = CLReEntity.ColorToSKColor((Color)this.Fill); canvas.DrawRect(destRect, rectPaint); } if (this.Angle != 0.0f) { canvas.Restore(); } }
private SKRect GetFontInfo() { if (!this.fontInfo.HasValue) { SKRect textSize = SKRect.Empty; font !.MeasureText(this.text, ref textSize); fontInfo = textSize; } return(fontInfo.Value); }
/** * Sets the rotation in degree. * * @param int */ public void SetRotationAngle(int rotationAngle) { this.rotationAngle = rotationAngle; if (this.rotationAngle != 90 && this.rotationAngle != 180 && this.rotationAngle != 270) { this.rotationAngle = 0; } this.rotationAngle %= 360; this.fontInfo = null; }
/** * <summary>Renders the specified content context into an image context.</summary> * <param name="contentContext">Source content context.</param> * <param name="size">Image size expressed in device-space units (that is typically pixels).</param> * <param name="area">Content area to render; <code>null</code> corresponds to the entire * <see cref="IContentContext.Box">content bounding box</see>.</param> * <returns>Image representing the rendered contents.</returns> */ public SKBitmap Render(IContentContext contentContext, SKSize size, SKRect?area) { //TODO:area! var image = new SKBitmap( (int)size.Width, (int)size.Height, SKColorType.Rgba8888, SKAlphaType.Opaque //PixelFormat.Format24bppRgb ); using (var canvas = new SKCanvas(image)) contentContext.Render(canvas, size); return(image); }
public override void PostProcess(SKRect?viewport, SKMatrix totalMatrix) { var element = Element; if (element is null) { return; } var enableMask = !IgnoreAttributes.HasFlag(DrawAttributes.Mask); ClipPath = null; if (enableMask) { MaskDrawable = SvgExtensions.GetSvgElementMask(element, GeometryBounds, new HashSet <Uri>(), AssetLoader, References); if (MaskDrawable is { })
// AllocatePositionedRun public SKPositionedRunBuffer AllocatePositionedRun(SKFont font, int count, SKRect?bounds = null) { if (font == null) { throw new ArgumentNullException(nameof(font)); } SKRunBufferInternal runbuffer; if (bounds is SKRect b) { SkiaApi.sk_textblob_builder_alloc_run_pos(Handle, font.Handle, count, &b, &runbuffer); } else { SkiaApi.sk_textblob_builder_alloc_run_pos(Handle, font.Handle, count, null, &runbuffer); } return(new SKPositionedRunBuffer(runbuffer, count)); }
/** * This will read the required data from the stream. * * @param glyphTable The glyph table this glyph belongs to. * @param data The stream to read the data from. * @param leftSideBearing The left side bearing for this glyph. * @ If there is an error reading the data. */ public void InitData(GlyphTable glyphTable, TTFDataStream data, int leftSideBearing) { numberOfContours = data.ReadSignedShort(); xMin = data.ReadSignedShort(); yMin = data.ReadSignedShort(); xMax = data.ReadSignedShort(); yMax = data.ReadSignedShort(); boundingBox = new SKRect(xMin, yMin, xMax, yMax); if (numberOfContours >= 0) { // create a simple glyph short x0 = (short)(leftSideBearing - xMin); glyphDescription = new GlyfSimpleDescript(numberOfContours, data, x0); } else { // create a composite glyph glyphDescription = new GlyfCompositeDescript(data, glyphTable); } }
public override void PostProcess(SKRect?viewport, SKMatrix totalMatrix) { var element = Element; if (element is null) { return; } var enableOpacity = !IgnoreAttributes.HasFlag(DrawAttributes.Opacity); ClipPath = null; MaskDrawable = null; Opacity = enableOpacity ? SvgExtensions.GetOpacityPaint(element) : null; Filter = null; TotalTransform = totalMatrix.PreConcat(Transform); TransformedBounds = TotalTransform.MapRect(GeometryBounds); foreach (var child in ChildrenDrawables) { child.PostProcess(viewport, totalMatrix); } }
public SKHorizontalRunBuffer AllocateHorizontalRun(SKPaint font, int count, float y, SKRect?bounds) => AllocateHorizontalRun(font, count, y, 0, bounds);
public SKRunBuffer AllocateRun(SKPaint font, int count, float x, float y, SKRect?bounds) => AllocateRun(font, count, x, y, 0, bounds);
public void AddPositionedRun(SKPaint font, ReadOnlySpan <ushort> glyphs, ReadOnlySpan <SKPoint> positions, SKRect?bounds) => AddPositionedRun(font, glyphs, positions, ReadOnlySpan <byte> .Empty, ReadOnlySpan <uint> .Empty, bounds);
public void AddHorizontalRun(SKPaint font, float y, ReadOnlySpan <ushort> glyphs, ReadOnlySpan <float> positions, SKRect?bounds) => AddHorizontalRun(font, y, glyphs, positions, ReadOnlySpan <byte> .Empty, ReadOnlySpan <uint> .Empty, bounds);
public SKPositionedRunBuffer AllocatePositionedRun(SKPaint font, int count, int textByteCount, SKRect?bounds) { if (font == null) { throw new ArgumentNullException(nameof(font)); } using (var lang = new SKString()) { unsafe { SKRunBufferInternal runbuffer; if (bounds is SKRect b) { SkiaApi.sk_textblob_builder_alloc_run_text_pos(Handle, font.Handle, count, textByteCount, lang.Handle, &b, out runbuffer); } else { SkiaApi.sk_textblob_builder_alloc_run_text_pos(Handle, font.Handle, count, textByteCount, lang.Handle, (SKRect *)IntPtr.Zero, out runbuffer); } return(new SKPositionedRunBuffer(runbuffer, count, textByteCount)); } } }
public void AddRun(SKPaint font, float x, float y, ReadOnlySpan <ushort> glyphs, SKRect?bounds) => AddRun(font, x, y, glyphs, ReadOnlySpan <byte> .Empty, ReadOnlySpan <uint> .Empty, bounds);
internal SKTextBlobBuilderRunBuffer AllocateRunHorizontal(SKPaint font, int count, float y, int textByteCount, SKRect?bounds) { if (font == null) { throw new ArgumentNullException(nameof(font)); } using (var lang = new SKString()) { unsafe { SKTextBlobBuilderRunBuffer runbuffer; if (bounds is SKRect b) { SkiaApi.sk_textblob_builder_alloc_run_text_pos_h(Handle, font.Handle, count, y, textByteCount, lang.Handle, &b, out runbuffer); } else { SkiaApi.sk_textblob_builder_alloc_run_text_pos_h(Handle, font.Handle, count, y, textByteCount, lang.Handle, (SKRect *)IntPtr.Zero, out runbuffer); } return(runbuffer); } } }
public SKHorizontalRunBuffer AllocateHorizontalRun(SKPaint font, int count, float y, int textByteCount, SKRect?bounds) { if (font == null) { throw new ArgumentNullException(nameof(font)); } using (var lang = new SKString()) { SKRunBufferInternal runbuffer; if (bounds is SKRect b) { SkiaApi.sk_textblob_builder_alloc_run_text_pos_h(Handle, font.Handle, count, y, textByteCount, lang.Handle, &b, &runbuffer); } else { SkiaApi.sk_textblob_builder_alloc_run_text_pos_h(Handle, font.Handle, count, y, textByteCount, lang.Handle, null, &runbuffer); } return(new SKHorizontalRunBuffer(runbuffer, count, textByteCount)); } }
private static void CanvasDrawImage(SKCanvas canvas, SKImage image, SKRect dest, SKRect?src = null, SKPaint paint = null) { if (src == null) { canvas.DrawImage(image, dest, paint); } else { canvas.DrawImage(image, (SKRect)src, dest, paint); } }
/** * <summary>Renders the specified contents into an image context.</summary> * <param name="contents">Source contents.</param> * <param name="size">Image size expressed in device-space units (that is typically pixels).</param> * <param name="area">Content area to render; <code>null</code> corresponds to the entire * <see cref="IContentContext.Box">content bounding box</see>.</param> * <returns>Image representing the rendered contents.</returns> */ public SKBitmap Render(ContentWrapper contents, SKSize size, SKRect?area) { return(Render(contents.ContentContext, size, area)); }
/** * Sets the text associated to the font. * * @param string text */ public void SetText(string text) { this.text = text; this.fontInfo = null; }
public SKPositionedRunBuffer AllocatePositionedRun(SKPaint font, int count, SKRect?bounds) => AllocatePositionedRun(font, count, 0, bounds);
private void AddRunInternal(SKPaint font, float x, float y, ushort[] glyphs, byte[] utf8Text, uint[] clusters, SKRect?bounds, bool hasText) { if (font == null) { throw new ArgumentNullException(nameof(font)); } if (glyphs == null) { throw new ArgumentNullException(nameof(glyphs)); } if (hasText) { if (utf8Text == null) { throw new ArgumentNullException(nameof(utf8Text)); } if (clusters == null) { throw new ArgumentNullException(nameof(clusters)); } if (glyphs.Length != clusters.Length) { throw new ArgumentException("The number of glyphs and clusters must be the same."); } } var run = AllocateRun(font, glyphs.Length, x, y, hasText ? utf8Text.Length : 0, bounds); run.SetGlyphs(glyphs); if (hasText) { run.SetText(utf8Text); run.SetClusters(clusters); } }
public SKPositionedRunBuffer AllocatePositionedRun(SKPaint font, int count, int textByteCount, SKRect?bounds) { if (font == null) { throw new ArgumentNullException(nameof(font)); } var originalEncoding = font.TextEncoding; try { font.TextEncoding = SKTextEncoding.GlyphId; SKRunBufferInternal runbuffer; if (bounds is SKRect b) { SkiaApi.sk_textblob_builder_alloc_run_text_pos(Handle, font.Handle, count, textByteCount, &b, &runbuffer); } else { SkiaApi.sk_textblob_builder_alloc_run_text_pos(Handle, font.Handle, count, textByteCount, null, &runbuffer); } return(new SKPositionedRunBuffer(runbuffer, count, textByteCount)); } finally { font.TextEncoding = originalEncoding; } }
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); skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixMarkerPoint); var skMatrixAngle = SKMatrix.MakeRotationDegrees(svgMarker.Orient.IsAuto ? fAngle : svgMarker.Orient.Angle); skMarkerMatrix = skMarkerMatrix.PreConcat(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); skMarkerMatrix = skMarkerMatrix.PreConcat(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); skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixTranslateRefXY); var skMatrixScaleXY = SKMatrix.MakeScale(viewBoxToMarkerUnitsScaleX, viewBoxToMarkerUnitsScaleY); skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixScaleXY); } break; case SvgMarkerUnits.UserSpaceOnUse: { var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX, -refY); skMarkerMatrix = skMarkerMatrix.PreConcat(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); Transform = Transform.PreConcat(skMarkerMatrix); Fill = null; Stroke = null; // TODO: Transform _skBounds using _skMatrix. TransformedBounds = Transform.MapRect(TransformedBounds); }
public void AddRun(SKPaint font, float x, float y, ReadOnlySpan <ushort> glyphs, ReadOnlySpan <byte> text, ReadOnlySpan <uint> clusters, SKRect?bounds) { if (font == null) { throw new ArgumentNullException(nameof(font)); } if (glyphs.IsEmpty) { throw new ArgumentNullException(nameof(glyphs)); } if (!text.IsEmpty) { if (clusters.IsEmpty) { throw new ArgumentNullException(nameof(clusters)); } if (glyphs.Length != clusters.Length) { throw new ArgumentException("The number of glyphs and clusters must be the same."); } } var run = AllocateRun(font, glyphs.Length, x, y, text.IsEmpty ? 0 : text.Length, bounds); run.SetGlyphs(glyphs); if (!text.IsEmpty) { run.SetText(text); run.SetClusters(clusters); } }
internal static SKPaint?GetFilterPaint(SvgVisualElement svgVisualElement, SKRect skBounds, SKRect skViewport, IFilterSource filterSource, IAssetLoader assetLoader, HashSet <Uri>?references, out bool isValid, out SKRect?filterClip) { var filter = svgVisualElement.Filter; if (filter is null || IsNone(filter)) { isValid = true; filterClip = default; return(default);