1 module ui.Draw;
2 
3 import ui.Core;
4 
5 struct Context {
6     package uiDrawContext * _context;
7 
8     this(uiDrawContext * context) {
9         _context = context;
10     }
11 
12     ref stroke(Path path, Brush brush, StrokeParams params) {
13         uiDrawStroke(_context, path._path, brush._brush, params._params);
14         return this;
15     }
16 
17     ref fill(Path path, Brush brush) {
18         uiDrawFill(_context, path._path, brush._brush);
19         return this;
20     }
21 
22     ref transform(Matrix matrix) {
23         uiDrawTransform(_context, matrix._matrix);
24         return this;
25     }
26 
27     ref clip(Path path) {
28         uiDrawClip(_context, path._path);
29         return this;
30     }
31 
32     ref save() {
33         uiDrawSave(_context);
34         return this;
35     }
36 
37     ref restore() {
38         uiDrawRestore(_context);
39         return this;
40     }
41 
42     ref text(double x, double y, TextLayout layout) {
43         uiDrawText(_context, x, y, layout._layout);
44         return this;
45     }
46 }
47 
48 struct Path {
49     private uiDrawPath * _path;
50     static int[uiDrawPath *] _ref;
51 
52     this(FillMode mode) {
53         _path = uiDrawNewPath(mode);
54         _ref[_path] = 1;
55     }
56 
57     ~this() {
58         _ref[_path]--;
59         if (_ref[_path] == 0) {
60             uiDrawFreePath(_path);
61             _ref.remove(_path);
62         }
63     }
64 
65     this(this) {
66         _ref[_path]++;
67     }
68 
69     ref newFigure(double x, double y) {
70         uiDrawPathNewFigure(_path, x, y);
71         return this;
72     }
73 
74     ref newFigureWithArc(
75         double xCenter, double yCenter,
76         double radius, double startAngle, double sweep, bool negative
77     ) {
78         uiDrawPathNewFigureWithArc(_path, xCenter, yCenter,
79             radius, startAngle, sweep, cast(int) negative);
80         return this;
81     }
82 
83     ref lineTo(double x, double y) {
84         uiDrawPathLineTo(_path, x, y);
85         return this;
86     }
87 
88     ref arcTo(
89         double xCenter, double yCenter, double radius,
90         double startAngle, double sweep, bool negative
91     ) {
92         uiDrawPathArcTo(_path, xCenter, yCenter,
93             radius, startAngle, sweep, cast(int) negative);
94         return this;
95     }
96 
97     ref bezierTo(double c1x, double c1y, double c2x, double c2y, double endX, double endY) {
98         uiDrawPathBezierTo(_path, c1x, c1y, c2x, c2y, endX, endY);
99         return this;
100     }
101 
102     ref closeFigure() {
103         uiDrawPathCloseFigure(_path);
104         return this;
105     }
106 
107     ref addRectangle(double x, double y, double width, double height) {
108         uiDrawPathAddRectangle(_path, x, y, width, height);
109         return this;
110     }
111 
112     ref end() {
113         uiDrawPathEnd(_path);
114         return this;
115     }
116 }
117 
118 struct Matrix {
119     private uiDrawMatrix * _matrix = new uiDrawMatrix;
120 
121     @property pragma(inline, true) {
122         ref m11() {
123             return _matrix.M11;
124         }
125         ref m12() {
126             return _matrix.M12;
127         }
128         ref m21() {
129             return _matrix.M21;
130         }
131         ref m22() {
132             return _matrix.M22;
133         }
134         ref m31() {
135             return _matrix.M31;
136         }
137         ref m32() {
138             return _matrix.M32;
139         }
140     }
141 
142     ref setIdentity() {
143         uiDrawMatrixSetIdentity(_matrix);
144         return this;
145     }
146 
147     ref translate(double x, double y) {
148         uiDrawMatrixTranslate(_matrix, x, y);
149         return this;
150     }
151 
152     ref scale(double xCenter, double yCenter, double x, double y) {
153         uiDrawMatrixScale(_matrix, xCenter, yCenter, x, y);
154         return this;
155     }
156 
157     ref rotate(double x, double y, double amount) {
158         uiDrawMatrixRotate(_matrix, x, y, amount);
159         return this;
160     }
161 
162     ref skew(double x, double y, double xamount, double yamount) {
163         uiDrawMatrixSkew(_matrix, x, y, xamount, yamount);
164         return this;
165     }
166 
167     ref multiply(ref Matrix other) {
168         uiDrawMatrixMultiply(_matrix, other._matrix);
169         return this;
170     }
171 
172     bool invertible() {
173         return cast(bool) uiDrawMatrixInvertible(_matrix);
174     }
175 
176     bool invert() {
177         return cast(bool) uiDrawMatrixInvert(_matrix);
178     }
179 
180     ref transformPoint(ref double x, ref double y) {
181         uiDrawMatrixTransformPoint(_matrix, &x, &y);
182         return this;
183     }
184 
185     ref transformSize(ref double x, ref double y) {
186         uiDrawMatrixTransformSize(_matrix, &x, &y);
187         return this;
188     }
189 }
190 
191 struct Brush {
192     private uiDrawBrush * _brush = new uiDrawBrush;
193 
194     @property pragma(inline, true) {
195         ref type() {
196             return _brush.Type;
197         }
198 
199         ref r() {
200             return _brush.R;
201         }
202         ref g() {
203             return _brush.G;
204         }
205         ref b() {
206             return _brush.B;
207         }
208         ref a() {
209             return _brush.A;
210         }
211 
212         ref x0() {
213             return _brush.X0;
214         }
215         ref y0() {
216             return _brush.X1;
217         }
218         ref x1() {
219             return _brush.Y0;
220         }
221         ref y1() {
222             return _brush.Y1;
223         }
224         ref oterRadius() {
225             return _brush.OuterRadius;
226         }
227         auto stops() {
228             return BrushGradientStop(_brush.Stops);
229         }
230         void stops(BrushGradientStop stop) {
231             _brush.Stops = stop._stop;
232         }
233         ref numStops() {
234             return _brush.NumStops;
235         }
236     }
237 }
238 
239 struct BrushGradientStop {
240     private uiDrawBrushGradientStop * _stop = new uiDrawBrushGradientStop;
241 
242     @property pragma(inline, true) {
243         ref pos() {
244             return _stop.Pos;
245         }
246         ref r() {
247             return _stop.R;
248         }
249         ref g() {
250             return _stop.G;
251         }
252         ref b() {
253             return _stop.B;
254         }
255         ref a() {
256             return _stop.A;
257         }
258     }
259 }
260 
261 struct StrokeParams {
262     private uiDrawStrokeParams * _params = new uiDrawStrokeParams;
263 
264     @property pragma(inline, true) {
265         ref cap() {
266             return _params.Cap;
267         }
268         ref join() {
269             return _params.Join;
270         }
271         ref thickness() {
272             return _params.Thickness;
273         }
274         ref miterLimit() {
275             return _params.MiterLimit;
276         }
277         ref dashes() {
278             return _params.Dashes;
279         }
280         ref numDashes() {
281             return _params.NumDashes;
282         }
283         ref dashPhase() {
284             return _params.DashPhase;
285         }
286     }
287 }
288 
289 struct FontFamilies {
290     private uiDrawFontFamilies * _families;
291     static int[uiDrawFontFamilies *] _ref;
292 
293     static FontFamilies create() {
294         return FontFamilies(uiDrawListFontFamilies);
295     }
296     private this(uiDrawFontFamilies * families) {
297         _families = families;
298         _ref[_families] = 1;
299     }
300 
301     ~this() {
302         _ref[_families]--;
303         if (_ref[_families] == 0) {
304             uiDrawFreeFontFamilies(_families);
305             _ref.remove(_families);
306         }
307     }
308 
309     @disable this();
310 
311     this(this) {
312         _ref[_families]++;
313     }
314 
315     size_t numFamilies() {
316         return cast(size_t) uiDrawFontFamiliesNumFamilies(_families);
317     }
318 
319     string family(size_t n) {
320         return uiDrawFontFamiliesFamily(_families, cast(int) n).toString;
321     }
322 }
323 
324 struct TextFontDescriptor {
325     private uiDrawTextFontDescriptor * _descriptor = new uiDrawTextFontDescriptor;
326 
327     @property pragma(inline, true) {
328         string family() {
329             import core.stdc.string: strlen;
330             auto c = _descriptor.Family;
331             return c[0..strlen(c)].idup;
332         }
333         void family(string text) {
334             import std.string: toStringz;
335             _descriptor.Family = text.toStringz;
336         }
337         ref size() {
338             return _descriptor.Size;
339         }
340         ref weight() {
341             return _descriptor.Weight;
342         }
343         ref italic() {
344             return _descriptor.Italic;
345         }
346         ref stretch() {
347             return _descriptor.Stretch;
348         }
349     }
350 
351     TextFont loadClosestFont() {
352         return TextFont(uiDrawLoadClosestFont(_descriptor));
353     }
354 }
355 
356 struct TextFontMetrics {
357     private uiDrawTextFontMetrics * _metrics = new uiDrawTextFontMetrics;
358 
359     @property pragma(inline, true) {
360         ref ascent() {
361             return _metrics.Ascent;
362         }
363         ref descent() {
364             return _metrics.Descent;
365         }
366         ref leading() {
367             return _metrics.Leading;
368         }
369         ref underlinePos() {
370             return _metrics.UnderlinePos;
371         }
372         ref underlineThickness() {
373             return _metrics.UnderlineThickness;
374         }
375     }
376 }
377 
378 struct TextFont {
379     private uiDrawTextFont * _font;
380     static int[uiDrawTextFont *] _ref;
381 
382     this(uiDrawTextFont * font) {
383         _font = font;
384         _ref[_font] = 1;
385     }
386 
387     ~this() {
388         _ref[_font]--;
389         if (_ref[_font] == 0) {
390             uiDrawFreeTextFont(_font);
391             _ref.remove(_font);
392         }
393     }
394 
395     this(this) {
396         _ref[_font]++;
397     }
398 
399     auto handle() {
400         return uiDrawTextFontHandle(_font);
401     }
402 
403     ref describe(TextFontDescriptor descriptor) {
404         uiDrawTextFontDescribe(_font, descriptor._descriptor);
405         return this;
406     }
407 
408     ref getMetrics(TextFontMetrics metrics) {
409         uiDrawTextFontGetMetrics(_font, metrics._metrics);
410         return this;
411     }
412 }
413 
414 struct TextLayout {
415     private uiDrawTextLayout * _layout;
416     static int[uiDrawTextLayout *] _ref;
417 
418     this(string text, TextFont font, double width) {
419         _layout = uiDrawNewTextLayout(text.ptr, font._font, width);
420         _ref[_layout] = 1;
421     }
422 
423     ~this() {
424         _ref[_layout]--;
425         if (_ref[_layout] == 0) {
426             uiDrawFreeTextLayout(_layout);
427             _ref.remove(_layout);
428         }
429     }
430 
431     this(this) {
432         _ref[_layout]++;
433     }
434 
435     ref setWidth(double width) {
436         uiDrawTextLayoutSetWidth(_layout, width);
437         return this;
438     }
439 
440     ref extents(ref double width, ref double height) {
441         uiDrawTextLayoutExtents(_layout, &width, &height);
442         return this;
443     }
444 
445     ref setColor(int startChar, int endChar, double r, double g, double b, double a) {
446         uiDrawTextLayoutSetColor(_layout, startChar, endChar, r, g, b, a);
447         return this;
448     }
449 }