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 class Matrix {
119     private uiDrawMatrix * _matrix;
120     this()
121     {
122         _matrix = new uiDrawMatrix;
123     }
124     @property pragma(inline, true) {
125         ref m11() {
126             return _matrix.M11;
127         }
128         ref m12() {
129             return _matrix.M12;
130         }
131         ref m21() {
132             return _matrix.M21;
133         }
134         ref m22() {
135             return _matrix.M22;
136         }
137         ref m31() {
138             return _matrix.M31;
139         }
140         ref m32() {
141             return _matrix.M32;
142         }
143     }
144 
145     Matrix setIdentity() {
146         uiDrawMatrixSetIdentity(_matrix);
147         return this;
148     }
149 
150     Matrix translate(double x, double y) {
151         uiDrawMatrixTranslate(_matrix, x, y);
152         return this;
153     }
154 
155     Matrix scale(double xCenter, double yCenter, double x, double y) {
156         uiDrawMatrixScale(_matrix, xCenter, yCenter, x, y);
157         return this;
158     }
159 
160     Matrix rotate(double x, double y, double amount) {
161         uiDrawMatrixRotate(_matrix, x, y, amount);
162         return this;
163     }
164 
165     Matrix skew(double x, double y, double xamount, double yamount) {
166         uiDrawMatrixSkew(_matrix, x, y, xamount, yamount);
167         return this;
168     }
169 
170     Matrix multiply(ref Matrix other) {
171         uiDrawMatrixMultiply(_matrix, other._matrix);
172         return this;
173     }
174 
175     bool invertible() {
176         return cast(bool) uiDrawMatrixInvertible(_matrix);
177     }
178 
179     bool invert() {
180         return cast(bool) uiDrawMatrixInvert(_matrix);
181     }
182 
183     Matrix transformPoint(ref double x, ref double y) {
184         uiDrawMatrixTransformPoint(_matrix, &x, &y);
185         return this;
186     }
187 
188     Matrix transformSize(ref double x, ref double y) {
189         uiDrawMatrixTransformSize(_matrix, &x, &y);
190         return this;
191     }
192 }
193 
194 class Brush {
195     private uiDrawBrush * _brush;
196     
197     this()
198     {
199          _brush = new uiDrawBrush;
200     }
201     @property pragma(inline, true) {
202         ref type() {
203             return _brush.Type;
204         }
205 
206         ref r() {
207             return _brush.R;
208         }
209         ref g() {
210             return _brush.G;
211         }
212         ref b() {
213             return _brush.B;
214         }
215         ref a() {
216             return _brush.A;
217         }
218 
219         ref x0() {
220             return _brush.X0;
221         }
222         ref y0() {
223             return _brush.X1;
224         }
225         ref x1() {
226             return _brush.Y0;
227         }
228         ref y1() {
229             return _brush.Y1;
230         }
231         ref oterRadius() {
232             return _brush.OuterRadius;
233         }
234         auto stops() {
235             return new BrushGradientStop(_brush.Stops);
236         }
237         void stops(BrushGradientStop stop) {
238             _brush.Stops = stop._stop;
239         }
240         ref numStops() {
241             return _brush.NumStops;
242         }
243     }
244 }
245 
246 class BrushGradientStop {
247     private uiDrawBrushGradientStop * _stop;
248     this()
249     {
250         _stop = new uiDrawBrushGradientStop;
251     }
252     this(uiDrawBrushGradientStop*  _stops)
253     {
254         _stop=_stops;
255     }
256     @property pragma(inline, true) {
257         ref pos() {
258             return _stop.Pos;
259         }
260         ref r() {
261             return _stop.R;
262         }
263         ref g() {
264             return _stop.G;
265         }
266         ref b() {
267             return _stop.B;
268         }
269         ref a() {
270             return _stop.A;
271         }
272     }
273 }
274 
275 class StrokeParams {
276     private uiDrawStrokeParams * _params;
277     this()
278     {
279         _params = new uiDrawStrokeParams;
280     }
281     @property pragma(inline, true) {
282         ref cap() {
283             return _params.Cap;
284         }
285         ref join() {
286             return _params.Join;
287         }
288         ref thickness() {
289             return _params.Thickness;
290         }
291         ref miterLimit() {
292             return _params.MiterLimit;
293         }
294         ref dashes() {
295             return _params.Dashes;
296         }
297         ref numDashes() {
298             return _params.NumDashes;
299         }
300         ref dashPhase() {
301             return _params.DashPhase;
302         }
303     }
304 }
305 
306 struct FontFamilies {
307     private uiDrawFontFamilies * _families;
308     static int[uiDrawFontFamilies *] _ref;
309 
310     static FontFamilies create() {
311         return FontFamilies(uiDrawListFontFamilies);
312     }
313     private this(uiDrawFontFamilies * families) {
314         _families = families;
315         _ref[_families] = 1;
316     }
317 
318     ~this() {
319         _ref[_families]--;
320         if (_ref[_families] == 0) {
321             uiDrawFreeFontFamilies(_families);
322             _ref.remove(_families);
323         }
324     }
325 
326     @disable this();
327 
328     this(this) {
329         _ref[_families]++;
330     }
331 
332     size_t numFamilies() {
333         return cast(size_t) uiDrawFontFamiliesNumFamilies(_families);
334     }
335 
336     string family(size_t n) {
337         return uiDrawFontFamiliesFamily(_families, cast(int) n).toString;
338     }
339 }
340 
341 class TextFontDescriptor {
342     private uiDrawTextFontDescriptor * _descriptor;
343     this()
344     {
345         _descriptor = new uiDrawTextFontDescriptor;
346     }
347     @property pragma(inline, true) {
348         string family() {
349             import core.stdc.string: strlen;
350             auto c = _descriptor.Family;
351             return c[0..strlen(c)].idup;
352         }
353         void family(string text) {
354             import std.string: toStringz;
355             _descriptor.Family = text.toStringz;
356         }
357         ref size() {
358             return _descriptor.Size;
359         }
360         ref weight() {
361             return _descriptor.Weight;
362         }
363         ref italic() {
364             return _descriptor.Italic;
365         }
366         ref stretch() {
367             return _descriptor.Stretch;
368         }
369     }
370 
371     TextFont loadClosestFont() {
372         return TextFont(uiDrawLoadClosestFont(_descriptor));
373     }
374 }
375 
376 class TextFontMetrics {
377     private uiDrawTextFontMetrics * _metrics;
378     this()
379     {
380         _metrics = new uiDrawTextFontMetrics;
381     }
382     @property pragma(inline, true) {
383         ref ascent() {
384             return _metrics.Ascent;
385         }
386         ref descent() {
387             return _metrics.Descent;
388         }
389         ref leading() {
390             return _metrics.Leading;
391         }
392         ref underlinePos() {
393             return _metrics.UnderlinePos;
394         }
395         ref underlineThickness() {
396             return _metrics.UnderlineThickness;
397         }
398     }
399 }
400 
401 struct TextFont {
402     private uiDrawTextFont * _font;
403     static int[uiDrawTextFont *] _ref;
404 
405     this(uiDrawTextFont * font) {
406         _font = font;
407         _ref[_font] = 1;
408     }
409 
410     ~this() {
411         _ref[_font]--;
412         if (_ref[_font] == 0) {
413             uiDrawFreeTextFont(_font);
414             _ref.remove(_font);
415         }
416     }
417 
418     this(this) {
419         _ref[_font]++;
420     }
421 
422     auto handle() {
423         return uiDrawTextFontHandle(_font);
424     }
425 
426     ref describe(TextFontDescriptor descriptor) {
427         uiDrawTextFontDescribe(_font, descriptor._descriptor);
428         return this;
429     }
430 
431     ref getMetrics(TextFontMetrics metrics) {
432         uiDrawTextFontGetMetrics(_font, metrics._metrics);
433         return this;
434     }
435 }
436 
437 struct TextLayout {
438     private uiDrawTextLayout * _layout;
439     static int[uiDrawTextLayout *] _ref;
440 
441     this(string text, TextFont font, double width) {
442         import std.string: toStringz;
443         _layout = uiDrawNewTextLayout(text.toStringz, font._font, width);
444         _ref[_layout] = 1;
445     }
446 
447     ~this() {
448         _ref[_layout]--;
449         if (_ref[_layout] == 0) {
450             uiDrawFreeTextLayout(_layout);
451             _ref.remove(_layout);
452         }
453     }
454 
455     this(this) {
456         _ref[_layout]++;
457     }
458 
459     ref setWidth(double width) {
460         uiDrawTextLayoutSetWidth(_layout, width);
461         return this;
462     }
463 
464     ref extents(ref double width, ref double height) {
465         uiDrawTextLayoutExtents(_layout, &width, &height);
466         return this;
467     }
468 
469     ref setColor(int startChar, int endChar, double r, double g, double b, double a) {
470         uiDrawTextLayoutSetColor(_layout, startChar, endChar, r, g, b, a);
471         return this;
472     }
473 }