DISTRHO Plugin Framework
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1204 lines
36KB

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