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.

1113 lines
33KB

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