This commit is contained in:
Tyler Hoeflicker 2017-01-18 14:02:33 -08:00
Родитель 4d13effb74
Коммит c7b7b496a1
6 изменённых файлов: 209 добавлений и 0 удалений

Просмотреть файл

@ -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);
}
}
}