egra: and even more faster text rendering
[iv.d.git] / nanovega_demo / goutline.d
blob04b23cebf58ac071ace92eed3fbf76bcb09b70d9
1 module nvg000;
3 import arsd.simpledisplay;
5 version(arsd) import arsd.nanovega;
6 else import iv.nanovega;
7 import iv.vfs.io;
10 //version = test_flatten;
11 //version = test_path_outline;
14 // ////////////////////////////////////////////////////////////////////////// //
15 version(arsd) public class NVGWindow : SimpleWindow {
16 public:
17 NVGContext nvg; // our NanoVega context
18 NVGContextFlag nvgInitFlags = NVGContextFlag.Default; // bitwise or
20 void delegate (NVGWindow self, NVGContext nvg) onInitOpenGL; // will be called after creating nvg
21 void delegate (NVGWindow self, NVGContext nvg) onDeinitOpenGL; // will be called before destroying nvg
22 void delegate (NVGWindow self, NVGContext nvg) onRedraw; // will be called in [redrawOpenGlScene]
24 protected:
25 void setupCallbacks () {
26 visibleForTheFirstTime = delegate () {
27 onBeforeInitNVG();
28 nvg = nvgCreateContext(cast(NVGContextFlag)nvgInitFlags);
29 if (nvg is null) assert(0, "cannot initialize NanoVega");
30 if (onInitOpenGL !is null) onInitOpenGL(this, nvg);
31 flushGui();
33 redrawOpenGlScene = delegate () {
34 if (width < 1 || height < 1 || closed) return;
35 if (onRedraw !is null && nvg !is null) {
36 setAsCurrentOpenGlContext();
37 scope(exit) releaseCurrentOpenGlContext();
38 glViewport(0, 0, width, height);
39 onRedraw(this, nvg);
44 void onBeforeInitNVG () {} // you can set [nvgInitFlags] here
46 public:
47 this (int width=800, int height=800, string title=null, Resizability resizable=Resizability.allowResizing, WindowTypes windowType=WindowTypes.normal, int customizationFlags=WindowFlags.normal, SimpleWindow parent=null) {
48 setupCallbacks();
49 super(width, height, title, OpenGlOptions.yes, resizable, windowType, customizationFlags, parent);
52 this (Size size, string title=null, Resizability resizable=Resizability.allowResizing) {
53 setupCallbacks();
54 super(size, title, OpenGlOptions.yes, resizable);
57 override void close () {
58 if (!closed && nvg !is null) {
59 setAsCurrentOpenGlContext();
60 scope(exit) { flushGui(); releaseCurrentOpenGlContext(); }
61 if (onDeinitOpenGL !is null) onDeinitOpenGL(this, nvg);
62 nvg.kill();
64 super.close();
67 final void forceRedraw () {
68 if (!closed && visible) redrawOpenGlSceneNow();
73 // ////////////////////////////////////////////////////////////////////////// //
74 void main () {
75 NVGContext nvg; // our NanoVega context
77 // we need at least OpenGL3 with GLSL to use NanoVega,
78 // so let's tell simpledisplay about that
79 setOpenGLContextVersion(3, 0);
81 // now create OpenGL window
82 sdpyWindowClass = "NVG_RASTER_TEST";
83 auto sdmain = new NVGWindow(800, 600, "NanoVega Simple Sample");
85 sdmain.onInitOpenGL = delegate (self, nvg) {
86 nvg.createFont("verdana", "verdana");
89 float dashStart = 0;
91 // this callback will be called when we will need to repaint our window
92 sdmain.onRedraw = delegate (self, nvg) {
93 glClearColor(0, 0, 0, 0);
94 glClear(glNVGClearFlags);
97 nvg.beginFrame(self.width, self.height);
98 scope(exit) nvg.endFrame();
100 float[4] bounds;
101 nvg.fontFace = "verdana";
102 nvg.fontSize = 24;
103 nvg.charPathBounds('A', bounds[]);
104 //writeln(bounds[]);
106 nvg.beginPath(); // start new path
107 nvg.scale(0.3, 0.3);
108 nvg.translate(100, bounds[3]-bounds[1]+100);
109 version(none) {
110 nvg.charToPath('Q');
111 } else {
112 version(test_path_outline) {
113 nvg.resetTransform();
114 nvg.beginPath();
115 nvg.moveTo(10, 80);
116 nvg.quadTo(30, 60, 50, 80);
117 nvg.lineTo(60, 120);
118 nvg.lineTo(0, 0);
119 auto ol = nvg.getCurrPathOutline();
120 nvg.beginPath();
121 //nvg.strokeWidth = 1;
122 } else {
123 auto ol = nvg.charOutline('Q');
125 if (!ol.empty) {
126 version(test_flatten) {
127 writeln("curved commands: ", ol.length);
128 ol = ol.flatten;
129 writeln("flattened commands: ", ol.length);
131 auto xol = ol;
132 foreach (const ref cmd; ol.commands) {
133 assert(cmd.valid);
134 final switch (cmd.code) {
135 case cmd.Kind.MoveTo:
136 version(test_path_outline) writeln("MoveTo(", cmd.args[0], ", ", cmd.args[1], ")");
137 nvg.moveTo(cmd.args[0], cmd.args[1]);
138 break;
139 case cmd.Kind.LineTo:
140 version(test_path_outline) writeln("LineTo(", cmd.args[0], ", ", cmd.args[1], ")");
141 nvg.lineTo(cmd.args[0], cmd.args[1]);
142 break;
143 case cmd.Kind.QuadTo:
144 version(test_path_outline) writeln("QuadTo(", cmd.args[0], ", ", cmd.args[1], ", ", cmd.args[2], ", ", cmd.args[3], ")");
145 version(test_flatten) {
146 assert(0, "wtf?!");
147 } else {
148 nvg.quadTo(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
150 break;
151 case cmd.Kind.BezierTo:
152 version(test_path_outline) writeln("BezierTo(", cmd.args[0], ", ", cmd.args[1], ", ", cmd.args[2], ", ", cmd.args[3], ", ", cmd.args[4], ", ", cmd.args[5], ")");
153 version(test_flatten) {
154 assert(0, "wtf?!");
155 } else {
156 nvg.bezierTo(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4], cmd.args[5]);
158 break;
159 case cmd.Kind.End: break; // the thing that should not be
162 //xol.clear();
165 nvg.fillColor = NVGColor.red;
166 nvg.strokeColor = NVGColor.red;
167 nvg.strokeWidth = 4;
168 nvg.lineDash = [8, 2, 4, 2];
169 nvg.lineDashStart = dashStart;
170 nvg.stroke();
174 sdmain.eventLoop(0, // no pulse timer required
175 delegate (KeyEvent event) {
176 if (event == "*-Q" || event == "Escape") { sdmain.close(); return; } // quit on Q, Ctrl+Q, and so on
177 if (event == "D-Space") { dashStart += 0.5; sdmain.forceRedraw(); }
181 flushGui(); // let OS do it's cleanup