Mercurial > hg > pub > prymula > com
comparison DPF-Prymula-audioplugins/dpf/dgl/src/NanoVG.cpp @ 3:84e66ea83026
DPF-Prymula-audioplugins-0.231015-2
author | prymula <prymula76@outlook.com> |
---|---|
date | Mon, 16 Oct 2023 21:53:34 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:cf2cb71d31dd | 3:84e66ea83026 |
---|---|
1 /* | |
2 * DISTRHO Plugin Framework (DPF) | |
3 * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> | |
4 * | |
5 * Permission to use, copy, modify, and/or distribute this software for any purpose with | |
6 * or without fee is hereby granted, provided that the above copyright notice and this | |
7 * permission notice appear in all copies. | |
8 * | |
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |
10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |
11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 */ | |
16 | |
17 #ifdef _MSC_VER | |
18 // instantiated template classes whose methods are defined elsewhere | |
19 # pragma warning(disable:4661) | |
20 #endif | |
21 | |
22 #include "../NanoVG.hpp" | |
23 #include "SubWidgetPrivateData.hpp" | |
24 | |
25 #ifndef DGL_NO_SHARED_RESOURCES | |
26 # include "Resources.hpp" | |
27 #endif | |
28 | |
29 // ----------------------------------------------------------------------- | |
30 | |
31 #if defined(DISTRHO_OS_WINDOWS) | |
32 # include <windows.h> | |
33 # define DGL_EXT(PROC, func) static PROC func; | |
34 DGL_EXT(PFNGLACTIVETEXTUREPROC, glActiveTexture) | |
35 DGL_EXT(PFNGLATTACHSHADERPROC, glAttachShader) | |
36 DGL_EXT(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation) | |
37 DGL_EXT(PFNGLBINDBUFFERPROC, glBindBuffer) | |
38 DGL_EXT(PFNGLBUFFERDATAPROC, glBufferData) | |
39 DGL_EXT(PFNGLCOMPILESHADERPROC, glCompileShader) | |
40 DGL_EXT(PFNGLCREATEPROGRAMPROC, glCreateProgram) | |
41 DGL_EXT(PFNGLCREATESHADERPROC, glCreateShader) | |
42 DGL_EXT(PFNGLDELETEBUFFERSPROC, glDeleteBuffers) | |
43 DGL_EXT(PFNGLDELETEPROGRAMPROC, glDeleteProgram) | |
44 DGL_EXT(PFNGLDELETESHADERPROC, glDeleteShader) | |
45 DGL_EXT(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray) | |
46 DGL_EXT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) | |
47 DGL_EXT(PFNGLGENBUFFERSPROC, glGenBuffers) | |
48 DGL_EXT(PFNGLGETPROGRAMIVPROC, glGetProgramiv) | |
49 DGL_EXT(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog) | |
50 DGL_EXT(PFNGLGETSHADERIVPROC, glGetShaderiv) | |
51 DGL_EXT(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog) | |
52 DGL_EXT(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation) | |
53 DGL_EXT(PFNGLLINKPROGRAMPROC, glLinkProgram) | |
54 DGL_EXT(PFNGLSHADERSOURCEPROC, glShaderSource) | |
55 DGL_EXT(PFNGLSTENCILOPSEPARATEPROC, glStencilOpSeparate) | |
56 DGL_EXT(PFNGLUNIFORM1IPROC, glUniform1i) | |
57 DGL_EXT(PFNGLUNIFORM2FVPROC, glUniform2fv) | |
58 DGL_EXT(PFNGLUNIFORM4FVPROC, glUniform4fv) | |
59 DGL_EXT(PFNGLUSEPROGRAMPROC, glUseProgram) | |
60 DGL_EXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) | |
61 DGL_EXT(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate) | |
62 # ifdef DGL_USE_NANOVG_FBO | |
63 DGL_EXT(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus) | |
64 DGL_EXT(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer) | |
65 DGL_EXT(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer) | |
66 DGL_EXT(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers) | |
67 DGL_EXT(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers) | |
68 DGL_EXT(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D) | |
69 DGL_EXT(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer) | |
70 DGL_EXT(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers) | |
71 DGL_EXT(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers) | |
72 DGL_EXT(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage) | |
73 # endif | |
74 # ifdef DGL_USE_OPENGL3 | |
75 DGL_EXT(PFNGLBINDBUFFERRANGEPROC, glBindBufferRange) | |
76 DGL_EXT(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray) | |
77 DGL_EXT(PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays) | |
78 DGL_EXT(PFNGLGENERATEMIPMAPPROC, glGenerateMipmap) | |
79 DGL_EXT(PFNGLGETUNIFORMBLOCKINDEXPROC, glGetUniformBlockIndex) | |
80 DGL_EXT(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays) | |
81 DGL_EXT(PFNGLUNIFORMBLOCKBINDINGPROC, glUniformBlockBinding) | |
82 # endif | |
83 # undef DGL_EXT | |
84 #endif | |
85 | |
86 // ----------------------------------------------------------------------- | |
87 // Include NanoVG OpenGL implementation | |
88 | |
89 //#define STB_IMAGE_STATIC | |
90 #if defined(DGL_USE_GLES2) | |
91 # define NANOVG_GLES2_IMPLEMENTATION | |
92 #elif defined(DGL_USE_OPENGL3) | |
93 # define NANOVG_GL3_IMPLEMENTATION | |
94 #else | |
95 # define NANOVG_GL2_IMPLEMENTATION | |
96 #endif | |
97 | |
98 #if defined(DISTRHO_OS_MAC) && defined(NANOVG_GL2_IMPLEMENTATION) | |
99 # define glBindVertexArray glBindVertexArrayAPPLE | |
100 # define glDeleteVertexArrays glDeleteVertexArraysAPPLE | |
101 # define glGenVertexArrays glGenVertexArraysAPPLE | |
102 #endif | |
103 | |
104 #include "nanovg/nanovg_gl.h" | |
105 | |
106 #ifdef DGL_USE_NANOVG_FBO | |
107 # define NANOVG_FBO_VALID 1 | |
108 # include "nanovg/nanovg_gl_utils.h" | |
109 #endif | |
110 | |
111 #if defined(NANOVG_GL2) | |
112 # define nvgCreateGLfn nvgCreateGL2 | |
113 # define nvgDeleteGL nvgDeleteGL2 | |
114 # define nvglCreateImageFromHandle nvglCreateImageFromHandleGL2 | |
115 # define nvglImageHandle nvglImageHandleGL2 | |
116 #elif defined(NANOVG_GL3) | |
117 # define nvgCreateGLfn nvgCreateGL3 | |
118 # define nvgDeleteGL nvgDeleteGL3 | |
119 # define nvglCreateImageFromHandle nvglCreateImageFromHandleGL3 | |
120 # define nvglImageHandle nvglImageHandleGL3 | |
121 #elif defined(NANOVG_GLES2) | |
122 # define nvgCreateGLfn nvgCreateGLES2 | |
123 # define nvgDeleteGL nvgDeleteGLES2 | |
124 # define nvglCreateImageFromHandle nvglCreateImageFromHandleGLES2 | |
125 # define nvglImageHandle nvglImageHandleGLES2 | |
126 #elif defined(NANOVG_GLES3) | |
127 # define nvgCreateGLfn nvgCreateGLES3 | |
128 # define nvgDeleteGL nvgDeleteGLES3 | |
129 # define nvglCreateImageFromHandle nvglCreateImageFromHandleGLES3 | |
130 # define nvglImageHandle nvglImageHandleGLES3 | |
131 #endif | |
132 | |
133 // ----------------------------------------------------------------------- | |
134 | |
135 START_NAMESPACE_DGL | |
136 | |
137 NVGcontext* nvgCreateGL(int flags) | |
138 { | |
139 #if defined(DISTRHO_OS_WINDOWS) | |
140 # if defined(__GNUC__) && (__GNUC__ >= 9) | |
141 # pragma GCC diagnostic push | |
142 # pragma GCC diagnostic ignored "-Wcast-function-type" | |
143 # endif | |
144 static bool needsInit = true; | |
145 # define DGL_EXT(PROC, func) \ | |
146 if (needsInit) func = (PROC) wglGetProcAddress ( #func ); \ | |
147 DISTRHO_SAFE_ASSERT_RETURN(func != nullptr, nullptr); | |
148 # define DGL_EXT2(PROC, func, fallback) \ | |
149 if (needsInit) { \ | |
150 func = (PROC) wglGetProcAddress ( #func ); \ | |
151 if (func == nullptr) func = (PROC) wglGetProcAddress ( #fallback ); \ | |
152 } DISTRHO_SAFE_ASSERT_RETURN(func != nullptr, nullptr); | |
153 DGL_EXT(PFNGLACTIVETEXTUREPROC, glActiveTexture) | |
154 DGL_EXT(PFNGLATTACHSHADERPROC, glAttachShader) | |
155 DGL_EXT(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation) | |
156 DGL_EXT(PFNGLBINDBUFFERPROC, glBindBuffer) | |
157 DGL_EXT(PFNGLBUFFERDATAPROC, glBufferData) | |
158 DGL_EXT(PFNGLCOMPILESHADERPROC, glCompileShader) | |
159 DGL_EXT(PFNGLCREATEPROGRAMPROC, glCreateProgram) | |
160 DGL_EXT(PFNGLCREATESHADERPROC, glCreateShader) | |
161 DGL_EXT(PFNGLDELETEBUFFERSPROC, glDeleteBuffers) | |
162 DGL_EXT(PFNGLDELETEPROGRAMPROC, glDeleteProgram) | |
163 DGL_EXT(PFNGLDELETESHADERPROC, glDeleteShader) | |
164 DGL_EXT(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray) | |
165 DGL_EXT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) | |
166 DGL_EXT(PFNGLGENBUFFERSPROC, glGenBuffers) | |
167 DGL_EXT(PFNGLGETPROGRAMIVPROC, glGetProgramiv) | |
168 DGL_EXT(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog) | |
169 DGL_EXT(PFNGLGETSHADERIVPROC, glGetShaderiv) | |
170 DGL_EXT(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog) | |
171 DGL_EXT(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation) | |
172 DGL_EXT(PFNGLLINKPROGRAMPROC, glLinkProgram) | |
173 DGL_EXT(PFNGLSHADERSOURCEPROC, glShaderSource) | |
174 DGL_EXT(PFNGLSTENCILOPSEPARATEPROC, glStencilOpSeparate) | |
175 DGL_EXT(PFNGLUNIFORM1IPROC, glUniform1i) | |
176 DGL_EXT(PFNGLUNIFORM2FVPROC, glUniform2fv) | |
177 DGL_EXT(PFNGLUNIFORM4FVPROC, glUniform4fv) | |
178 DGL_EXT(PFNGLUSEPROGRAMPROC, glUseProgram) | |
179 DGL_EXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) | |
180 DGL_EXT(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate) | |
181 # ifdef DGL_USE_NANOVG_FBO | |
182 DGL_EXT(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus) | |
183 DGL_EXT2(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer, glBindFramebufferEXT) | |
184 DGL_EXT2(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer, glBindRenderbufferEXT) | |
185 DGL_EXT2(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers, glDeleteFramebuffersEXT) | |
186 DGL_EXT2(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers, glDeleteRenderbuffersEXT) | |
187 DGL_EXT2(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D, glFramebufferTexture2DEXT) | |
188 DGL_EXT2(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer, glFramebufferRenderbufferEXT) | |
189 DGL_EXT2(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers, glGenFramebuffersEXT) | |
190 DGL_EXT2(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers, glGenRenderbuffersEXT) | |
191 DGL_EXT2(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage, glRenderbufferStorageEXT) | |
192 # endif | |
193 # ifdef DGL_USE_OPENGL3 | |
194 DGL_EXT(PFNGLBINDBUFFERRANGEPROC, glBindBufferRange) | |
195 DGL_EXT(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray) | |
196 DGL_EXT(PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays) | |
197 DGL_EXT(PFNGLGENERATEMIPMAPPROC, glGenerateMipmap) | |
198 DGL_EXT(PFNGLGETUNIFORMBLOCKINDEXPROC, glGetUniformBlockIndex) | |
199 DGL_EXT(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays) | |
200 DGL_EXT(PFNGLUNIFORMBLOCKBINDINGPROC, glUniformBlockBinding) | |
201 # endif | |
202 # undef DGL_EXT | |
203 # undef DGL_EXT2 | |
204 needsInit = false; | |
205 # if defined(__GNUC__) && (__GNUC__ >= 9) | |
206 # pragma GCC diagnostic pop | |
207 # endif | |
208 #endif | |
209 return nvgCreateGLfn(flags); | |
210 } | |
211 | |
212 // ----------------------------------------------------------------------- | |
213 // DGL Color class conversion | |
214 | |
215 Color::Color(const NVGcolor& c) noexcept | |
216 : red(c.r), green(c.g), blue(c.b), alpha(c.a) | |
217 { | |
218 fixBounds(); | |
219 } | |
220 | |
221 Color::operator NVGcolor() const noexcept | |
222 { | |
223 NVGcolor nc; | |
224 nc.r = red; | |
225 nc.g = green; | |
226 nc.b = blue; | |
227 nc.a = alpha; | |
228 return nc; | |
229 } | |
230 | |
231 // ----------------------------------------------------------------------- | |
232 // NanoImage | |
233 | |
234 NanoImage::NanoImage() | |
235 : fHandle(), | |
236 fSize() {} | |
237 | |
238 NanoImage::NanoImage(const Handle& handle) | |
239 : fHandle(handle), | |
240 fSize() | |
241 { | |
242 DISTRHO_SAFE_ASSERT_RETURN(fHandle.context != nullptr && fHandle.imageId != 0,); | |
243 | |
244 _updateSize(); | |
245 } | |
246 | |
247 NanoImage::~NanoImage() | |
248 { | |
249 if (fHandle.context != nullptr && fHandle.imageId != 0) | |
250 nvgDeleteImage(fHandle.context, fHandle.imageId); | |
251 } | |
252 | |
253 NanoImage& NanoImage::operator=(const Handle& handle) | |
254 { | |
255 if (fHandle.context != nullptr && fHandle.imageId != 0) | |
256 nvgDeleteImage(fHandle.context, fHandle.imageId); | |
257 | |
258 fHandle.context = handle.context; | |
259 fHandle.imageId = handle.imageId; | |
260 _updateSize(); | |
261 | |
262 return *this; | |
263 } | |
264 | |
265 bool NanoImage::isValid() const noexcept | |
266 { | |
267 return (fHandle.context != nullptr && fHandle.imageId != 0); | |
268 } | |
269 | |
270 Size<uint> NanoImage::getSize() const noexcept | |
271 { | |
272 return fSize; | |
273 } | |
274 | |
275 GLuint NanoImage::getTextureHandle() const | |
276 { | |
277 DISTRHO_SAFE_ASSERT_RETURN(fHandle.context != nullptr && fHandle.imageId != 0, 0); | |
278 | |
279 return nvglImageHandle(fHandle.context, fHandle.imageId); | |
280 } | |
281 | |
282 void NanoImage::_updateSize() | |
283 { | |
284 int w=0, h=0; | |
285 | |
286 nvgImageSize(fHandle.context, fHandle.imageId, &w, &h); | |
287 | |
288 if (w < 0) w = 0; | |
289 if (h < 0) h = 0; | |
290 | |
291 fSize.setSize(static_cast<uint>(w), static_cast<uint>(h)); | |
292 } | |
293 | |
294 // ----------------------------------------------------------------------- | |
295 // Paint | |
296 | |
297 NanoVG::Paint::Paint() noexcept | |
298 : radius(0.0f), feather(0.0f), innerColor(), outerColor(), imageId(0) | |
299 { | |
300 std::memset(xform, 0, sizeof(float)*6); | |
301 std::memset(extent, 0, sizeof(float)*2); | |
302 } | |
303 | |
304 NanoVG::Paint::Paint(const NVGpaint& p) noexcept | |
305 : radius(p.radius), feather(p.feather), innerColor(p.innerColor), outerColor(p.outerColor), imageId(p.image) | |
306 { | |
307 std::memcpy(xform, p.xform, sizeof(float)*6); | |
308 std::memcpy(extent, p.extent, sizeof(float)*2); | |
309 } | |
310 | |
311 NanoVG::Paint::operator NVGpaint() const noexcept | |
312 { | |
313 NVGpaint p; | |
314 p.radius = radius; | |
315 p.feather = feather; | |
316 p.innerColor = innerColor; | |
317 p.outerColor = outerColor; | |
318 p.image = imageId; | |
319 std::memcpy(p.xform, xform, sizeof(float)*6); | |
320 std::memcpy(p.extent, extent, sizeof(float)*2); | |
321 return p; | |
322 } | |
323 | |
324 // ----------------------------------------------------------------------- | |
325 // NanoVG | |
326 | |
327 NanoVG::NanoVG(int flags) | |
328 : fContext(nvgCreateGL(flags)), | |
329 fInFrame(false), | |
330 fIsSubWidget(false) | |
331 { | |
332 DISTRHO_CUSTOM_SAFE_ASSERT("Failed to create NanoVG context, expect a black screen", fContext != nullptr); | |
333 } | |
334 | |
335 NanoVG::NanoVG(NVGcontext* const context) | |
336 : fContext(context), | |
337 fInFrame(false), | |
338 fIsSubWidget(true) | |
339 { | |
340 DISTRHO_CUSTOM_SAFE_ASSERT("Failed to create NanoVG context, expect a black screen", fContext != nullptr); | |
341 } | |
342 | |
343 NanoVG::~NanoVG() | |
344 { | |
345 DISTRHO_CUSTOM_SAFE_ASSERT("Destroying NanoVG context with still active frame", ! fInFrame); | |
346 | |
347 if (fContext != nullptr && ! fIsSubWidget) | |
348 nvgDeleteGL(fContext); | |
349 } | |
350 | |
351 // ----------------------------------------------------------------------- | |
352 | |
353 void NanoVG::beginFrame(const uint width, const uint height, const float scaleFactor) | |
354 { | |
355 DISTRHO_SAFE_ASSERT_RETURN(scaleFactor > 0.0f,); | |
356 DISTRHO_SAFE_ASSERT_RETURN(! fInFrame,); | |
357 fInFrame = true; | |
358 | |
359 if (fContext != nullptr) | |
360 nvgBeginFrame(fContext, static_cast<int>(width), static_cast<int>(height), scaleFactor); | |
361 } | |
362 | |
363 void NanoVG::beginFrame(Widget* const widget) | |
364 { | |
365 DISTRHO_SAFE_ASSERT_RETURN(widget != nullptr,); | |
366 DISTRHO_SAFE_ASSERT_RETURN(! fInFrame,); | |
367 fInFrame = true; | |
368 | |
369 if (fContext == nullptr) | |
370 return; | |
371 | |
372 if (TopLevelWidget* const tlw = widget->getTopLevelWidget()) | |
373 nvgBeginFrame(fContext, | |
374 static_cast<int>(tlw->getWidth()), | |
375 static_cast<int>(tlw->getHeight()), | |
376 tlw->getScaleFactor()); | |
377 } | |
378 | |
379 void NanoVG::cancelFrame() | |
380 { | |
381 DISTRHO_SAFE_ASSERT_RETURN(fInFrame,); | |
382 | |
383 if (fContext != nullptr) | |
384 nvgCancelFrame(fContext); | |
385 | |
386 fInFrame = false; | |
387 } | |
388 | |
389 void NanoVG::endFrame() | |
390 { | |
391 DISTRHO_SAFE_ASSERT_RETURN(fInFrame,); | |
392 | |
393 // Save current blend state | |
394 GLboolean blendEnabled; | |
395 GLint blendSrc, blendDst; | |
396 glGetBooleanv(GL_BLEND, &blendEnabled); | |
397 glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrc); | |
398 glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDst); | |
399 | |
400 if (fContext != nullptr) | |
401 nvgEndFrame(fContext); | |
402 | |
403 // Restore blend state | |
404 if (blendEnabled) | |
405 glEnable(GL_BLEND); | |
406 else | |
407 glDisable(GL_BLEND); | |
408 | |
409 glBlendFunc(blendSrc, blendDst); | |
410 | |
411 fInFrame = false; | |
412 } | |
413 | |
414 // ----------------------------------------------------------------------- | |
415 // State Handling | |
416 | |
417 void NanoVG::save() | |
418 { | |
419 if (fContext != nullptr) | |
420 nvgSave(fContext); | |
421 } | |
422 | |
423 void NanoVG::restore() | |
424 { | |
425 if (fContext != nullptr) | |
426 nvgRestore(fContext); | |
427 } | |
428 | |
429 void NanoVG::reset() | |
430 { | |
431 if (fContext != nullptr) | |
432 nvgReset(fContext); | |
433 } | |
434 | |
435 // ----------------------------------------------------------------------- | |
436 // Render styles | |
437 | |
438 void NanoVG::strokeColor(const Color& color) | |
439 { | |
440 if (fContext != nullptr) | |
441 nvgStrokeColor(fContext, color); | |
442 } | |
443 | |
444 void NanoVG::strokeColor(const int red, const int green, const int blue, const int alpha) | |
445 { | |
446 if (fContext != nullptr) | |
447 { | |
448 DISTRHO_SAFE_ASSERT_RETURN(red >= 0 && red <= 255,); | |
449 DISTRHO_SAFE_ASSERT_RETURN(green >= 0 && green <= 255,); | |
450 DISTRHO_SAFE_ASSERT_RETURN(blue >= 0 && blue <= 255,); | |
451 DISTRHO_SAFE_ASSERT_RETURN(alpha >= 0 && alpha <= 255,); | |
452 | |
453 nvgStrokeColor(fContext, nvgRGBA(static_cast<uchar>(red), | |
454 static_cast<uchar>(green), | |
455 static_cast<uchar>(blue), | |
456 static_cast<uchar>(alpha))); | |
457 } | |
458 } | |
459 | |
460 void NanoVG::strokeColor(const float red, const float green, const float blue, const float alpha) | |
461 { | |
462 if (fContext != nullptr) | |
463 nvgStrokeColor(fContext, nvgRGBAf(red, green, blue, alpha)); | |
464 } | |
465 | |
466 void NanoVG::strokePaint(const Paint& paint) | |
467 { | |
468 if (fContext != nullptr) | |
469 nvgStrokePaint(fContext, paint); | |
470 } | |
471 | |
472 void NanoVG::fillColor(const Color& color) | |
473 { | |
474 if (fContext != nullptr) | |
475 nvgFillColor(fContext, color); | |
476 } | |
477 | |
478 void NanoVG::fillColor(const int red, const int green, const int blue, const int alpha) | |
479 { | |
480 if (fContext != nullptr) | |
481 { | |
482 DISTRHO_SAFE_ASSERT_RETURN(red >= 0 && red <= 255,); | |
483 DISTRHO_SAFE_ASSERT_RETURN(green >= 0 && green <= 255,); | |
484 DISTRHO_SAFE_ASSERT_RETURN(blue >= 0 && blue <= 255,); | |
485 DISTRHO_SAFE_ASSERT_RETURN(alpha >= 0 && alpha <= 255,); | |
486 | |
487 nvgFillColor(fContext, nvgRGBA(static_cast<uchar>(red), | |
488 static_cast<uchar>(green), | |
489 static_cast<uchar>(blue), | |
490 static_cast<uchar>(alpha))); | |
491 } | |
492 } | |
493 | |
494 void NanoVG::fillColor(const float red, const float green, const float blue, const float alpha) | |
495 { | |
496 if (fContext != nullptr) | |
497 nvgFillColor(fContext, nvgRGBAf(red, green, blue, alpha)); | |
498 } | |
499 | |
500 void NanoVG::fillPaint(const Paint& paint) | |
501 { | |
502 if (fContext != nullptr) | |
503 nvgFillPaint(fContext, paint); | |
504 } | |
505 | |
506 void NanoVG::miterLimit(float limit) | |
507 { | |
508 if (fContext == nullptr) return; | |
509 DISTRHO_SAFE_ASSERT_RETURN(limit > 0.0f,); | |
510 | |
511 nvgMiterLimit(fContext, limit); | |
512 } | |
513 | |
514 void NanoVG::strokeWidth(float size) | |
515 { | |
516 if (fContext == nullptr) return; | |
517 DISTRHO_SAFE_ASSERT_RETURN(size > 0.0f,); | |
518 | |
519 nvgStrokeWidth(fContext, size); | |
520 } | |
521 | |
522 void NanoVG::lineCap(NanoVG::LineCap cap) | |
523 { | |
524 if (fContext != nullptr) | |
525 nvgLineCap(fContext, cap); | |
526 } | |
527 | |
528 void NanoVG::lineJoin(NanoVG::LineCap join) | |
529 { | |
530 if (fContext != nullptr) | |
531 nvgLineJoin(fContext, join); | |
532 } | |
533 | |
534 void NanoVG::globalAlpha(float alpha) | |
535 { | |
536 if (fContext != nullptr) | |
537 nvgGlobalAlpha(fContext, alpha); | |
538 } | |
539 | |
540 void NanoVG::globalTint(Color tint) | |
541 { | |
542 if (fContext != nullptr) | |
543 nvgGlobalTint(fContext, tint); | |
544 } | |
545 | |
546 // ----------------------------------------------------------------------- | |
547 // Transforms | |
548 | |
549 void NanoVG::resetTransform() | |
550 { | |
551 if (fContext != nullptr) | |
552 nvgResetTransform(fContext); | |
553 } | |
554 | |
555 void NanoVG::transform(float a, float b, float c, float d, float e, float f) | |
556 { | |
557 if (fContext != nullptr) | |
558 nvgTransform(fContext, a, b, c, d, e, f); | |
559 } | |
560 | |
561 void NanoVG::translate(float x, float y) | |
562 { | |
563 if (fContext != nullptr) | |
564 nvgTranslate(fContext, x, y); | |
565 } | |
566 | |
567 void NanoVG::rotate(float angle) | |
568 { | |
569 if (fContext != nullptr) | |
570 nvgRotate(fContext, angle); | |
571 } | |
572 | |
573 void NanoVG::skewX(float angle) | |
574 { | |
575 if (fContext == nullptr) return; | |
576 DISTRHO_SAFE_ASSERT_RETURN(angle > 0.0f,); | |
577 | |
578 nvgSkewX(fContext, angle); | |
579 } | |
580 | |
581 void NanoVG::skewY(float angle) | |
582 { | |
583 if (fContext == nullptr) return; | |
584 DISTRHO_SAFE_ASSERT_RETURN(angle > 0.0f,); | |
585 | |
586 nvgSkewY(fContext, angle); | |
587 } | |
588 | |
589 void NanoVG::scale(float x, float y) | |
590 { | |
591 if (fContext == nullptr) return; | |
592 DISTRHO_SAFE_ASSERT_RETURN(d_isNotZero(x),); | |
593 DISTRHO_SAFE_ASSERT_RETURN(d_isNotZero(y),); | |
594 | |
595 nvgScale(fContext, x, y); | |
596 } | |
597 | |
598 void NanoVG::currentTransform(float xform[6]) | |
599 { | |
600 if (fContext != nullptr) | |
601 nvgCurrentTransform(fContext, xform); | |
602 } | |
603 | |
604 void NanoVG::transformIdentity(float dst[6]) | |
605 { | |
606 nvgTransformIdentity(dst); | |
607 } | |
608 | |
609 void NanoVG::transformTranslate(float dst[6], float tx, float ty) | |
610 { | |
611 nvgTransformTranslate(dst, tx, ty); | |
612 } | |
613 | |
614 void NanoVG::transformScale(float dst[6], float sx, float sy) | |
615 { | |
616 nvgTransformScale(dst, sx, sy); | |
617 } | |
618 | |
619 void NanoVG::transformRotate(float dst[6], float a) | |
620 { | |
621 nvgTransformRotate(dst, a); | |
622 } | |
623 | |
624 void NanoVG::transformSkewX(float dst[6], float a) | |
625 { | |
626 nvgTransformSkewX(dst, a); | |
627 } | |
628 | |
629 void NanoVG::transformSkewY(float dst[6], float a) | |
630 { | |
631 nvgTransformSkewY(dst, a); | |
632 } | |
633 | |
634 void NanoVG::transformMultiply(float dst[6], const float src[6]) | |
635 { | |
636 nvgTransformMultiply(dst, src); | |
637 } | |
638 | |
639 void NanoVG::transformPremultiply(float dst[6], const float src[6]) | |
640 { | |
641 nvgTransformPremultiply(dst, src); | |
642 } | |
643 | |
644 int NanoVG::transformInverse(float dst[6], const float src[6]) | |
645 { | |
646 return nvgTransformInverse(dst, src); | |
647 } | |
648 | |
649 void NanoVG::transformPoint(float& dstx, float& dsty, const float xform[6], float srcx, float srcy) | |
650 { | |
651 nvgTransformPoint(&dstx, &dsty, xform, srcx, srcy); | |
652 } | |
653 | |
654 float NanoVG::degToRad(float deg) | |
655 { | |
656 return nvgDegToRad(deg); | |
657 } | |
658 | |
659 float NanoVG::radToDeg(float rad) | |
660 { | |
661 return nvgRadToDeg(rad); | |
662 } | |
663 | |
664 // ----------------------------------------------------------------------- | |
665 // Images | |
666 | |
667 NanoImage::Handle NanoVG::createImageFromFile(const char* filename, ImageFlags imageFlags) | |
668 { | |
669 return createImageFromFile(filename, static_cast<int>(imageFlags)); | |
670 } | |
671 | |
672 NanoImage::Handle NanoVG::createImageFromFile(const char* filename, int imageFlags) | |
673 { | |
674 if (fContext == nullptr) return NanoImage::Handle(); | |
675 DISTRHO_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', NanoImage::Handle()); | |
676 | |
677 return NanoImage::Handle(fContext, nvgCreateImage(fContext, filename, imageFlags)); | |
678 } | |
679 | |
680 NanoImage::Handle NanoVG::createImageFromMemory(const uchar* data, uint dataSize, ImageFlags imageFlags) | |
681 { | |
682 return createImageFromMemory(data, dataSize, static_cast<int>(imageFlags)); | |
683 } | |
684 | |
685 NanoImage::Handle NanoVG::createImageFromMemory(const uchar* data, uint dataSize, int imageFlags) | |
686 { | |
687 if (fContext == nullptr) return NanoImage::Handle(); | |
688 DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, NanoImage::Handle()); | |
689 DISTRHO_SAFE_ASSERT_RETURN(dataSize > 0, NanoImage::Handle()); | |
690 | |
691 return NanoImage::Handle(fContext, nvgCreateImageMem(fContext, imageFlags, data, static_cast<int>(dataSize))); | |
692 } | |
693 | |
694 NanoImage::Handle NanoVG::createImageFromRawMemory(uint w, uint h, const uchar* data, | |
695 ImageFlags imageFlags, ImageFormat format) | |
696 { | |
697 return createImageFromRawMemory(w, h, data, static_cast<int>(imageFlags), format); | |
698 } | |
699 | |
700 NanoImage::Handle NanoVG::createImageFromRawMemory(uint w, uint h, const uchar* data, | |
701 int imageFlags, ImageFormat format) | |
702 { | |
703 if (fContext == nullptr) return NanoImage::Handle(); | |
704 DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, NanoImage::Handle()); | |
705 | |
706 NVGtexture nvgformat; | |
707 switch (format) | |
708 { | |
709 case kImageFormatGrayscale: | |
710 nvgformat = NVG_TEXTURE_ALPHA; | |
711 break; | |
712 case kImageFormatBGR: | |
713 nvgformat = NVG_TEXTURE_BGR; | |
714 break; | |
715 case kImageFormatBGRA: | |
716 nvgformat = NVG_TEXTURE_BGRA; | |
717 break; | |
718 case kImageFormatRGB: | |
719 nvgformat = NVG_TEXTURE_RGB; | |
720 break; | |
721 case kImageFormatRGBA: | |
722 nvgformat = NVG_TEXTURE_RGBA; | |
723 break; | |
724 default: | |
725 return NanoImage::Handle(); | |
726 } | |
727 | |
728 return NanoImage::Handle(fContext, nvgCreateImageRaw(fContext, | |
729 static_cast<int>(w), | |
730 static_cast<int>(h), imageFlags, nvgformat, data)); | |
731 } | |
732 | |
733 NanoImage::Handle NanoVG::createImageFromRGBA(uint w, uint h, const uchar* data, ImageFlags imageFlags) | |
734 { | |
735 return createImageFromRGBA(w, h, data, static_cast<int>(imageFlags)); | |
736 } | |
737 | |
738 NanoImage::Handle NanoVG::createImageFromRGBA(uint w, uint h, const uchar* data, int imageFlags) | |
739 { | |
740 if (fContext == nullptr) return NanoImage::Handle(); | |
741 DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, NanoImage::Handle()); | |
742 | |
743 return NanoImage::Handle(fContext, nvgCreateImageRGBA(fContext, | |
744 static_cast<int>(w), | |
745 static_cast<int>(h), imageFlags, data)); | |
746 } | |
747 | |
748 NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, | |
749 ImageFlags imageFlags, bool deleteTexture) | |
750 { | |
751 return createImageFromTextureHandle(textureId, w, h, static_cast<int>(imageFlags), deleteTexture); | |
752 } | |
753 | |
754 NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, | |
755 int imageFlags, bool deleteTexture) | |
756 { | |
757 if (fContext == nullptr) return NanoImage::Handle(); | |
758 DISTRHO_SAFE_ASSERT_RETURN(textureId != 0, NanoImage::Handle()); | |
759 | |
760 if (! deleteTexture) | |
761 imageFlags |= NVG_IMAGE_NODELETE; | |
762 | |
763 return NanoImage::Handle(fContext, nvglCreateImageFromHandle(fContext, | |
764 textureId, | |
765 static_cast<int>(w), | |
766 static_cast<int>(h), imageFlags)); | |
767 } | |
768 | |
769 // ----------------------------------------------------------------------- | |
770 // Paints | |
771 | |
772 NanoVG::Paint NanoVG::linearGradient(float sx, float sy, float ex, float ey, const Color& icol, const Color& ocol) | |
773 { | |
774 if (fContext == nullptr) return Paint(); | |
775 return nvgLinearGradient(fContext, sx, sy, ex, ey, icol, ocol); | |
776 } | |
777 | |
778 NanoVG::Paint NanoVG::boxGradient(float x, float y, float w, float h, float r, float f, const Color& icol, const Color& ocol) | |
779 { | |
780 if (fContext == nullptr) return Paint(); | |
781 return nvgBoxGradient(fContext, x, y, w, h, r, f, icol, ocol); | |
782 } | |
783 | |
784 NanoVG::Paint NanoVG::radialGradient(float cx, float cy, float inr, float outr, const Color& icol, const Color& ocol) | |
785 { | |
786 if (fContext == nullptr) return Paint(); | |
787 return nvgRadialGradient(fContext, cx, cy, inr, outr, icol, ocol); | |
788 } | |
789 | |
790 NanoVG::Paint NanoVG::imagePattern(float ox, float oy, float ex, float ey, float angle, const NanoImage& image, float alpha) | |
791 { | |
792 if (fContext == nullptr) return Paint(); | |
793 | |
794 const int imageId(image.fHandle.imageId); | |
795 DISTRHO_SAFE_ASSERT_RETURN(imageId != 0, Paint()); | |
796 | |
797 return nvgImagePattern(fContext, ox, oy, ex, ey, angle, imageId, alpha); | |
798 } | |
799 | |
800 // ----------------------------------------------------------------------- | |
801 // Scissoring | |
802 | |
803 void NanoVG::scissor(float x, float y, float w, float h) | |
804 { | |
805 if (fContext != nullptr) | |
806 nvgScissor(fContext, x, y, w, h); | |
807 } | |
808 | |
809 void NanoVG::intersectScissor(float x, float y, float w, float h) | |
810 { | |
811 if (fContext != nullptr) | |
812 nvgIntersectScissor(fContext, x, y, w, h); | |
813 } | |
814 | |
815 void NanoVG::resetScissor() | |
816 { | |
817 if (fContext != nullptr) | |
818 nvgResetScissor(fContext); | |
819 } | |
820 | |
821 // ----------------------------------------------------------------------- | |
822 // Paths | |
823 | |
824 void NanoVG::beginPath() | |
825 { | |
826 if (fContext != nullptr) | |
827 nvgBeginPath(fContext); | |
828 } | |
829 | |
830 void NanoVG::moveTo(float x, float y) | |
831 { | |
832 if (fContext != nullptr) | |
833 nvgMoveTo(fContext, x, y); | |
834 } | |
835 | |
836 void NanoVG::lineTo(float x, float y) | |
837 { | |
838 if (fContext != nullptr) | |
839 nvgLineTo(fContext, x, y); | |
840 } | |
841 | |
842 void NanoVG::bezierTo(float c1x, float c1y, float c2x, float c2y, float x, float y) | |
843 { | |
844 if (fContext != nullptr) | |
845 nvgBezierTo(fContext, c1x, c1y, c2x, c2y, x, y); | |
846 } | |
847 | |
848 void NanoVG::quadTo(float cx, float cy, float x, float y) | |
849 { | |
850 if (fContext != nullptr) | |
851 nvgQuadTo(fContext, cx, cy, x, y); | |
852 } | |
853 | |
854 void NanoVG::arcTo(float x1, float y1, float x2, float y2, float radius) | |
855 { | |
856 if (fContext != nullptr) | |
857 nvgArcTo(fContext, x1, y1, x2, y2, radius); | |
858 } | |
859 | |
860 void NanoVG::closePath() | |
861 { | |
862 if (fContext != nullptr) | |
863 nvgClosePath(fContext); | |
864 } | |
865 | |
866 void NanoVG::pathWinding(NanoVG::Winding dir) | |
867 { | |
868 if (fContext != nullptr) | |
869 nvgPathWinding(fContext, dir); | |
870 } | |
871 | |
872 void NanoVG::arc(float cx, float cy, float r, float a0, float a1, NanoVG::Winding dir) | |
873 { | |
874 if (fContext != nullptr) | |
875 nvgArc(fContext, cx, cy, r, a0, a1, dir); | |
876 } | |
877 | |
878 void NanoVG::rect(float x, float y, float w, float h) | |
879 { | |
880 if (fContext != nullptr) | |
881 nvgRect(fContext, x, y, w, h); | |
882 } | |
883 | |
884 void NanoVG::roundedRect(float x, float y, float w, float h, float r) | |
885 { | |
886 if (fContext != nullptr) | |
887 nvgRoundedRect(fContext, x, y, w, h, r); | |
888 } | |
889 | |
890 void NanoVG::ellipse(float cx, float cy, float rx, float ry) | |
891 { | |
892 if (fContext != nullptr) | |
893 nvgEllipse(fContext, cx, cy, rx, ry); | |
894 } | |
895 | |
896 void NanoVG::circle(float cx, float cy, float r) | |
897 { | |
898 if (fContext != nullptr) | |
899 nvgCircle(fContext, cx, cy, r); | |
900 } | |
901 | |
902 void NanoVG::fill() | |
903 { | |
904 if (fContext != nullptr) | |
905 nvgFill(fContext); | |
906 } | |
907 | |
908 void NanoVG::stroke() | |
909 { | |
910 if (fContext != nullptr) | |
911 nvgStroke(fContext); | |
912 } | |
913 | |
914 // ----------------------------------------------------------------------- | |
915 // Text | |
916 | |
917 NanoVG::FontId NanoVG::createFontFromFile(const char* name, const char* filename) | |
918 { | |
919 DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1); | |
920 DISTRHO_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', -1); | |
921 DISTRHO_SAFE_ASSERT_RETURN(fContext != nullptr, -1); | |
922 | |
923 return nvgCreateFont(fContext, name, filename); | |
924 } | |
925 | |
926 NanoVG::FontId NanoVG::createFontFromMemory(const char* name, const uchar* data, uint dataSize, bool freeData) | |
927 { | |
928 DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1); | |
929 DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, -1); | |
930 DISTRHO_SAFE_ASSERT_RETURN(fContext != nullptr, -1); | |
931 | |
932 return nvgCreateFontMem(fContext, name, const_cast<uchar*>(data), static_cast<int>(dataSize), freeData); | |
933 } | |
934 | |
935 NanoVG::FontId NanoVG::findFont(const char* name) | |
936 { | |
937 DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1); | |
938 DISTRHO_SAFE_ASSERT_RETURN(fContext != nullptr, -1); | |
939 | |
940 return nvgFindFont(fContext, name); | |
941 } | |
942 | |
943 void NanoVG::fontSize(float size) | |
944 { | |
945 if (fContext == nullptr) return; | |
946 DISTRHO_SAFE_ASSERT_RETURN(size > 0.0f,); | |
947 | |
948 nvgFontSize(fContext, size); | |
949 } | |
950 | |
951 void NanoVG::fontBlur(float blur) | |
952 { | |
953 if (fContext == nullptr) return; | |
954 DISTRHO_SAFE_ASSERT_RETURN(blur >= 0.0f,); | |
955 | |
956 nvgFontBlur(fContext, blur); | |
957 } | |
958 | |
959 void NanoVG::textLetterSpacing(float spacing) | |
960 { | |
961 if (fContext == nullptr) return; | |
962 DISTRHO_SAFE_ASSERT_RETURN(spacing >= 0.0f,); | |
963 | |
964 nvgTextLetterSpacing(fContext, spacing); | |
965 } | |
966 | |
967 void NanoVG::textLineHeight(float lineHeight) | |
968 { | |
969 if (fContext == nullptr) return; | |
970 DISTRHO_SAFE_ASSERT_RETURN(lineHeight > 0.0f,); | |
971 | |
972 nvgTextLineHeight(fContext, lineHeight); | |
973 } | |
974 | |
975 void NanoVG::textAlign(NanoVG::Align align) | |
976 { | |
977 if (fContext != nullptr) | |
978 nvgTextAlign(fContext, align); | |
979 } | |
980 | |
981 void NanoVG::textAlign(int align) | |
982 { | |
983 if (fContext != nullptr) | |
984 nvgTextAlign(fContext, align); | |
985 } | |
986 | |
987 void NanoVG::fontFaceId(FontId font) | |
988 { | |
989 if (fContext == nullptr) return; | |
990 DISTRHO_SAFE_ASSERT_RETURN(font >= 0,); | |
991 | |
992 nvgFontFaceId(fContext, font); | |
993 } | |
994 | |
995 void NanoVG::fontFace(const char* font) | |
996 { | |
997 if (fContext == nullptr) return; | |
998 DISTRHO_SAFE_ASSERT_RETURN(font != nullptr && font[0] != '\0',); | |
999 | |
1000 nvgFontFace(fContext, font); | |
1001 } | |
1002 | |
1003 float NanoVG::text(float x, float y, const char* string, const char* end) | |
1004 { | |
1005 if (fContext == nullptr) return 0.0f; | |
1006 DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0', 0.0f); | |
1007 | |
1008 return nvgText(fContext, x, y, string, end); | |
1009 } | |
1010 | |
1011 void NanoVG::textBox(float x, float y, float breakRowWidth, const char* string, const char* end) | |
1012 { | |
1013 if (fContext == nullptr) return; | |
1014 DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0',); | |
1015 | |
1016 nvgTextBox(fContext, x, y, breakRowWidth, string, end); | |
1017 } | |
1018 | |
1019 float NanoVG::textBounds(float x, float y, const char* string, const char* end, Rectangle<float>& bounds) | |
1020 { | |
1021 if (fContext == nullptr) return 0.0f; | |
1022 DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0', 0.0f); | |
1023 | |
1024 float b[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; | |
1025 const float ret = nvgTextBounds(fContext, x, y, string, end, b); | |
1026 bounds = Rectangle<float>(b[0], b[1], b[2] - b[0], b[3] - b[1]); | |
1027 return ret; | |
1028 } | |
1029 | |
1030 void NanoVG::textBoxBounds(float x, float y, float breakRowWidth, const char* string, const char* end, float bounds[4]) | |
1031 { | |
1032 if (fContext == nullptr) return; | |
1033 DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0',); | |
1034 | |
1035 nvgTextBoxBounds(fContext, x, y, breakRowWidth, string, end, bounds); | |
1036 } | |
1037 | |
1038 int NanoVG::textGlyphPositions(float x, float y, const char* string, const char* end, NanoVG::GlyphPosition& positions, int maxPositions) | |
1039 { | |
1040 if (fContext == nullptr) return 0; | |
1041 DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0', 0); | |
1042 | |
1043 return nvgTextGlyphPositions(fContext, x, y, string, end, (NVGglyphPosition*)&positions, maxPositions); | |
1044 } | |
1045 | |
1046 void NanoVG::textMetrics(float* ascender, float* descender, float* lineh) | |
1047 { | |
1048 if (fContext != nullptr) | |
1049 nvgTextMetrics(fContext, ascender, descender, lineh); | |
1050 } | |
1051 | |
1052 int NanoVG::textBreakLines(const char* string, const char* end, float breakRowWidth, NanoVG::TextRow& rows, int maxRows) | |
1053 { | |
1054 if (fContext != nullptr) | |
1055 return nvgTextBreakLines(fContext, string, end, breakRowWidth, (NVGtextRow*)&rows, maxRows); | |
1056 return 0; | |
1057 } | |
1058 | |
1059 #ifndef DGL_NO_SHARED_RESOURCES | |
1060 bool NanoVG::loadSharedResources() | |
1061 { | |
1062 if (fContext == nullptr) return false; | |
1063 | |
1064 if (nvgFindFont(fContext, NANOVG_DEJAVU_SANS_TTF) >= 0) | |
1065 return true; | |
1066 | |
1067 using namespace dpf_resources; | |
1068 | |
1069 return nvgCreateFontMem(fContext, NANOVG_DEJAVU_SANS_TTF, (uchar*)dejavusans_ttf, dejavusans_ttf_size, 0) >= 0; | |
1070 } | |
1071 #endif | |
1072 | |
1073 // ----------------------------------------------------------------------- | |
1074 | |
1075 template <class BaseWidget> | |
1076 void NanoBaseWidget<BaseWidget>::displayChildren() | |
1077 { | |
1078 std::list<SubWidget*> children(BaseWidget::getChildren()); | |
1079 | |
1080 for (std::list<SubWidget*>::iterator it = children.begin(); it != children.end(); ++it) | |
1081 { | |
1082 if (NanoSubWidget* const subwidget = dynamic_cast<NanoSubWidget*>(*it)) | |
1083 { | |
1084 if (subwidget->fUsingParentContext && subwidget->isVisible()) | |
1085 subwidget->onDisplay(); | |
1086 } | |
1087 } | |
1088 } | |
1089 | |
1090 // ----------------------------------------------------------------------- | |
1091 // NanoSubWidget | |
1092 | |
1093 template <> | |
1094 NanoBaseWidget<SubWidget>::NanoBaseWidget(Widget* const parentWidget, int flags) | |
1095 : SubWidget(parentWidget), | |
1096 NanoVG(flags), | |
1097 fUsingParentContext(false) | |
1098 { | |
1099 setNeedsViewportScaling(); | |
1100 } | |
1101 | |
1102 template <> | |
1103 NanoBaseWidget<SubWidget>::NanoBaseWidget(NanoSubWidget* const parentWidget) | |
1104 : SubWidget(parentWidget), | |
1105 NanoVG(parentWidget->getContext()), | |
1106 fUsingParentContext(true) | |
1107 { | |
1108 setSkipDrawing(); | |
1109 } | |
1110 | |
1111 template <> | |
1112 NanoBaseWidget<SubWidget>::NanoBaseWidget(NanoTopLevelWidget* const parentWidget) | |
1113 : SubWidget(parentWidget), | |
1114 NanoVG(parentWidget->getContext()), | |
1115 fUsingParentContext(true) | |
1116 { | |
1117 setSkipDrawing(); | |
1118 } | |
1119 | |
1120 template <> | |
1121 inline void NanoBaseWidget<SubWidget>::onDisplay() | |
1122 { | |
1123 if (fUsingParentContext) | |
1124 { | |
1125 NanoVG::save(); | |
1126 translate(SubWidget::getAbsoluteX(), SubWidget::getAbsoluteY()); | |
1127 onNanoDisplay(); | |
1128 NanoVG::restore(); | |
1129 displayChildren(); | |
1130 } | |
1131 else | |
1132 { | |
1133 NanoVG::beginFrame(SubWidget::getWidth(), SubWidget::getHeight()); | |
1134 onNanoDisplay(); | |
1135 displayChildren(); | |
1136 NanoVG::endFrame(); | |
1137 } | |
1138 } | |
1139 | |
1140 template class NanoBaseWidget<SubWidget>; | |
1141 | |
1142 // ----------------------------------------------------------------------- | |
1143 // NanoTopLevelWidget | |
1144 | |
1145 template <> | |
1146 NanoBaseWidget<TopLevelWidget>::NanoBaseWidget(Window& windowToMapTo, int flags) | |
1147 : TopLevelWidget(windowToMapTo), | |
1148 NanoVG(flags), | |
1149 fUsingParentContext(false) {} | |
1150 | |
1151 template <> | |
1152 inline void NanoBaseWidget<TopLevelWidget>::onDisplay() | |
1153 { | |
1154 NanoVG::beginFrame(TopLevelWidget::getWidth(), TopLevelWidget::getHeight()); | |
1155 onNanoDisplay(); | |
1156 displayChildren(); | |
1157 NanoVG::endFrame(); | |
1158 } | |
1159 | |
1160 template class NanoBaseWidget<TopLevelWidget>; | |
1161 | |
1162 // ----------------------------------------------------------------------- | |
1163 // NanoStandaloneWindow | |
1164 | |
1165 template <> | |
1166 NanoBaseWidget<StandaloneWindow>::NanoBaseWidget(Application& app, int flags) | |
1167 : StandaloneWindow(app), | |
1168 NanoVG(flags), | |
1169 fUsingParentContext(false) {} | |
1170 | |
1171 template <> | |
1172 NanoBaseWidget<StandaloneWindow>::NanoBaseWidget(Application& app, Window& parentWindow, int flags) | |
1173 : StandaloneWindow(app, parentWindow), | |
1174 NanoVG(flags), | |
1175 fUsingParentContext(false) {} | |
1176 | |
1177 template <> | |
1178 inline void NanoBaseWidget<StandaloneWindow>::onDisplay() | |
1179 { | |
1180 NanoVG::beginFrame(Window::getWidth(), Window::getHeight()); | |
1181 onNanoDisplay(); | |
1182 displayChildren(); | |
1183 NanoVG::endFrame(); | |
1184 } | |
1185 | |
1186 template class NanoBaseWidget<StandaloneWindow>; | |
1187 | |
1188 // ----------------------------------------------------------------------- | |
1189 | |
1190 END_NAMESPACE_DGL | |
1191 | |
1192 #undef final | |
1193 | |
1194 #if defined(__GNUC__) && (__GNUC__ >= 6) | |
1195 # pragma GCC diagnostic push | |
1196 # pragma GCC diagnostic ignored "-Wmisleading-indentation" | |
1197 # pragma GCC diagnostic ignored "-Wshift-negative-value" | |
1198 #endif | |
1199 | |
1200 extern "C" { | |
1201 #include "nanovg/nanovg.c" | |
1202 } | |
1203 | |
1204 #if defined(__GNUC__) && (__GNUC__ >= 6) | |
1205 # pragma GCC diagnostic pop | |
1206 #endif | |
1207 | |
1208 // ----------------------------------------------------------------------- |