1 module nanovg.packer;
2 
3 // Packed Classes
4 import nanovg.h;
5 import std.typecons, std..string;
6 
7 enum LineCap : NVGlineCap
8 {
9 	BUTT = NVG_BUTT, ROUND = NVG_ROUND,
10 	SQUARE = NVG_SQUARE, BEVEL = NVG_BEVEL,
11 	MITER = NVG_MITER
12 }
13 enum TextAlign : NVGalign
14 {
15 	LEFT = NVG_ALIGN_LEFT, CENTER = NVG_ALIGN_CENTER, RIGHT = NVG_ALIGN_RIGHT,
16 	TOP = NVG_ALIGN_TOP, MIDDLE = NVG_ALIGN_MIDDLE, BOTTOM = NVG_ALIGN_BOTTOM,
17 	BASELINE = NVG_ALIGN_BASELINE
18 }
19 enum ImageFlags : NVGimageFlags
20 {
21 	GENERATE_MIPMAPS = NVG_IMAGE_GENERATE_MIPMAPS,
22 	REPEATX = NVG_IMAGE_REPEATX, REPEATY = NVG_IMAGE_REPEATY,
23 	FLIPY = NVG_IMAGE_FLIPY, PREMULTIPLIED = NVG_IMAGE_PREMULTIPLIED
24 }
25 enum Winding : NVGwinding
26 {
27 	CCW = NVG_CCW,
28 	CW = NVG_CW
29 }
30 struct Matrix3x2
31 {
32 	float[6] elements;
33 	static auto FromXF(float[6] xf)
34 	{
35 		return Matrix3x2(xf);
36 	}
37 	
38 	// Matrix Maths //
39 	static @property Identity()
40 	{
41 		float[6] xform;
42 		nvgTransformIdentity(xform.ptr);
43 		return FromXF(xform);
44 	}
45 	auto translate(float tx, float ty) { nvgTransformTranslate(this.elements.ptr, tx, ty); return this; }
46 	auto scale(float sx, float sy) { nvgTransformScale(this.elements.ptr, sx, sy); return this; }
47 	auto rotate(float a) { nvgTransformRotate(this.elements.ptr, a); return this; }
48 	auto skewX(float a) { nvgTransformSkewX(this.elements.ptr, a); return this; }
49 	auto skewY(float a) { nvgTransformSkewY(this.elements.ptr, a); return this; }
50 	auto opBinary(string op)(Matrix3x2 other) if(op == "*")
51 	{
52 		float[6] elm_t; elm_t[] = this.elements[];
53 		nvgTransformMultiply(elm_t.ptr, other.elements.ptr);
54 		return FromXF(elm_t);
55 	}
56 	auto opOpAssign(string op)(Matrix3x2 other) if(op == "*")
57 	{
58 		nvgTransformMultiply(this.elements.ptr, other.elements.ptr);
59 	}
60 	auto inverse()
61 	{
62 		float[6] dst;
63 		nvgTransformInverse(dst.ptr, this.elements.ptr);
64 		this.elements[] = dst[];
65 	}
66 	auto transformPoint(float px, float py)
67 	{
68 		float dx, dy;
69 		nvgTransformPoint(&dx, &dy, this.elements.ptr, px, py);
70 		return tuple(dx, dy);
71 	}
72 }
73 class Texture
74 {
75 	NVGcontext* relatedContext;
76 	int id;
77 	
78 	public this(NVGcontext* pc, int i)
79 	{
80 		this.relatedContext = pc;
81 		this.id = i;
82 	}
83 	public ~this()
84 	{
85 		this.relatedContext.nvgDeleteImage(this.id);
86 	}
87 	public bool update(const(byte[]) data)
88 	{
89 		return this.relatedContext.nvgUpdateImage(this.id, data.ptr) != 0;
90 	}
91 	public auto size()
92 	{
93 		int w, h;
94 		this.relatedContext.nvgImageSize(this.id, &w, &h);
95 		return tuple(w, h);
96 	}
97 }
98 alias Font = int;
99 alias GlyphPosition = NVGglyphPosition;
100 alias TextRow = NVGtextRow;
101 class Context(alias InitializerFun, alias DisposerFun)
102 {
103 	NVGcontext* pInternal;
104 	
105 	public this()
106 	{
107 		this.pInternal = InitializerFun();
108 	}
109 	public ~this()
110 	{
111 		DisposerFun(this.pInternal);
112 	}
113 	
114 	// StateController //
115 	public void save() { this.pInternal.nvgSave(); }
116 	public void restore() { this.pInternal.nvgRestore(); }
117 	public void reset() { this.pInternal.nvgReset(); }
118 	
119 	// RenderingManagement //
120 	public auto beginFrame(int w, int h, float aspect) { this.pInternal.nvgBeginFrame(w, h, aspect); }
121 	public auto endFrame() { this.pInternal.nvgEndFrame(); }
122 	
123 	// RenderSetters //
124 	public @property
125 	{
126 		void strokeColor(NVGcolor color) { this.pInternal.nvgStrokeColor(color); }
127 		void strokePaint(NVGpaint paint) { this.pInternal.nvgStrokePaint(paint); }
128 		void fillColor(NVGcolor color) { this.pInternal.nvgFillColor(color); }
129 		void fillPaint(NVGpaint paint) { this.pInternal.nvgFillPaint(paint); }
130 		void miterLimit(float limit) { this.pInternal.nvgMiterLimit(limit); }
131 		void strokeWidth(float width) { this.pInternal.nvgStrokeWidth(width); }
132 		void lineCap(LineCap cap) { this.pInternal.nvgLineCap(cap); }
133 		void lineJoin(int join) { this.pInternal.nvgLineJoin(join); }
134 		void globalAlpha(float alpha) { this.pInternal.nvgGlobalAlpha(alpha); }
135 	}
136 	
137 	// Transforms //
138 	public void resetTransform() { this.pInternal.nvgResetTransform(); }
139 	public @property void transform(Matrix3x2 matr)
140 	{
141 		this.pInternal.nvgTransform(matr.elements[0], matr.elements[1], matr.elements[2],
142 			matr.elements[3], matr.elements[4], matr.elements[5]);
143 	}
144 	public @property auto transform()
145 	{
146 		float[6] xform;
147 		this.pInternal.nvgCurrentTransform(xform.ptr);
148 		return Matrix3x2.FromXF(xform);
149 	}
150 	public auto translate(float x, float y) { this.pInternal.nvgTranslate(x, y); return this; }
151 	public auto rotate(float angle) { this.pInternal.nvgRotate(angle); return this; }
152 	public auto skewX(float angle) { this.pInternal.nvgSkewX(angle); return this; }
153 	public auto skewY(float angle) { this.pInternal.nvgSkewY(angle); return this; }
154 	public auto scale(float x, float y) { this.pInternal.nvgScale(x, y); return this; }
155 	
156 	// Images //
157 	public Texture createImage(string filePath, ImageFlags imageFlags)
158 	{
159 		return new Texture(this.pInternal, this.pInternal.nvgCreateImage(filePath.toStringz, imageFlags));
160 	}
161 	public Texture createImageMem(ImageFlags imageFlags, byte[] data)
162 	{
163 		return new Texture(this.pInternal, this.pInternal.nvgCreateImageMem(imageFlags, data.ptr, cast(int)data.length));
164 	}
165 	public Texture createImageRGBA(int w, int h, ImageFlags imageFlags, const(byte[]) data)
166 	{
167 		return new Texture(this.pInternal, this.pInternal.nvgCreateImageRGBA(w, h, imageFlags, data.ptr));
168 	}
169 	
170 	// PaintMaking //
171 	public auto createLinearGradientPaint(float sx, float sy, float ex, float ey, NVGcolor col1, NVGcolor col2)
172 	{
173 		return this.pInternal.nvgLinearGradient(sx, sy, ex, ey, col1, col2);
174 	}
175 	public auto createBoxGradientPaint(float x, float y, float w, float h, float r, float f, NVGcolor icol, NVGcolor ocol)
176 	{
177 		return this.pInternal.nvgBoxGradient(x, y, w, h, r, f, icol, ocol);
178 	}
179 	public auto createRadialGradientPaint(float cx, float cy, float ir, float or, NVGcolor icol, NVGcolor ocol)
180 	{
181 		return this.pInternal.nvgRadialGradient(cx, cy, ir, or, icol, ocol);
182 	}
183 	public auto createImagePattern(float ox, float oy, float ex, float ey, float angle, Texture image, float alpha)
184 	in { assert(image !is null); }
185 	body {
186 		return this.pInternal.nvgImagePattern(ox, oy, ex, ey, angle, image.id, alpha);
187 	}
188 	
189 	// Scissoring //
190 	public @property scissor(Tuple!(float, float, float, float) sr) { this.pInternal.nvgScissor(sr.expand); }
191 	public @property intersectScissor(Tuple!(float, float, float, float) sr) { this.pInternal.nvgIntersectScissor(sr.expand); }
192 	public void resetScissor() { this.pInternal.nvgResetScissor(); }
193 	
194 	// PathMaking/Drawing //
195 	public void beginPath() { this.pInternal.nvgBeginPath(); }
196 	public void moveTo(float x, float y) { this.pInternal.nvgMoveTo(x, y); }
197 	public void lineTo(float x, float y) { this.pInternal.nvgLineTo(x, y); }
198 	public void bezierTo(float c1x, float c1y, float c2x, float c2y, float x, float y) { this.pInternal.nvgBezierTo(c1x, c1y, c2x, c2y, x, y); }
199 	public void quadTo(float cx, float cy, float x, float y) { this.pInternal.nvgQuadTo(cx, cy, x, y); }
200 	public void arcTo(float x1, float y1, float x2, float y2, float rad) { this.pInternal.nvgArcTo(x1, y1, x2, y2, rad); }
201 	public void closePath() { this.pInternal.nvgClosePath(); }
202 	public @property pathWinding(Winding d) { this.pInternal.nvgPathWinding(d); }
203 	public void arc(float cx, float cy, float r, float a0, float a1, Winding d) { this.pInternal.nvgArc(cx, cy, r, a0, a1, d); }
204 	public void rect(float x, float y, float w, float h) { this.pInternal.nvgRect(x, y, w, h); }
205 	public void roundedRect(float x, float y, float w, float h, float r) { this.pInternal.nvgRoundedRect(x, y, w, h, r); }
206 	public void ellipse(float cx, float cy, float rx, float ry) { this.pInternal.nvgEllipse(cx, cy, rx, ry); }
207 	public void circle(float cx, float cy, float r) { this.pInternal.nvgCircle(cx, cy, r); }
208 	public void fill() { this.pInternal.nvgFill(); }
209 	public void stroke() { this.pInternal.nvgStroke(); }
210 	
211 	// Font/TextPositioning //
212 	public Font createFont(string name, string fileName) { return this.pInternal.nvgCreateFont(name.toStringz, fileName.toStringz); }
213 	public Font createFontMem(string name, byte[] data, int freeData)
214 	{
215 		return this.pInternal.nvgCreateFontMem(name.toStringz, data.ptr, cast(int)data.length, freeData);
216 	}
217 	public Font findFont(string name) { return this.pInternal.nvgFindFont(name.toStringz); }
218 	public @property fontSize(float size) { this.pInternal.nvgFontSize(size); }
219 	public @property fontBlur(float blur) { this.pInternal.nvgFontBlur(blur); }
220 	public @property fontFace(Font f) { this.pInternal.nvgFontFaceId(f); }
221 	public @property fontFace(string name) { this.pInternal.nvgFontFace(name.toStringz); }
222 	public @property textLetterSpacing(float spacing) { this.pInternal.nvgTextLetterSpacing(spacing); }
223 	public @property textLineHeight(float lineHeight) { this.pInternal.nvgTextLineHeight(lineHeight); }
224 	public @property textAlign(TextAlign a) { this.pInternal.nvgTextAlign(a); }
225 	
226 	// TextDrawing //
227 	public auto text(float x, float y, string str, string end = null)
228 	{
229 		return this.pInternal.nvgText(x, y, str.toStringz, end is null ? null : end.toStringz);
230 	}
231 	public void textBox(float x, float y, float breakRowWidth, string str, string end = null)
232 	{
233 		this.pInternal.nvgTextBox(x, y, breakRowWidth, str.toStringz, end is null ? null : end.toStringz);
234 	}
235 	public auto textBounds(float x, float y, string str, string end, float[4] bounds)
236 	{
237 		return this.pInternal.nvgTextBounds(x, y, str.toStringz, end is null ? null : end.toStringz, bounds.ptr);
238 	}
239 	public void textBoxBounds(float x, float y, float breakRowWidth, string str, string end, float[4] bounds)
240 	{
241 		this.pInternal.nvgTextBoxBounds(x, y, breakRowWidth, str.toStringz, end is null ? null : end.toStringz, bounds.ptr);
242 	}
243 	public auto textGlyphPositions(float x, float y, string str, string end, GlyphPosition[] positions)
244 	{
245 		return this.pInternal.nvgTextGlyphPositions(x, y, str.toStringz, end is null ? null : end.toStringz, positions.ptr, cast(int)positions.length);
246 	}
247 	public void textMetrics(out float ascender, out float descender, out float lineheight)
248 	{
249 		this.pInternal.nvgTextMetrics(&ascender, &descender, &lineheight);
250 	}
251 	public auto textBreakLines(string str, string end, float breakRowWidth, TextRow[] rows)
252 	{
253 		return this.pInternal.nvgTextBreakLines(str.toStringz, end is null ? null : end.toStringz, breakRowWidth, rows.ptr, cast(int)rows.length);
254 	}
255 }
256 
257 version(UseGL3Renderer)
258 {
259 	import nanovg.gl3;
260 	alias ContextGL3 = Context!(nvgCreateGL3, nvgDeleteGL3);
261 }