1 module skia.SKMask; 2 3 import skia.Definitions; 4 import skia.MathTypes; 5 import skia.SkiaApi; 6 import skia.IDisposable; 7 import skia.Exceptions; 8 9 import std.format; 10 11 struct SKMask { 12 SKRectI fBounds; 13 uint fRowBytes; 14 SKMaskFormat fFormat; 15 void* fImage; 16 this(void* image, SKRectI bounds, uint rowBytes, SKMaskFormat format) { 17 fBounds = bounds; 18 fRowBytes = rowBytes; 19 fFormat = format; 20 fImage = cast(byte*) image; 21 } 22 23 this(SKRectI bounds, uint rowBytes, SKMaskFormat format) { 24 fBounds = bounds; 25 fRowBytes = rowBytes; 26 fFormat = format; 27 fImage = null; 28 } 29 30 // properties 31 32 // readonly void* Image() 33 void* Image() { 34 return cast(void*) fImage; 35 } 36 37 void Image(void* value) { 38 fImage = cast(byte*) value; 39 } 40 41 // Span!(byte) GetImageSpan () 42 // { 43 // return new byte[] (cast(void*)Image, cast(int)ComputeTotalImageSize ()); 44 // } 45 46 // readonly SKRectI Bounds() 47 SKRectI Bounds() { 48 return fBounds; 49 } 50 51 void Bounds(SKRectI value) { 52 fBounds = value; 53 } 54 55 uint RowBytes() { 56 return fRowBytes; 57 } 58 59 // void uint RowBytes(uint value) 60 // { 61 // fRowBytes = value; 62 // } 63 64 // readonly SKMaskFormat Format() 65 // { 66 // return fFormat; 67 // } 68 69 void Format(SKMaskFormat value) { 70 fFormat = value; 71 } 72 73 const bool IsEmpty() { 74 SKMask* t = cast(SKMask*)&this; 75 return SkiaApi.sk_mask_is_empty(t); 76 } 77 78 // allocate / free 79 80 long AllocateImage() { 81 SKMask* t = &this; 82 { 83 auto size = SkiaApi.sk_mask_compute_total_image_size(t); 84 fImage = SkiaApi.sk_mask_alloc_image(size); 85 return cast(long) size; 86 } 87 } 88 89 void FreeImage() { 90 if (fImage !is null) { 91 SKMask.FreeImage(cast(void*) fImage); 92 fImage = null; 93 } 94 } 95 96 // Compute* 97 98 const long ComputeImageSize() { 99 SKMask* t = cast(SKMask*)&this; 100 return cast(long) SkiaApi.sk_mask_compute_image_size(t); 101 } 102 103 const long ComputeTotalImageSize() { 104 SKMask* t = cast(SKMask*)&this; 105 return cast(long) SkiaApi.sk_mask_compute_total_image_size(t); 106 } 107 108 // GetAddr* 109 110 const byte GetAddr1(int x, int y) { 111 SKMask* t = cast(SKMask*)&this; 112 return *SkiaApi.sk_mask_get_addr_1(t, x, y); 113 } 114 115 const byte GetAddr8(int x, int y) { 116 SKMask* t = cast(SKMask*)&this; 117 return *SkiaApi.sk_mask_get_addr_8(t, x, y); 118 } 119 120 const ushort GetAddr16(int x, int y) { 121 SKMask* t = cast(SKMask*)&this; 122 return *SkiaApi.sk_mask_get_addr_lcd_16(t, x, y); 123 } 124 125 const uint GetAddr32(int x, int y) { 126 SKMask* t = cast(SKMask*)&this; 127 return *SkiaApi.sk_mask_get_addr_32(t, x, y); 128 } 129 130 const void* GetAddr(int x, int y) { 131 SKMask* t = cast(SKMask*)&this; 132 return cast(void*) SkiaApi.sk_mask_get_addr(t, x, y); 133 } 134 135 // statics 136 137 static void* AllocateImage(long size) { 138 return cast(void*) SkiaApi.sk_mask_alloc_image(cast(void*) size); 139 } 140 141 static void FreeImage(void* image) { 142 return SkiaApi.sk_mask_free_image(cast(byte*) image); 143 } 144 145 static SKMask Create(byte[] image, SKRectI bounds, uint rowBytes, SKMaskFormat format) { 146 return Create(cast(const(byte)[]) image, bounds, rowBytes, format); 147 } 148 149 static SKMask Create(const(byte)[] image, SKRectI bounds, uint rowBytes, SKMaskFormat format) { 150 // create the mask 151 auto mask = SKMask(bounds, rowBytes, format); 152 153 // calculate the size 154 auto imageSize = cast(int) mask.ComputeTotalImageSize(); 155 156 // is there the right amount of space in the mask 157 if (image.length != imageSize) { 158 // Note: buffer.Length must match bounds.Height * rowBytes 159 auto expectedSize = bounds.Height * rowBytes; 160 auto message = "Length of image ({image.Length}) does not match the computed size of the mask ({expectedSize}). Check the {bounds.stringof} and {rowBytes.stringof}."; 161 throw new ArgumentException(message); 162 } 163 164 // allocate and copy the image data 165 mask.AllocateImage(); 166 // image.CopyTo (new byte[] (cast(void*)mask.Image, imageSize)); 167 168 byte* buffer = cast(byte*)mask.Image; 169 for(size_t i = 0; i<imageSize; i++) { 170 buffer[i] = image[i]; 171 } 172 173 // return the mask 174 return mask; 175 } 176 } 177 178 class SKAutoMaskFreeImage : IDisposable { 179 private void* image; 180 181 this(void* maskImage) { 182 image = maskImage; 183 } 184 185 void Dispose() { 186 if (image !is null) { 187 SKMask.FreeImage(image); 188 image = null; 189 } 190 } 191 }