Collection of DPF-based plugins for packaging
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.

1222 lines
36KB

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