106 private SKImage? _image;
107 private SKBitmap? _bitmap;
108 private SKRect? _src;
111 private readonly SKPaint _paint =
new()
114 FilterQuality = SKFilterQuality.Medium,
115 BlendMode = SKBlendMode.SrcOver,
116 Color = SKColors.White
120 private SKColor? _tint;
121 private byte _opacity = 255;
124 private float _rotationDeg = 0f;
127 private float _anchorX = 0.5f, _anchorY = 0.5f;
129 private DirectImage(SKBitmap bitmap,
134 Rectangle? screenBounds,
135 Rectangle? worldBounds,
137 : base(renderSurfaceHost, mode, sceneLayer, view, screenBounds, worldBounds, name)
142 private DirectImage(SKImage image,
147 Rectangle? screenBounds,
148 Rectangle? worldBounds,
149 string? nickname =
null)
150 : base(renderSurfaceHost, mode, sceneLayer, view, screenBounds, worldBounds, nickname)
178 Rectangle worldBounds,
179 string? nickname =
null) : this(bitmap, renderSurfaceHost,
DirectDrawingMode.
SceneLayer, sceneLayer, null, null, worldBounds, nickname) { }
203 Rectangle screenBounds,
204 string? nickname =
null) : this(bitmap, renderSurfaceHost,
DirectDrawingMode.
View, null, view, screenBounds, null, nickname) { }
230 Rectangle worldBounds,
231 string? nickname =
null) : this(image, renderSurfaceHost,
DirectDrawingMode.
SceneLayer, sceneLayer, null, null, worldBounds, nickname) { }
256 Rectangle screenBounds,
257 string? nickname =
null) : this(image, renderSurfaceHost,
DirectDrawingMode.
View, null, view, screenBounds, null, nickname) { }
278 _bitmap = bitmap ??
throw new ArgumentNullException(nameof(bitmap));
303 _image = image ??
throw new ArgumentNullException(nameof(image));
460 _paint.BlendMode = mode;
493 _paint.FilterQuality = q;
518 _rotationDeg = degrees;
550 _anchorX = Math.Clamp(ax, 0f, 1f);
551 _anchorY = Math.Clamp(ay, 0f, 1f);
581 var canvas = backbuffer.
Canvas;
584 var img = _image ?? (_bitmap !=
null ? SKImage.FromBitmap(_bitmap) :
null);
588 if (backbuffer is RecordingBackbuffer && img.IsTextureBacked)
589 throw new NotSupportedException(
"Desktop frame recording requires a CPU image, not a context-bound texture.");
592 SKRect src = _src ??
new SKRect(0, 0, img.Width, img.Height);
595 SKRect dst = ComputeDestRect(destRectScreen.ToPixelAlignedRect(), src, _scale);
599 var tint = _tint ?? SKColors.White;
600 var withAlpha =
new SKColor(tint.Red, tint.Green, tint.Blue, _opacity);
601 using var cf = SKColorFilter.CreateBlendMode(withAlpha, SKBlendMode.Modulate);
602 _paint.ColorFilter = cf;
605 if (_rotationDeg != 0f)
607 float ax = dst.Left + _anchorX * dst.Width;
608 float ay = dst.Top + _anchorY * dst.Height;
610 canvas.RotateDegrees(_rotationDeg, ax, ay);
614 canvas.DrawImage(img, src, dst, _paint);
616 if (_rotationDeg != 0f)
620 if (_image is
null && img is not
null)
624 private static SKRect ComputeDestRect(Rectangle bounds, SKRect src,
ScaleMode mode)
626 var dst = bounds.ToSKRect();
633 float w = MathF.Min(dst.Width, src.Width);
634 float h = MathF.Min(dst.Height, src.Height);
635 float dx = dst.MidX - w * 0.5f, dy = dst.MidY - h * 0.5f;
637 return new SKRect(dx, dy, dx + w, dy + h);
640 float srcW = src.Width, srcH = src.Height;
641 float dstW = dst.Width, dstH = dst.Height;
643 float scaleX = dstW / srcW;
644 float scaleY = dstH / srcH;
646 float scale = mode
switch
648 ScaleMode.Fit => MathF.Min(scaleX, scaleY),
649 ScaleMode.Fill => MathF.Max(scaleX, scaleY),
650 ScaleMode.PixelPerfect => MathF.Max(1f, MathF.Floor(MathF.Min(scaleX, scaleY))),
654 float w2 = srcW * scale, h2 = srcH * scale;
655 float x = dst.MidX - w2 * 0.5f;
656 float y = dst.MidY - h2 * 0.5f;
658 return new SKRect(x, y, x + w2, y + h2);
View? View
Gets the view to which this direct drawing is attached, or null if the drawing is in scene-layer mode...
SceneLayer? SceneLayer
Gets the scene layer to which this direct drawing is attached, or null if the drawing is in view mode...
DirectDrawingMovableBase(RenderSurfaceHostBase renderSurfaceHost, DirectDrawingMode mode, SceneLayer? sceneLayer, View? view, Rectangle? screenBounds, Rectangle? worldBounds, string? name=null)
Initializes a new instance of the DirectDrawingMovableBase class with integrated movement capabilitie...
DirectImage(SKBitmap bitmap, RenderSurfaceHostBase renderSurfaceHost, SceneLayer sceneLayer, Rectangle worldBounds, string? nickname=null)
Initializes a new instance of the DirectImage class for scene-layer (world-space) rendering using a b...
DirectImage SetAnchor(float ax, float ay)
Sets the rotation and scaling anchor point within the destination rectangle using normalized coordina...
DirectImage SetScaleMode(ScaleMode mode)
Sets how the image is scaled to fit within the destination rectangle.
DirectImage SetFilterQuality(SKFilterQuality q)
Sets the filter quality used when scaling the image.
DirectImage ClearTint()
Removes any color tint, restoring the image's original colors.
DirectImage SetBlendMode(SKBlendMode mode)
Sets the Skia blend mode used when compositing this image onto the backbuffer.
DirectImage SetTint(SKColor color)
Applies a color tint (multiplicative blend) to the image.
override void OnDraw(BackbufferBase backbuffer, RectangleF destRectScreen)
Renders the image to the backbuffer with all configured transformations and effects applied.
DirectImage SetImage(SKImage image)
Replaces the backing image with a new one.
DirectImage SetBitmap(SKBitmap bitmap)
Replaces the backing bitmap with a new one.
DirectImage SetOpacity(byte alpha)
Sets the overall opacity (alpha transparency) of the image.
DirectImage(SKImage image, RenderSurfaceHostBase renderSurfaceHost, View view, Rectangle screenBounds, string? nickname=null)
Initializes a new instance of the DirectImage class for view (screen-space) rendering using a pre-enc...
DirectImage(SKImage image, RenderSurfaceHostBase renderSurfaceHost, SceneLayer sceneLayer, Rectangle worldBounds, string? nickname=null)
Initializes a new instance of the DirectImage class for scene-layer (world-space) rendering using a p...
DirectImage SetRotation(float degrees)
Sets the rotation angle in degrees around the anchor point.
DirectImage SetSourceRect(SKRect? srcPixels)
Sets the source rectangle within the image to display, enabling sprite sheet support.
ScaleMode
Defines how an image is scaled to fit within the destination rectangle.
@ Fit
Scales the image to fit entirely within the destination rectangle while preserving aspect ratio....
@ PixelPerfect
Scales the image by the largest integer factor that fits within the destination rectangle while prese...
@ Center
Displays the image at its native resolution without scaling, centered in the destination rectangle....
@ Fill
Scales the image to completely cover the destination rectangle while preserving aspect ratio....
@ Stretch
Stretches the image to fill the entire destination rectangle, ignoring aspect ratio....
DirectImage(SKBitmap bitmap, RenderSurfaceHostBase renderSurfaceHost, View view, Rectangle screenBounds, string? nickname=null)
Initializes a new instance of the DirectImage class for view (screen-space) rendering using a bitmap.
Represents a base class for managing a graphical backbuffer, and is the in-memory surface where rende...
SKCanvas Canvas
Gets the SkiaSharp canvas used for drawing operations on this backbuffer.
Represents a base class for hosting a render surface, providing functionality for managing rendering ...
Represents a rendered view of a scene, combining a camera position with a viewport configuration to c...
Represents a single layer within a Scene, containing a grid of tiles and supporting various coordinat...
DirectDrawingMode
Specifies where direct drawing operations are applied within the rendering pipeline.