expose SKMask
This commit is contained in:
Родитель
4d13effb74
Коммит
c7b7b496a1
|
@ -2533,6 +2533,70 @@ typeMask = Mask.Scale | Mask.RectStaysRect
|
|||
}
|
||||
}
|
||||
|
||||
public enum SKMaskFormat
|
||||
{
|
||||
BW_Format,
|
||||
A8_Format,
|
||||
THREE_D_Format,
|
||||
ARGB32_Format,
|
||||
LCD16_Format,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SKMask : IDisposable
|
||||
{
|
||||
IntPtr image;
|
||||
SKRectI bounds;
|
||||
UInt32 rowBytes;
|
||||
SKMaskFormat format;
|
||||
|
||||
public SKMask(byte[] buffer, SKRectI bounds, UInt32 rowBytes, SKMaskFormat format)
|
||||
{
|
||||
this.bounds = bounds;
|
||||
this.rowBytes = rowBytes;
|
||||
this.format = format;
|
||||
this.image = IntPtr.Zero;
|
||||
|
||||
if (buffer.Length != (int)ComputeImageSize()) {
|
||||
// Note: buffer.Length must match bounds.Height * rowBytes
|
||||
var expectedHeight = bounds.Height * rowBytes;
|
||||
var message = $"Length of buffer ({buffer.Length}) does not match the computed size of the mask ({expectedHeight}). Check bounds and rowBytes";
|
||||
throw new System.ArgumentException(message);
|
||||
}
|
||||
|
||||
AllocateImage();
|
||||
Marshal.Copy(buffer, 0, this.image, buffer.Length);
|
||||
}
|
||||
|
||||
public IntPtr Image => image;
|
||||
public SKRectI Bounds => bounds;
|
||||
public UInt32 RowBytes => rowBytes;
|
||||
public SKMaskFormat Format => format;
|
||||
|
||||
|
||||
private void AllocateImage()
|
||||
{
|
||||
if (this.format == SKMaskFormat.THREE_D_Format) {
|
||||
this.image = SkiaApi.sk_mask_alloc_image(ComputeTotalImageSize());
|
||||
} else {
|
||||
this.image = SkiaApi.sk_mask_alloc_image(ComputeImageSize());
|
||||
}
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
SkiaApi.sk_mask_free_image(this.image);
|
||||
}
|
||||
public bool IsEmpty() => SkiaApi.sk_mask_is_empty(ref this);
|
||||
public IntPtr ComputeImageSize() => SkiaApi.sk_mask_compute_image_size(ref this);
|
||||
public IntPtr ComputeTotalImageSize() => SkiaApi.sk_mask_compute_total_image_size(ref this);
|
||||
public byte GetAddr1(int x, int y) => SkiaApi.sk_mask_get_addr_1(ref this, x, y);
|
||||
public byte GetAddr8(int x, int y) => SkiaApi.sk_mask_get_addr_8(ref this, x, y);
|
||||
public UInt16 GetAddr16(int x, int y) => SkiaApi.sk_mask_get_addr_lcd_16(ref this, x, y);
|
||||
public UInt32 GetAddr32(int x, int y) => SkiaApi.sk_mask_get_addr_32(ref this, x, y);
|
||||
public IntPtr GetAddr(int x, int y) => SkiaApi.sk_mask_get_addr(ref this, x, y);
|
||||
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SKFontMetrics
|
||||
{
|
||||
|
|
|
@ -465,6 +465,11 @@ namespace SkiaSharp
|
|||
return SkiaApi.sk_bitmap_install_pixels_with_pixmap (Handle, pixmap.Handle);
|
||||
}
|
||||
|
||||
public bool InstallMaskPixels(SKMask mask)
|
||||
{
|
||||
return SkiaApi.sk_bitmap_install_mask_pixels(Handle, ref mask);
|
||||
}
|
||||
|
||||
public SKPixmap PeekPixels ()
|
||||
{
|
||||
SKPixmap pixmap = new SKPixmap ();
|
||||
|
|
|
@ -1153,6 +1153,9 @@ namespace SkiaSharp
|
|||
public extern static bool sk_bitmap_install_pixels_with_pixmap(sk_bitmap_t cbitmap, sk_pixmap_t cpixmap);
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
public extern static bool sk_bitmap_install_mask_pixels(sk_bitmap_t cbitmap, ref SKMask cmask);
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
public extern static bool sk_bitmap_try_alloc_pixels(sk_bitmap_t cbitmap, ref SKImageInfo requestedInfo, IntPtr rowBytes);
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
|
@ -1189,6 +1192,29 @@ namespace SkiaSharp
|
|||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
public extern static sk_colortable_t sk_pixmap_get_colortable(sk_pixmap_t cpixmap);
|
||||
|
||||
// Mask
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
public extern static IntPtr sk_mask_alloc_image(IntPtr bytes);
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
public extern static void sk_mask_free_image(IntPtr image);
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
public extern static bool sk_mask_is_empty(ref SKMask cmask);
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
public extern static IntPtr sk_mask_compute_image_size(ref SKMask cmask);
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
public extern static IntPtr sk_mask_compute_total_image_size(ref SKMask cmask);
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
public extern static byte sk_mask_get_addr_1(ref SKMask cmask, int x, int y);
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
public extern static byte sk_mask_get_addr_8(ref SKMask cmask, int x, int y);
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
public extern static UInt16 sk_mask_get_addr_lcd_16(ref SKMask cmask, int x, int y);
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
public extern static UInt32 sk_mask_get_addr_32(ref SKMask cmask, int x, int y);
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
public extern static IntPtr sk_mask_get_addr(ref SKMask cmask, int x, int y);
|
||||
|
||||
// Matrix
|
||||
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "sk_document.h"
|
||||
#include "sk_image.h"
|
||||
#include "sk_imagefilter.h"
|
||||
#include "sk_mask.h"
|
||||
#include "sk_maskfilter.h"
|
||||
#include "sk_matrix.h"
|
||||
#include "sk_paint.h"
|
||||
|
@ -86,6 +87,7 @@ void** KeepSkiaCSymbols ()
|
|||
(void*)sk_matrix_map_vector,
|
||||
(void*)sk_matrix_map_radius,
|
||||
(void*)sk_matrix_try_invert,
|
||||
(void*)sk_mask_get_addr,
|
||||
(void*)sk_colortable_new,
|
||||
(void*)gr_context_unref,
|
||||
(void*)sk_xmlstreamwriter_new,
|
||||
|
|
|
@ -123,5 +123,71 @@ namespace SkiaSharp.Tests
|
|||
Assert.AreEqual(40, fitWide.Width);
|
||||
Assert.AreEqual(20, fitWide.Height);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MonochromeMaskBufferIsCopied()
|
||||
{
|
||||
byte rawMask = 1 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 1;
|
||||
var buffer = new byte[] { rawMask };
|
||||
var bounds = new SKRectI(0, 0, 8, 1);
|
||||
UInt32 rowBytes = 1;
|
||||
var format = SKMaskFormat.BW_Format;
|
||||
|
||||
var mask = new SKMask(buffer, bounds, rowBytes, format);
|
||||
|
||||
Assert.AreEqual(rawMask, mask.GetAddr1(0, 0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Alpha8MaskBufferIsCopied()
|
||||
{
|
||||
var buffer = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
var bounds = new SKRectI(0, 0, 4, 2);
|
||||
UInt32 rowBytes = 4;
|
||||
var format = SKMaskFormat.A8_Format;
|
||||
|
||||
var mask = new SKMask(buffer, bounds, rowBytes, format);
|
||||
|
||||
Assert.AreEqual(buffer[0], mask.GetAddr8(0, 0));
|
||||
Assert.AreEqual(buffer[1], mask.GetAddr8(1, 0));
|
||||
Assert.AreEqual(buffer[2], mask.GetAddr8(2, 0));
|
||||
Assert.AreEqual(buffer[3], mask.GetAddr8(3, 0));
|
||||
Assert.AreEqual(buffer[4], mask.GetAddr8(0, 1));
|
||||
Assert.AreEqual(buffer[5], mask.GetAddr8(1, 1));
|
||||
Assert.AreEqual(buffer[6], mask.GetAddr8(2, 1));
|
||||
Assert.AreEqual(buffer[7], mask.GetAddr8(3, 1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThirtyTwoBitMaskBufferIsCopied()
|
||||
{
|
||||
var buffer = new byte[]
|
||||
{
|
||||
0, 0, 255, 255,
|
||||
255, 0, 0, 255,
|
||||
0, 0, 255, 255,
|
||||
255, 0, 0, 255,
|
||||
0, 0, 255, 255,
|
||||
255, 0, 0, 255,
|
||||
0, 0, 255, 255,
|
||||
255, 0, 0, 255
|
||||
};
|
||||
var bounds = new SKRectI(0, 0, 4, 2);
|
||||
UInt32 rowBytes = 16;
|
||||
var format = SKMaskFormat.ARGB32_Format;
|
||||
|
||||
var mask = new SKMask(buffer, bounds, rowBytes, format);
|
||||
|
||||
var red = SKColors.Red;
|
||||
var blue = SKColors.Blue;
|
||||
Assert.AreEqual((uint)red, mask.GetAddr32(0, 0));
|
||||
Assert.AreEqual((uint)blue, mask.GetAddr32(1, 0));
|
||||
Assert.AreEqual((uint)red, mask.GetAddr32(2, 0));
|
||||
Assert.AreEqual((uint)blue, mask.GetAddr32(3, 0));
|
||||
Assert.AreEqual((uint)red, mask.GetAddr32(0, 1));
|
||||
Assert.AreEqual((uint)blue, mask.GetAddr32(1, 1));
|
||||
Assert.AreEqual((uint)red, mask.GetAddr32(2, 1));
|
||||
Assert.AreEqual((uint)blue, mask.GetAddr32(3, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,5 +83,51 @@ namespace SkiaSharp.Tests
|
|||
Assert.AreEqual(SKColors.Green, dstBmp.GetPixel(25, 25));
|
||||
Assert.AreEqual(SKColors.Blue, dstBmp.GetPixel(75, 75));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AlphaMaskIsApplied()
|
||||
{
|
||||
var srcInfo = new SKImageInfo(4, 4);
|
||||
var srcBmp = new SKBitmap(srcInfo);
|
||||
srcBmp.Erase(SKColors.Red);
|
||||
var pixels = srcBmp.Pixels;
|
||||
|
||||
foreach (var pixel in pixels)
|
||||
{
|
||||
Assert.AreEqual(255, pixel.Alpha);
|
||||
}
|
||||
|
||||
var maskBuffer = new byte[]
|
||||
{
|
||||
128, 127, 126, 125,
|
||||
101, 102, 103, 104,
|
||||
96, 95, 94, 93,
|
||||
72, 73, 74, 75
|
||||
};
|
||||
var bounds = new SKRectI(0, 0, 4, 4);
|
||||
uint rowBytes = 4;
|
||||
var format = SKMaskFormat.A8_Format;
|
||||
var mask = new SKMask(maskBuffer, bounds, rowBytes, format);
|
||||
|
||||
srcBmp.InstallMaskPixels(mask);
|
||||
|
||||
pixels = srcBmp.Pixels;
|
||||
Assert.AreEqual(128, pixels[0].Alpha);
|
||||
Assert.AreEqual(127, pixels[1].Alpha);
|
||||
Assert.AreEqual(126, pixels[2].Alpha);
|
||||
Assert.AreEqual(125, pixels[3].Alpha);
|
||||
Assert.AreEqual(101, pixels[4].Alpha);
|
||||
Assert.AreEqual(102, pixels[5].Alpha);
|
||||
Assert.AreEqual(103, pixels[6].Alpha);
|
||||
Assert.AreEqual(104, pixels[7].Alpha);
|
||||
Assert.AreEqual(96, pixels[8].Alpha);
|
||||
Assert.AreEqual(95, pixels[9].Alpha);
|
||||
Assert.AreEqual(94, pixels[10].Alpha);
|
||||
Assert.AreEqual(93, pixels[11].Alpha);
|
||||
Assert.AreEqual(72, pixels[12].Alpha);
|
||||
Assert.AreEqual(73, pixels[13].Alpha);
|
||||
Assert.AreEqual(74, pixels[14].Alpha);
|
||||
Assert.AreEqual(75, pixels[15].Alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче