public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKPaint paint) { // For now silently ignore if (context.GrContext == null) { return; } using (Lock()) { if (_textureId == 0) { return; } using (var backendTexture = new GRBackendTexture(PixelSize.Width, PixelSize.Height, false, new GRGlTextureInfo( GlConsts.GL_TEXTURE_2D, (uint)_textureId, (uint)_internalFormat))) using (var surface = SKSurface.Create(context.GrContext, backendTexture, GRSurfaceOrigin.TopLeft, SKColorType.Rgba8888)) { // Again, silently ignore, if something went wrong it's not our fault if (surface == null) { return; } using (var snapshot = surface.Snapshot()) context.Canvas.DrawImage(snapshot, sourceRect, destRect, paint); } } }
/// <inheritdoc /> public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKPaint paint) { using (var image = SnapshotImage()) { context.Canvas.DrawImage(image, sourceRect, destRect, paint); } }
/// <inheritdoc /> public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKPaint paint) { if (sourceRect.Left == 0 && sourceRect.Top == 0 && sourceRect.Size == destRect.Size) { _surface.Canvas.Flush(); _surface.Draw(context.Canvas, destRect.Left, destRect.Top, paint); } else { using (var image = SnapshotImage()) { context.Canvas.DrawImage(image, sourceRect, destRect, paint); } } }
/// <inheritdoc /> public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKPaint paint) { lock (_lock) context.Canvas.DrawBitmap(_bitmap, sourceRect, destRect, paint); }
internal void Draw(DrawingContextImpl context, SKCanvas canvas, SKPoint origin, DrawingContextImpl.PaintWrapper foreground, bool canUseLcdRendering) { /* TODO: This originated from Native code, it might be useful for debugging character positions as * we improve the FormattedText support. Will need to port this to C# obviously. Rmove when * not needed anymore. * * SkPaint dpaint; * ctx->Canvas->save(); * ctx->Canvas->translate(origin.fX, origin.fY); * for (int c = 0; c < Lines.size(); c++) * { * dpaint.setARGB(255, 0, 0, 0); * SkRect rc; * rc.fLeft = 0; * rc.fTop = Lines[c].Top; * rc.fRight = Lines[c].Width; * rc.fBottom = rc.fTop + LineOffset; * ctx->Canvas->drawRect(rc, dpaint); * } * for (int c = 0; c < Length; c++) * { * dpaint.setARGB(255, c % 10 * 125 / 10 + 125, (c * 7) % 10 * 250 / 10, (c * 13) % 10 * 250 / 10); * dpaint.setStyle(SkPaint::kFill_Style); * ctx->Canvas->drawRect(Rects[c], dpaint); * } * ctx->Canvas->restore(); */ using (var paint = _paint.Clone()) { IDisposable currd = null; var currentWrapper = foreground; SKPaint currentPaint = null; try { ApplyWrapperTo(ref currentPaint, foreground, ref currd, paint, canUseLcdRendering); bool hasCusomFGBrushes = _foregroundBrushes.Any(); for (int c = 0; c < _skiaLines.Count; c++) { AvaloniaFormattedTextLine line = _skiaLines[c]; float x = TransformX(origin.X, 0, paint.TextAlign); if (!hasCusomFGBrushes) { var subString = Text.Substring(line.Start, line.Length); canvas.DrawText(subString, x, origin.Y + line.Top + _lineOffset, paint); } else { float currX = x; string subStr; float measure; int len; float factor; switch (paint.TextAlign) { case SKTextAlign.Left: factor = 0; break; case SKTextAlign.Center: factor = 0.5f; break; case SKTextAlign.Right: factor = 1; break; default: throw new ArgumentOutOfRangeException(); } var textLine = Text.Substring(line.Start, line.Length); currX -= textLine.Length == 0 ? 0 : paint.MeasureText(textLine) * factor; for (int i = line.Start; i < line.Start + line.Length;) { var fb = GetNextForegroundBrush(ref line, i, out len); if (fb != null) { //TODO: figure out how to get the brush size currentWrapper = context.CreatePaint(new SKPaint { IsAntialias = true }, fb, new Size()); } else { if (!currentWrapper.Equals(foreground)) { currentWrapper.Dispose(); } currentWrapper = foreground; } subStr = Text.Substring(i, len); measure = paint.MeasureText(subStr); currX += measure * factor; ApplyWrapperTo(ref currentPaint, currentWrapper, ref currd, paint, canUseLcdRendering); canvas.DrawText(subStr, currX, origin.Y + line.Top + _lineOffset, paint); i += len; currX += measure * (1 - factor); } } } } finally { if (!currentWrapper.Equals(foreground)) { currentWrapper.Dispose(); } currd?.Dispose(); } } }
private static SKPaint ApplyWrapperTo(ref DrawingContextImpl.PaintWrapper wrapper, ref IDisposable curr, SKPaint paint) { curr?.Dispose(); curr = wrapper.ApplyTo(paint); return wrapper.Paint; }
internal void Draw(DrawingContextImpl context, SKCanvas canvas, SKPoint origin, DrawingContextImpl.PaintWrapper foreground) { /* TODO: This originated from Native code, it might be useful for debugging character positions as * we improve the FormattedText support. Will need to port this to C# obviously. Rmove when * not needed anymore. SkPaint dpaint; ctx->Canvas->save(); ctx->Canvas->translate(origin.fX, origin.fY); for (int c = 0; c < Lines.size(); c++) { dpaint.setARGB(255, 0, 0, 0); SkRect rc; rc.fLeft = 0; rc.fTop = Lines[c].Top; rc.fRight = Lines[c].Width; rc.fBottom = rc.fTop + LineOffset; ctx->Canvas->drawRect(rc, dpaint); } for (int c = 0; c < Length; c++) { dpaint.setARGB(255, c % 10 * 125 / 10 + 125, (c * 7) % 10 * 250 / 10, (c * 13) % 10 * 250 / 10); dpaint.setStyle(SkPaint::kFill_Style); ctx->Canvas->drawRect(Rects[c], dpaint); } ctx->Canvas->restore(); */ SKPaint paint = _paint; IDisposable currd = null; var currentWrapper = foreground; try { SKPaint currFGPaint = ApplyWrapperTo(ref foreground, ref currd, paint); bool hasCusomFGBrushes = _foregroundBrushes.Any(); for (int c = 0; c < _skiaLines.Count; c++) { AvaloniaFormattedTextLine line = _skiaLines[c]; float x = TransformX(origin.X, 0, paint.TextAlign); if (!hasCusomFGBrushes) { var subString = _text.Substring(line.Start, line.Length); canvas.DrawText(subString, x, origin.Y + line.Top + _lineOffset, paint); } else { float currX = x; string subStr; int len; for (int i = line.Start; i < line.Start + line.Length;) { var fb = GetNextForegroundBrush(ref line, i, out len); if (fb != null) { //TODO: figure out how to get the brush size currentWrapper = context.CreatePaint(fb, new Size()); } else { if (!currentWrapper.Equals(foreground)) currentWrapper.Dispose(); currentWrapper = foreground; } subStr = _text.Substring(i, len); if (currFGPaint != currentWrapper.Paint) { currFGPaint = ApplyWrapperTo(ref currentWrapper, ref currd, paint); } canvas.DrawText(subStr, currX, origin.Y + line.Top + _lineOffset, paint); i += len; currX += paint.MeasureText(subStr); } } } } finally { if (!currentWrapper.Equals(foreground)) currentWrapper.Dispose(); currd?.Dispose(); } }
internal void Draw(DrawingContextImpl context, SKCanvas canvas, SKPoint origin, DrawingContextImpl.PaintWrapper foreground) { /* TODO: This originated from Native code, it might be useful for debugging character positions as * we improve the FormattedText support. Will need to port this to C# obviously. Rmove when * not needed anymore. * * SkPaint dpaint; * ctx->Canvas->save(); * ctx->Canvas->translate(origin.fX, origin.fY); * for (int c = 0; c < Lines.size(); c++) * { * dpaint.setARGB(255, 0, 0, 0); * SkRect rc; * rc.fLeft = 0; * rc.fTop = Lines[c].Top; * rc.fRight = Lines[c].Width; * rc.fBottom = rc.fTop + LineOffset; * ctx->Canvas->drawRect(rc, dpaint); * } * for (int c = 0; c < Length; c++) * { * dpaint.setARGB(255, c % 10 * 125 / 10 + 125, (c * 7) % 10 * 250 / 10, (c * 13) % 10 * 250 / 10); * dpaint.setStyle(SkPaint::kFill_Style); * ctx->Canvas->drawRect(Rects[c], dpaint); * } * ctx->Canvas->restore(); */ SKPaint paint = _paint; IDisposable currd = null; var currentWrapper = foreground; try { SKPaint currFGPaint = ApplyWrapperTo(ref foreground, ref currd, paint); bool hasCusomFGBrushes = _foregroundBrushes.Any(); for (int c = 0; c < _skiaLines.Count; c++) { AvaloniaFormattedTextLine line = _skiaLines[c]; float x = TransformX(origin.X, 0, paint.TextAlign); if (!hasCusomFGBrushes) { var subString = _text.Substring(line.Start, line.Length); canvas.DrawText(subString, x, origin.Y + line.Top + _lineOffset, paint); } else { float currX = x; string subStr; int len; for (int i = line.Start; i < line.Start + line.Length;) { var fb = GetNextForegroundBrush(ref line, i, out len); if (fb != null) { //TODO: figure out how to get the brush size currentWrapper = context.CreatePaint(fb, new Size()); } else { if (!currentWrapper.Equals(foreground)) { currentWrapper.Dispose(); } currentWrapper = foreground; } subStr = _text.Substring(i, len); if (currFGPaint != currentWrapper.Paint) { currFGPaint = ApplyWrapperTo(ref currentWrapper, ref currd, paint); } canvas.DrawText(subStr, currX, origin.Y + line.Top + _lineOffset, paint); i += len; currX += paint.MeasureText(subStr); } } } } finally { if (!currentWrapper.Equals(foreground)) { currentWrapper.Dispose(); } currd?.Dispose(); } }
/// <inheritdoc /> public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKPaint paint) { context.Canvas.DrawImage(_image, sourceRect, destRect, paint); }
public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer) { var session = _surface.BeginDraw(); bool success = false; try { var disp = session.Display; var gl = disp.GlInterface; gl.GetIntegerv(GL_FRAMEBUFFER_BINDING, out var fb); var size = session.Size; var scaling = session.Scaling; if (size.Width <= 0 || size.Height <= 0 || scaling < 0) { session.Dispose(); throw new InvalidOperationException( $"Can't create drawing context for surface with {size} size and {scaling} scaling"); } gl.Viewport(0, 0, size.Width, size.Height); gl.ClearStencil(0); gl.ClearColor(0, 0, 0, 0); gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); lock (_grContext) { _grContext.ResetContext(); GRBackendRenderTarget renderTarget = new GRBackendRenderTarget(size.Width, size.Height, disp.SampleCount, disp.StencilSize, new GRGlFramebufferInfo((uint)fb, GRPixelConfig.Rgba8888.ToGlSizedFormat())); var surface = SKSurface.Create(_grContext, renderTarget, GRSurfaceOrigin.BottomLeft, GRPixelConfig.Rgba8888.ToColorType()); var nfo = new DrawingContextImpl.CreateInfo { GrContext = _grContext, Canvas = surface.Canvas, Dpi = SkiaPlatform.DefaultDpi * scaling, VisualBrushRenderer = visualBrushRenderer, DisableTextLcdRendering = true }; var ctx = new DrawingContextImpl(nfo, Disposable.Create(() => { surface.Canvas.Flush(); surface.Dispose(); renderTarget.Dispose(); _grContext.Flush(); session.Dispose(); })); success = true; return(ctx); } } finally { if (!success) { session.Dispose(); } } }
public SkiaLeaseFeature(DrawingContextImpl context) { _context = context; }
public void Dispose() { _context.Canvas.SetMatrix(_revertTransform); _context._leased = false; _context = null; }
public ApiLease(DrawingContextImpl context) { _revertTransform = context.Canvas.TotalMatrix; _context = context; _context._leased = true; }