Add a few more members for SKCanvas (#1090)
- DrawArc - DrawAtlas - DrawPatch - DrawRoundRectDifference - IsClipEmpty and IsClipRect
This commit is contained in:
Родитель
e2514cda18
Коммит
48c9d72a56
|
@ -3,18 +3,12 @@
|
|||
namespace SkiaSharp
|
||||
{
|
||||
// TODO: carefully consider the `PeekPixels`, `ReadPixels`
|
||||
// TODO: `ClipRRect` may be useful
|
||||
// TODO: `DrawRRect` may be useful
|
||||
// TODO: `DrawDRRect` may be useful
|
||||
// TODO: add the `DrawArc` variants
|
||||
// TODO: add `DrawTextBlob` variants if/when we bind `SKTextBlob`
|
||||
// TODO: add `DrawPatch` variants
|
||||
// TODO: add `DrawAtlas` variants
|
||||
// TODO: add `DrawDrawable` variants if/when we bind `SKDrawable`
|
||||
// TODO: add `IsClipEmpty` and `IsClipRect`
|
||||
|
||||
public unsafe class SKCanvas : SKObject
|
||||
{
|
||||
private const int PatchCornerCount = 4;
|
||||
private const int PatchCubicsCount = 12;
|
||||
|
||||
[Preserve]
|
||||
internal SKCanvas (IntPtr handle, bool owns)
|
||||
: base (handle, owns)
|
||||
|
@ -220,6 +214,10 @@ namespace SkiaSharp
|
|||
}
|
||||
}
|
||||
|
||||
public bool IsClipEmpty => SkiaApi.sk_canvas_is_clip_empty (Handle);
|
||||
|
||||
public bool IsClipRect => SkiaApi.sk_canvas_is_clip_rect (Handle);
|
||||
|
||||
public bool GetLocalClipBounds (out SKRect bounds)
|
||||
{
|
||||
fixed (SKRect* b = &bounds) {
|
||||
|
@ -833,6 +831,102 @@ namespace SkiaSharp
|
|||
throw new ArgumentNullException (nameof (paint));
|
||||
SkiaApi.sk_canvas_draw_vertices (Handle, vertices.Handle, mode, paint.Handle);
|
||||
}
|
||||
|
||||
public void DrawArc (SKRect oval, float startAngle, float sweepAngle, bool useCenter, SKPaint paint)
|
||||
{
|
||||
if (paint == null)
|
||||
throw new ArgumentNullException (nameof (paint));
|
||||
SkiaApi.sk_canvas_draw_arc (Handle, &oval, startAngle, sweepAngle, useCenter, paint.Handle);
|
||||
}
|
||||
|
||||
public void DrawRoundRectDifference (SKRoundRect outer, SKRoundRect inner, SKPaint paint)
|
||||
{
|
||||
if (outer == null)
|
||||
throw new ArgumentNullException (nameof (outer));
|
||||
if (inner == null)
|
||||
throw new ArgumentNullException (nameof (inner));
|
||||
if (paint == null)
|
||||
throw new ArgumentNullException (nameof (paint));
|
||||
|
||||
SkiaApi.sk_canvas_draw_drrect (Handle, outer.Handle, inner.Handle, paint.Handle);
|
||||
}
|
||||
|
||||
public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKPaint paint)
|
||||
=> DrawAtlas (atlas, sprites, transforms, null, SKBlendMode.Dst, null, paint);
|
||||
|
||||
public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKRect cullRect, SKPaint paint)
|
||||
=> DrawAtlas (atlas, sprites, transforms, null, SKBlendMode.Dst, &cullRect, paint);
|
||||
|
||||
public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKBlendMode mode, SKPaint paint)
|
||||
=> DrawAtlas (atlas, sprites, transforms, null, mode, null, paint);
|
||||
|
||||
public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKBlendMode mode, SKRect cullRect, SKPaint paint)
|
||||
=> DrawAtlas (atlas, sprites, transforms, null, mode, &cullRect, paint);
|
||||
|
||||
public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKPaint paint)
|
||||
=> DrawAtlas (atlas, sprites, transforms, colors, mode, null, paint);
|
||||
|
||||
public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKRect cullRect, SKPaint paint)
|
||||
=> DrawAtlas (atlas, sprites, transforms, colors, mode, &cullRect, paint);
|
||||
|
||||
private void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKRect* cullRect, SKPaint paint)
|
||||
{
|
||||
if (atlas == null)
|
||||
throw new ArgumentNullException (nameof (atlas));
|
||||
if (sprites == null)
|
||||
throw new ArgumentNullException (nameof (sprites));
|
||||
if (transforms == null)
|
||||
throw new ArgumentNullException (nameof (transforms));
|
||||
|
||||
if (transforms.Length != sprites.Length)
|
||||
throw new ArgumentException ("The number of transforms must match the number of sprites.", nameof (transforms));
|
||||
if (colors != null && colors.Length != sprites.Length)
|
||||
throw new ArgumentException ("The number of colors must match the number of sprites.", nameof (colors));
|
||||
|
||||
fixed (SKRect* s = sprites)
|
||||
fixed (SKRotationScaleMatrix* t = transforms)
|
||||
fixed (SKColor* c = colors) {
|
||||
SkiaApi.sk_canvas_draw_atlas (Handle, atlas.Handle, t, s, (uint*)c, transforms.Length, mode, cullRect, paint.Handle);
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawPatch (SKPoint[] cubics, SKColor[] colors, SKPaint paint)
|
||||
=> DrawPatch (cubics, colors, null, SKBlendMode.Modulate, paint);
|
||||
|
||||
public void DrawPatch (SKPoint[] cubics, SKColor[] colors, SKBlendMode mode, SKPaint paint)
|
||||
=> DrawPatch (cubics, colors, null, mode, paint);
|
||||
|
||||
public void DrawPatch (SKPoint[] cubics, SKPoint[] texCoords, SKPaint paint)
|
||||
=> DrawPatch (cubics, null, texCoords, SKBlendMode.Modulate, paint);
|
||||
|
||||
public void DrawPatch (SKPoint[] cubics, SKPoint[] texCoords, SKBlendMode mode, SKPaint paint)
|
||||
=> DrawPatch (cubics, null, texCoords, mode, paint);
|
||||
|
||||
public void DrawPatch (SKPoint[] cubics, SKColor[] colors, SKPoint[] texCoords, SKPaint paint)
|
||||
=> DrawPatch (cubics, colors, texCoords, SKBlendMode.Modulate, paint);
|
||||
|
||||
public void DrawPatch (SKPoint[] cubics, SKColor[] colors, SKPoint[] texCoords, SKBlendMode mode, SKPaint paint)
|
||||
{
|
||||
if (cubics == null)
|
||||
throw new ArgumentNullException (nameof (cubics));
|
||||
if (cubics.Length != PatchCubicsCount)
|
||||
throw new ArgumentException ($"Cubics must have a length of {PatchCubicsCount}.", nameof (cubics));
|
||||
|
||||
if (colors != null && colors.Length != PatchCornerCount)
|
||||
throw new ArgumentException ($"Colors must have a length of {PatchCornerCount}.", nameof (colors));
|
||||
|
||||
if (texCoords != null && texCoords.Length != PatchCornerCount)
|
||||
throw new ArgumentException ($"Texture coordinates must have a length of {PatchCornerCount}.", nameof (texCoords));
|
||||
|
||||
if (paint == null)
|
||||
throw new ArgumentNullException (nameof (paint));
|
||||
|
||||
fixed (SKPoint* cubes = cubics)
|
||||
fixed (SKColor* cols = colors)
|
||||
fixed (SKPoint* coords = texCoords) {
|
||||
SkiaApi.sk_canvas_draw_patch (Handle, cubes, (uint*)cols, coords, mode, paint.Handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SKAutoCanvasRestore : IDisposable
|
||||
|
|
|
@ -486,6 +486,8 @@ namespace SkiaSharp
|
|||
public bool IsAlphaOnly => SkiaApi.sk_image_is_alpha_only (Handle);
|
||||
public SKData EncodedData => GetObject<SKData> (SkiaApi.sk_image_ref_encoded (Handle));
|
||||
|
||||
public SKShader ToShader () => ToShader (SKShaderTileMode.Clamp, SKShaderTileMode.Clamp);
|
||||
|
||||
public SKShader ToShader (SKShaderTileMode tileX, SKShaderTileMode tileY)
|
||||
{
|
||||
return GetObject<SKShader> (SkiaApi.sk_image_make_shader (Handle, tileX, tileY, null));
|
||||
|
|
|
@ -5,6 +5,8 @@ namespace SkiaSharp
|
|||
{
|
||||
public unsafe partial struct SKMatrix
|
||||
{
|
||||
internal const float DegreesToRadians = (float)System.Math.PI / 180.0f;
|
||||
|
||||
private class Indices {
|
||||
public const int ScaleX = 0;
|
||||
public const int SkewX = 1;
|
||||
|
@ -122,7 +124,7 @@ namespace SkiaSharp
|
|||
#if OPTIMIZED_SKMATRIX
|
||||
, typeMask = Mask.Identity | Mask.RectStaysRect
|
||||
#endif
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
public void SetScaleTranslate (float sx, float sy, float tx, float ty)
|
||||
|
@ -219,19 +221,17 @@ typeMask = Mask.Scale | Mask.RectStaysRect
|
|||
return matrix;
|
||||
}
|
||||
|
||||
const float degToRad = (float)System.Math.PI / 180.0f;
|
||||
|
||||
public static SKMatrix MakeRotationDegrees (float degrees)
|
||||
{
|
||||
return MakeRotation (degrees * degToRad);
|
||||
return MakeRotation (degrees * DegreesToRadians);
|
||||
}
|
||||
|
||||
public static SKMatrix MakeRotationDegrees (float degrees, float pivotx, float pivoty)
|
||||
{
|
||||
return MakeRotation (degrees * degToRad, pivotx, pivoty);
|
||||
return MakeRotation (degrees * DegreesToRadians, pivotx, pivoty);
|
||||
}
|
||||
|
||||
static void SetSinCos (ref SKMatrix matrix, float sin, float cos)
|
||||
private static void SetSinCos (ref SKMatrix matrix, float sin, float cos)
|
||||
{
|
||||
matrix.scaleX = cos;
|
||||
matrix.skewX = -sin;
|
||||
|
@ -247,7 +247,7 @@ typeMask = Mask.Scale | Mask.RectStaysRect
|
|||
#endif
|
||||
}
|
||||
|
||||
static void SetSinCos (ref SKMatrix matrix, float sin, float cos, float pivotx, float pivoty)
|
||||
private static void SetSinCos (ref SKMatrix matrix, float sin, float cos, float pivotx, float pivoty)
|
||||
{
|
||||
float oneMinusCos = 1-cos;
|
||||
|
||||
|
@ -274,8 +274,8 @@ typeMask = Mask.Scale | Mask.RectStaysRect
|
|||
|
||||
public static void RotateDegrees (ref SKMatrix matrix, float degrees, float pivotx, float pivoty)
|
||||
{
|
||||
var sin = (float) Math.Sin (degrees * degToRad);
|
||||
var cos = (float) Math.Cos (degrees * degToRad);
|
||||
var sin = (float) Math.Sin (degrees * DegreesToRadians);
|
||||
var cos = (float) Math.Cos (degrees * DegreesToRadians);
|
||||
SetSinCos (ref matrix, sin, cos, pivotx, pivoty);
|
||||
}
|
||||
|
||||
|
@ -288,8 +288,8 @@ typeMask = Mask.Scale | Mask.RectStaysRect
|
|||
|
||||
public static void RotateDegrees (ref SKMatrix matrix, float degrees)
|
||||
{
|
||||
var sin = (float) Math.Sin (degrees * degToRad);
|
||||
var cos = (float) Math.Cos (degrees * degToRad);
|
||||
var sin = (float) Math.Sin (degrees * DegreesToRadians);
|
||||
var cos = (float) Math.Cos (degrees * DegreesToRadians);
|
||||
SetSinCos (ref matrix, sin, cos);
|
||||
}
|
||||
|
||||
|
@ -1006,4 +1006,48 @@ typeMask = Mask.Scale | Mask.RectStaysRect
|
|||
return SkiaApi.sk_matrix44_determinant (Handle);
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe partial struct SKRotationScaleMatrix
|
||||
{
|
||||
public static readonly SKRotationScaleMatrix Empty;
|
||||
|
||||
public SKRotationScaleMatrix (float scos, float ssin, float tx, float ty)
|
||||
{
|
||||
fSCos = scos;
|
||||
fSSin = ssin;
|
||||
fTX = tx;
|
||||
fTY = ty;
|
||||
}
|
||||
|
||||
public SKMatrix ToMatrix () =>
|
||||
new SKMatrix (fSCos, -fSSin, fTX, fSSin, fSCos, fTY, 0, 0, 1);
|
||||
|
||||
public static SKRotationScaleMatrix FromDegrees (float scale, float degrees, float tx, float ty, float anchorX, float anchorY) =>
|
||||
FromRadians (scale, degrees * SKMatrix.DegreesToRadians, tx, ty, anchorX, anchorY);
|
||||
|
||||
public static SKRotationScaleMatrix FromRadians (float scale, float radians, float tx, float ty, float anchorX, float anchorY)
|
||||
{
|
||||
var s = (float)Math.Sin (radians) * scale;
|
||||
var c = (float)Math.Cos (radians) * scale;
|
||||
var x = tx + -c * anchorX + s * anchorY;
|
||||
var y = ty + -s * anchorX - c * anchorY;
|
||||
|
||||
return new SKRotationScaleMatrix (c, s, x, y);
|
||||
}
|
||||
|
||||
public static SKRotationScaleMatrix CreateIdentity () =>
|
||||
new SKRotationScaleMatrix (1, 0, 0, 0);
|
||||
|
||||
public static SKRotationScaleMatrix CreateTranslate (float x, float y) =>
|
||||
new SKRotationScaleMatrix (1, 0, x, y);
|
||||
|
||||
public static SKRotationScaleMatrix CreateScale (float s) =>
|
||||
new SKRotationScaleMatrix (s, 0, 0, 0);
|
||||
|
||||
public static SKRotationScaleMatrix CreateRotation (float radians, float anchorX, float anchorY) =>
|
||||
FromRadians (1, radians, 0, 0, anchorX, anchorY);
|
||||
|
||||
public static SKRotationScaleMatrix CreateRotationDegrees (float degrees, float anchorX, float anchorY) =>
|
||||
FromDegrees (1, degrees, 0, 0, anchorX, anchorY);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,11 @@ namespace SkiaSharp
|
|||
SetRect (rect);
|
||||
}
|
||||
|
||||
public SKRoundRect (SKRect rect, float radius)
|
||||
: this (rect, radius, radius)
|
||||
{
|
||||
}
|
||||
|
||||
public SKRoundRect (SKRect rect, float xRadius, float yRadius)
|
||||
: this (SkiaApi.sk_rrect_new (), true)
|
||||
{
|
||||
|
|
|
@ -653,6 +653,14 @@ namespace SkiaSharp
|
|||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void sk_canvas_draw_annotation (sk_canvas_t t, SKRect* rect, /* char */ void* key, sk_data_t value);
|
||||
|
||||
// void sk_canvas_draw_arc(sk_canvas_t* ccanvas, const sk_rect_t* oval, float startAngle, float sweepAngle, bool useCenter, const sk_paint_t* paint)
|
||||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void sk_canvas_draw_arc (sk_canvas_t ccanvas, SKRect* oval, Single startAngle, Single sweepAngle, [MarshalAs (UnmanagedType.I1)] bool useCenter, sk_paint_t paint);
|
||||
|
||||
// void sk_canvas_draw_atlas(sk_canvas_t* ccanvas, const sk_image_t* atlas, const sk_rsxform_t* xform, const sk_rect_t* tex, const sk_color_t* colors, int count, sk_blendmode_t mode, const sk_rect_t* cullRect, const sk_paint_t* paint)
|
||||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void sk_canvas_draw_atlas (sk_canvas_t ccanvas, sk_image_t atlas, SKRotationScaleMatrix* xform, SKRect* tex, UInt32* colors, Int32 count, SKBlendMode mode, SKRect* cullRect, sk_paint_t paint);
|
||||
|
||||
// void sk_canvas_draw_bitmap(sk_canvas_t* ccanvas, const sk_bitmap_t* bitmap, float left, float top, const sk_paint_t* paint)
|
||||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void sk_canvas_draw_bitmap (sk_canvas_t ccanvas, sk_bitmap_t bitmap, Single left, Single top, sk_paint_t paint);
|
||||
|
@ -681,6 +689,10 @@ namespace SkiaSharp
|
|||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void sk_canvas_draw_drawable (sk_canvas_t param0, sk_drawable_t param1, SKMatrix* param2);
|
||||
|
||||
// void sk_canvas_draw_drrect(sk_canvas_t* ccanvas, const sk_rrect_t* outer, const sk_rrect_t* inner, const sk_paint_t* paint)
|
||||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void sk_canvas_draw_drrect (sk_canvas_t ccanvas, sk_rrect_t outer, sk_rrect_t inner, sk_paint_t paint);
|
||||
|
||||
// void sk_canvas_draw_image(sk_canvas_t*, const sk_image_t*, float x, float y, const sk_paint_t*)
|
||||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void sk_canvas_draw_image (sk_canvas_t param0, sk_image_t param1, Single x, Single y, sk_paint_t param4);
|
||||
|
@ -717,6 +729,10 @@ namespace SkiaSharp
|
|||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void sk_canvas_draw_paint (sk_canvas_t param0, sk_paint_t param1);
|
||||
|
||||
// void sk_canvas_draw_patch(sk_canvas_t* ccanvas, const sk_point_t* cubics, const sk_color_t* colors, const sk_point_t* texCoords, sk_blendmode_t mode, const sk_paint_t* paint)
|
||||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void sk_canvas_draw_patch (sk_canvas_t ccanvas, SKPoint* cubics, UInt32* colors, SKPoint* texCoords, SKBlendMode mode, sk_paint_t paint);
|
||||
|
||||
// void sk_canvas_draw_path(sk_canvas_t*, const sk_path_t*, const sk_paint_t*)
|
||||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void sk_canvas_draw_path (sk_canvas_t param0, sk_path_t param1, sk_paint_t param2);
|
||||
|
@ -769,7 +785,7 @@ namespace SkiaSharp
|
|||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void sk_canvas_draw_url_annotation (sk_canvas_t t, SKRect* rect, sk_data_t value);
|
||||
|
||||
// void sk_canvas_draw_vertices(sk_canvas_t* ccanvas, sk_vertices_t* vertices, sk_blendmode_t mode, const sk_paint_t* paint)
|
||||
// void sk_canvas_draw_vertices(sk_canvas_t* ccanvas, const sk_vertices_t* vertices, sk_blendmode_t mode, const sk_paint_t* paint)
|
||||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void sk_canvas_draw_vertices (sk_canvas_t ccanvas, sk_vertices_t vertices, SKBlendMode mode, sk_paint_t paint);
|
||||
|
||||
|
@ -795,6 +811,16 @@ namespace SkiaSharp
|
|||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void sk_canvas_get_total_matrix (sk_canvas_t ccanvas, SKMatrix* matrix);
|
||||
|
||||
// bool sk_canvas_is_clip_empty(sk_canvas_t* ccanvas)
|
||||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
[return: MarshalAs (UnmanagedType.I1)]
|
||||
internal static extern bool sk_canvas_is_clip_empty (sk_canvas_t ccanvas);
|
||||
|
||||
// bool sk_canvas_is_clip_rect(sk_canvas_t* ccanvas)
|
||||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
[return: MarshalAs (UnmanagedType.I1)]
|
||||
internal static extern bool sk_canvas_is_clip_rect (sk_canvas_t ccanvas);
|
||||
|
||||
// sk_canvas_t* sk_canvas_new_from_bitmap(const sk_bitmap_t* bitmap)
|
||||
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern sk_canvas_t sk_canvas_new_from_bitmap (sk_bitmap_t bitmap);
|
||||
|
@ -4214,6 +4240,39 @@ namespace SkiaSharp
|
|||
|
||||
}
|
||||
|
||||
// sk_rsxform_t
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
public unsafe partial struct SKRotationScaleMatrix {
|
||||
// public float fSCos
|
||||
private Single fSCos;
|
||||
public Single SCos {
|
||||
get => fSCos;
|
||||
set => fSCos = value;
|
||||
}
|
||||
|
||||
// public float fSSin
|
||||
private Single fSSin;
|
||||
public Single SSin {
|
||||
get => fSSin;
|
||||
set => fSSin = value;
|
||||
}
|
||||
|
||||
// public float fTX
|
||||
private Single fTX;
|
||||
public Single TX {
|
||||
get => fTX;
|
||||
set => fTX = value;
|
||||
}
|
||||
|
||||
// public float fTY
|
||||
private Single fTY;
|
||||
public Single TY {
|
||||
get => fTY;
|
||||
set => fTY = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// sk_size_t
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
public unsafe partial struct SKSize {
|
||||
|
|
|
@ -102,6 +102,9 @@
|
|||
"sk_colortype_t": {
|
||||
"cs": "SKColorType"
|
||||
},
|
||||
"sk_rsxform_t": {
|
||||
"cs": "SKRotationScaleMatrix"
|
||||
},
|
||||
"sk_shader_tilemode_t": {
|
||||
"cs": "SKShaderTileMode"
|
||||
},
|
||||
|
|
|
@ -80,6 +80,90 @@ namespace SkiaSharp.Tests
|
|||
Assert.Equal(textPixels, glyphsPixels);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void CanDrawRoundRectDifference()
|
||||
{
|
||||
using var outer = new SKRoundRect(SKRect.Create(50, 50, 200, 200), 20);
|
||||
using var inner = new SKRoundRect(SKRect.Create(100, 100, 100, 100), 20);
|
||||
|
||||
using var paint = new SKPaint();
|
||||
|
||||
SKColor[] diff;
|
||||
using (var bmp = new SKBitmap(new SKImageInfo(300, 300)))
|
||||
using (var canvas = new SKCanvas(bmp))
|
||||
{
|
||||
canvas.Clear(SKColors.Transparent);
|
||||
canvas.DrawRoundRectDifference(outer, inner, paint);
|
||||
|
||||
diff = bmp.Pixels;
|
||||
}
|
||||
|
||||
SKColor[] paths;
|
||||
using (var bmp = new SKBitmap(new SKImageInfo(300, 300)))
|
||||
using (var canvas = new SKCanvas(bmp))
|
||||
using (var path = new SKPath())
|
||||
{
|
||||
canvas.Clear(SKColors.Transparent);
|
||||
|
||||
path.AddRoundRect(outer);
|
||||
path.AddRoundRect(inner);
|
||||
path.FillType = SKPathFillType.EvenOdd;
|
||||
|
||||
canvas.DrawPath(path, paint);
|
||||
|
||||
paths = bmp.Pixels;
|
||||
}
|
||||
|
||||
Assert.Equal(paths, diff);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void DrawAtlasThrowsOnMismatchingArgs()
|
||||
{
|
||||
using var bmp = new SKBitmap(new SKImageInfo(300, 300));
|
||||
using var img = SKImage.FromBitmap(bmp);
|
||||
using var canvas = new SKCanvas(bmp);
|
||||
|
||||
using var paint = new SKPaint();
|
||||
var sprites = new[] { SKRect.Empty, SKRect.Empty };
|
||||
var transforms = new[] { SKRotationScaleMatrix.Empty };
|
||||
|
||||
Assert.Throws<ArgumentException>("transforms", () => canvas.DrawAtlas(img, sprites, transforms, SKBlendMode.Src, paint));
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void CanDrawPatch()
|
||||
{
|
||||
var cubics = new SKPoint[12] {
|
||||
// top points
|
||||
new SKPoint(100, 100), new SKPoint(150, 50), new SKPoint(250, 150), new SKPoint(300, 100),
|
||||
// right points
|
||||
new SKPoint(250, 150), new SKPoint(350, 250),
|
||||
// bottom points
|
||||
new SKPoint(300, 300), new SKPoint(250, 250), new SKPoint(150, 350), new SKPoint(100, 300),
|
||||
// left points
|
||||
new SKPoint(50, 250), new SKPoint(150, 150)
|
||||
};
|
||||
|
||||
var baboon = SKImage.FromEncodedData(Path.Combine(PathToImages, "baboon.jpg"));
|
||||
var tex = new SKPoint[4] {
|
||||
new SKPoint(0, 0),
|
||||
new SKPoint(baboon.Width, 0),
|
||||
new SKPoint(baboon.Width, baboon.Height),
|
||||
new SKPoint(0, baboon.Height),
|
||||
};
|
||||
|
||||
using var bmp = new SKBitmap(new SKImageInfo(400, 400));
|
||||
using var canvas = new SKCanvas(bmp);
|
||||
using var paint = new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
Shader = baboon.ToShader(),
|
||||
};
|
||||
|
||||
canvas.DrawPatch(cubics, tex, paint);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void CanDrawText()
|
||||
{
|
||||
|
@ -200,6 +284,96 @@ namespace SkiaSharp.Tests
|
|||
}
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void DrawAtlasSupportsTransforms()
|
||||
{
|
||||
var target = new SKRect(50, 50, 80, 90);
|
||||
var rec = new[]
|
||||
{
|
||||
(Scale: 1, Degrees: 0, TX: 10, TY: 10), // just translate
|
||||
(Scale: 2, Degrees: 0, TX: 110, TY: 10), // scale + translate
|
||||
(Scale: 1, Degrees: 30, TX: 210, TY: 10), // rotate + translate
|
||||
(Scale: 2, Degrees: -30, TX: 310, TY: 30), // scale + rotate + translate
|
||||
};
|
||||
|
||||
var N = rec.Length;
|
||||
var xform = new SKRotationScaleMatrix[N];
|
||||
var tex = new SKRect[N];
|
||||
var colors = new SKColor[N];
|
||||
|
||||
for (var i = 0; i < N; ++i)
|
||||
{
|
||||
xform[i] = Apply(rec[i]);
|
||||
tex[i] = target;
|
||||
colors[i] = 0x80FF0000 + (uint)(i * 40 * 256);
|
||||
}
|
||||
|
||||
using var atlas = CreateAtlas(target);
|
||||
|
||||
using var bitmap = new SKBitmap(new SKImageInfo(640, 480));
|
||||
using var canvas = new SKCanvas(bitmap);
|
||||
|
||||
using var paint = new SKPaint
|
||||
{
|
||||
FilterQuality = SKFilterQuality.Low,
|
||||
IsAntialias = true
|
||||
};
|
||||
|
||||
canvas.Clear(SKColors.White);
|
||||
canvas.DrawAtlas(atlas, tex, xform, paint);
|
||||
canvas.Translate(0, 100);
|
||||
canvas.DrawAtlas(atlas, tex, xform, colors, SKBlendMode.SrcIn, paint);
|
||||
|
||||
Assert.Equal(SKColors.Blue, bitmap.GetPixel(32, 41));
|
||||
Assert.Equal(SKColors.Blue, bitmap.GetPixel(156, 77));
|
||||
Assert.Equal(SKColors.Blue, bitmap.GetPixel(201, 45));
|
||||
Assert.Equal(SKColors.Blue, bitmap.GetPixel(374, 80));
|
||||
|
||||
Assert.Equal(0xFF7F7FFF, bitmap.GetPixel(32, 141));
|
||||
Assert.Equal(0xFF7F7FFF, bitmap.GetPixel(156, 177));
|
||||
Assert.Equal(0xFF7F7FFF, bitmap.GetPixel(201, 145));
|
||||
Assert.Equal(0xFF7F7FFF, bitmap.GetPixel(374, 180));
|
||||
|
||||
static SKRotationScaleMatrix Apply((float Scale, float Degrees, float TX, float TY) rec)
|
||||
{
|
||||
var rad = SKMatrix.DegreesToRadians * rec.Degrees;
|
||||
return new SKRotationScaleMatrix(
|
||||
rec.Scale * (float)Math.Cos(rad),
|
||||
rec.Scale * (float)Math.Sin(rad),
|
||||
rec.TX,
|
||||
rec.TY);
|
||||
}
|
||||
|
||||
static SKImage CreateAtlas(SKRect target)
|
||||
{
|
||||
var info = new SKImageInfo(100, 100);
|
||||
|
||||
using var surface = SKSurface.Create(info);
|
||||
using var canvas = surface.Canvas;
|
||||
|
||||
// draw red everywhere, but we don't expect to see it in the draw, testing the notion
|
||||
// that drawAtlas draws a subset-region of the atlas.
|
||||
canvas.Clear(SKColors.Red);
|
||||
|
||||
using var paint = new SKPaint
|
||||
{
|
||||
BlendMode = SKBlendMode.Clear
|
||||
};
|
||||
|
||||
// zero out a place (with a 1-pixel border) to land our drawing.
|
||||
var r = target;
|
||||
r.Inflate(1, 1);
|
||||
canvas.DrawRect(r, paint);
|
||||
|
||||
paint.BlendMode = SKBlendMode.SrcOver;
|
||||
paint.Color = SKColors.Blue;
|
||||
paint.IsAntialias = true;
|
||||
canvas.DrawOval(target, paint);
|
||||
|
||||
return surface.Snapshot();
|
||||
}
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void TotalMatrixIsCorrect()
|
||||
{
|
||||
|
|
|
@ -187,6 +187,33 @@ namespace SkiaSharp.Tests
|
|||
Assert.Equal(SKMatrix.MakeTranslation(15, 27).Values, a.Values);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void SKRotationScaleMatrixTranslationToMatrixIsCorrect()
|
||||
{
|
||||
var m = SKMatrix.MakeTranslation(5, 7);
|
||||
var rsm = SKRotationScaleMatrix.CreateTranslate(5, 7).ToMatrix();
|
||||
|
||||
Assert.Equal(m.Values, rsm.Values);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void SKRotationScaleMatrixRotationToMatrixIsCorrect()
|
||||
{
|
||||
var m = SKMatrix.MakeRotationDegrees(45);
|
||||
var rsm = SKRotationScaleMatrix.CreateRotationDegrees(45, 0, 0).ToMatrix();
|
||||
|
||||
Assert.Equal(m.Values, rsm.Values);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void SKRotationScaleMatrixScaleToMatrixIsCorrect()
|
||||
{
|
||||
var m = SKMatrix.MakeScale(3.5f, 3.5f);
|
||||
var rsm = SKRotationScaleMatrix.CreateScale(3.5f).ToMatrix();
|
||||
|
||||
Assert.Equal(m.Values, rsm.Values);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void MatrixMapsPoints()
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче