1 module skia.SKDrawable; 2 3 import skia.Definitions; 4 import skia.Exceptions; 5 import skia.GRDefinitions; 6 import skia.MathTypes; 7 import skia.SKCanvas; 8 import skia.SKPictureRecorder; 9 import skia.SKObject; 10 import skia.SKMatrix; 11 import skia.SKPicture; 12 import skia.SkiaApi; 13 14 import core.atomic; 15 16 class SKDrawable : SKObject { 17 private __gshared SKManagedDrawableDelegates delegates; 18 19 private shared int fromNative; 20 21 shared static this () 22 { 23 delegates.fDraw = &DrawInternal; 24 delegates.fGetBounds = &GetBoundsInternal; 25 delegates.fNewPictureSnapshot = &NewPictureSnapshotInternal; 26 delegates.fDestroy = &DestroyInternal; 27 28 SkiaApi.sk_manageddrawable_set_procs (delegates); 29 } 30 31 this() { 32 this(true); 33 } 34 35 protected this(bool owns) { 36 super(null, owns); 37 // auto ctx = DelegateProxies.CreateUserData(this, true); 38 void* ctx = cast(void*) this; 39 Handle = SkiaApi.sk_manageddrawable_new(ctx); 40 41 if (Handle is null) { 42 throw new InvalidOperationException("Unable to create a new SKDrawable instance."); 43 } 44 } 45 46 this(void* x, bool owns) { 47 super(x, owns); 48 } 49 50 // protected override void Dispose(bool disposing) { 51 // return super.Dispose(disposing); 52 // } 53 54 protected override void DisposeNative() { 55 // if (Interlocked.CompareExchange(fromNative, 0, 0) == 0) 56 int v = cas(&fromNative, 0, 0); 57 if (v == 0) 58 SkiaApi.sk_drawable_unref(cast(sk_drawable_t*) Handle); 59 } 60 61 uint GenerationId() { 62 return SkiaApi.sk_drawable_get_generation_id(cast(sk_drawable_t*) Handle); 63 } 64 65 SKRect Bounds() { 66 SKRect bounds; 67 SkiaApi.sk_drawable_get_bounds(cast(sk_drawable_t*) Handle, &bounds); 68 return bounds; 69 } 70 71 void Draw(SKCanvas canvas, ref SKMatrix matrix) { 72 SKMatrix* m = &matrix; 73 SkiaApi.sk_drawable_draw(cast(sk_drawable_t*) Handle, cast(sk_canvas_t*) canvas.Handle, m); 74 } 75 76 void Draw(SKCanvas canvas, float x, float y) { 77 auto matrix = SKMatrix.CreateTranslation(x, y); 78 Draw(canvas, matrix); 79 } 80 81 // do not unref as this is a plain pointer return, not a reference counted pointer 82 SKPicture Snapshot () 83 { 84 return SKPicture.GetObject (SkiaApi.sk_drawable_new_picture_snapshot (cast(sk_drawable_t*)Handle), true, false); 85 } 86 87 void NotifyDrawingChanged() { 88 return SkiaApi.sk_drawable_notify_drawing_changed(cast(sk_drawable_t*) Handle); 89 } 90 91 protected void OnDraw(SKCanvas canvas) { 92 } 93 94 protected SKRect OnGetBounds() { 95 return SKRect.Empty; 96 } 97 98 protected SKPicture OnSnapshot() { 99 SKPictureRecorder recorder = new SKPictureRecorder(); 100 scope (exit) { 101 recorder.Dispose(); 102 } 103 104 auto canvas = recorder.BeginRecording(Bounds); 105 Draw(canvas, 0, 0); 106 return recorder.EndRecording(); 107 } 108 109 extern (C) { 110 private static void DrawInternal(void* d, void* context, void* canvas) { 111 // auto drawable = DelegateProxies.GetUserData!(SKDrawable)(cast(void*) context, _); 112 SKDrawable drawable = cast(SKDrawable) context; 113 drawable.OnDraw(SKCanvas.GetObject(canvas, false)); 114 } 115 116 private static void GetBoundsInternal(void* d, void* context, SKRect* rect) { 117 // auto drawable = DelegateProxies.GetUserData!(SKDrawable)(cast(void*) context, _); 118 SKDrawable drawable = cast(SKDrawable) context; 119 auto bounds = drawable.OnGetBounds(); 120 *rect = bounds; 121 } 122 123 private static void* NewPictureSnapshotInternal(void* d, void* context) { 124 // auto drawable = DelegateProxies.GetUserData!(SKDrawable)(cast(void*) context, _); 125 SKDrawable drawable = cast(SKDrawable) context; 126 return drawable.OnSnapshot().Handle ? drawable.OnSnapshot().Handle : null; 127 } 128 129 private static void DestroyInternal (void* d, void* context) 130 { 131 // auto drawable = DelegateProxies.GetUserData<SKDrawable> (cast(void*)context, var gch); 132 SKDrawable drawable = cast(SKDrawable) context; 133 if (drawable !is null) { 134 // Interlocked.Exchange ( drawable.fromNative, 1); 135 atomicStore(drawable.fromNative, 1); 136 drawable.Dispose (); 137 } 138 } 139 } 140 141 static SKDrawable GetObject(void* handle) { 142 return GetOrAddObject!(SKDrawable)(handle, delegate SKDrawable(h, o) { 143 return new SKDrawable(h, o); 144 }); 145 // return GetOrAddObject!(SKDrawable) (handle, (h, o){return new SKDrawable (h, o);}); 146 } 147 148 }