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.

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