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.

993 lines
28KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2018 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 "WidgetPrivateData.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. # undef DGL_EXT
  53. #endif
  54. // -----------------------------------------------------------------------
  55. // Include NanoVG OpenGL implementation
  56. //#define STB_IMAGE_STATIC
  57. #define NANOVG_GL2_IMPLEMENTATION
  58. #include "nanovg/nanovg_gl.h"
  59. #if defined(NANOVG_GL2)
  60. # define nvgCreateGL nvgCreateGL2
  61. # define nvgDeleteGL nvgDeleteGL2
  62. #elif defined(NANOVG_GL3)
  63. # define nvgCreateGL nvgCreateGL3
  64. # define nvgDeleteGL nvgDeleteGL3
  65. #elif defined(NANOVG_GLES2)
  66. # define nvgCreateGL nvgCreateGLES2
  67. # define nvgDeleteGL nvgDeleteGLES2
  68. #elif defined(NANOVG_GLES3)
  69. # define nvgCreateGL nvgCreateGLES3
  70. # define nvgDeleteGL nvgDeleteGLES3
  71. #endif
  72. static NVGcontext* nvgCreateGL_helper(int flags)
  73. {
  74. #if defined(DISTRHO_OS_WINDOWS)
  75. static bool needsInit = true;
  76. if (needsInit)
  77. {
  78. needsInit = false;
  79. # define DGL_EXT(PROC, func) \
  80. func = (PROC) wglGetProcAddress ( #func ); \
  81. DISTRHO_SAFE_ASSERT_RETURN(func != nullptr, nullptr);
  82. DGL_EXT(PFNGLACTIVETEXTUREPROC, glActiveTexture)
  83. DGL_EXT(PFNGLATTACHSHADERPROC, glAttachShader)
  84. DGL_EXT(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation)
  85. DGL_EXT(PFNGLBINDBUFFERPROC, glBindBuffer)
  86. DGL_EXT(PFNGLBUFFERDATAPROC, glBufferData)
  87. DGL_EXT(PFNGLCOMPILESHADERPROC, glCompileShader)
  88. DGL_EXT(PFNGLCREATEPROGRAMPROC, glCreateProgram)
  89. DGL_EXT(PFNGLCREATESHADERPROC, glCreateShader)
  90. DGL_EXT(PFNGLDELETEBUFFERSPROC, glDeleteBuffers)
  91. DGL_EXT(PFNGLDELETEPROGRAMPROC, glDeleteProgram)
  92. DGL_EXT(PFNGLDELETESHADERPROC, glDeleteShader)
  93. DGL_EXT(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray)
  94. DGL_EXT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray)
  95. DGL_EXT(PFNGLGENBUFFERSPROC, glGenBuffers)
  96. DGL_EXT(PFNGLGETPROGRAMIVPROC, glGetProgramiv)
  97. DGL_EXT(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog)
  98. DGL_EXT(PFNGLGETSHADERIVPROC, glGetShaderiv)
  99. DGL_EXT(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog)
  100. DGL_EXT(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation)
  101. DGL_EXT(PFNGLLINKPROGRAMPROC, glLinkProgram)
  102. DGL_EXT(PFNGLSHADERSOURCEPROC, glShaderSource)
  103. DGL_EXT(PFNGLSTENCILOPSEPARATEPROC, glStencilOpSeparate)
  104. DGL_EXT(PFNGLUNIFORM1IPROC, glUniform1i)
  105. DGL_EXT(PFNGLUNIFORM2FVPROC, glUniform2fv)
  106. DGL_EXT(PFNGLUNIFORM4FVPROC, glUniform4fv)
  107. DGL_EXT(PFNGLUSEPROGRAMPROC, glUseProgram)
  108. DGL_EXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer)
  109. # undef DGL_EXT
  110. }
  111. #endif
  112. return nvgCreateGL(flags);
  113. }
  114. // -----------------------------------------------------------------------
  115. START_NAMESPACE_DGL
  116. // -----------------------------------------------------------------------
  117. // NanoImage
  118. NanoImage::NanoImage()
  119. : fHandle(),
  120. fSize() {}
  121. NanoImage::NanoImage(const Handle& handle)
  122. : fHandle(handle),
  123. fSize()
  124. {
  125. DISTRHO_SAFE_ASSERT_RETURN(fHandle.context != nullptr && fHandle.imageId != 0,);
  126. _updateSize();
  127. }
  128. NanoImage::~NanoImage()
  129. {
  130. if (fHandle.context != nullptr && fHandle.imageId != 0)
  131. nvgDeleteImage(fHandle.context, fHandle.imageId);
  132. }
  133. NanoImage& NanoImage::operator=(const Handle& handle)
  134. {
  135. if (fHandle.context != nullptr && fHandle.imageId != 0)
  136. nvgDeleteImage(fHandle.context, fHandle.imageId);
  137. fHandle.context = handle.context;
  138. fHandle.imageId = handle.imageId;
  139. return *this;
  140. }
  141. bool NanoImage::isValid() const noexcept
  142. {
  143. return (fHandle.context != nullptr && fHandle.imageId != 0);
  144. }
  145. Size<uint> NanoImage::getSize() const noexcept
  146. {
  147. return fSize;
  148. }
  149. GLuint NanoImage::getTextureHandle() const
  150. {
  151. DISTRHO_SAFE_ASSERT_RETURN(fHandle.context != nullptr && fHandle.imageId != 0, 0);
  152. return nvglImageHandle(fHandle.context, fHandle.imageId);
  153. }
  154. void NanoImage::_updateSize()
  155. {
  156. int w=0, h=0;
  157. nvgImageSize(fHandle.context, fHandle.imageId, &w, &h);
  158. if (w < 0) w = 0;
  159. if (h < 0) h = 0;
  160. fSize.setSize(static_cast<uint>(w), static_cast<uint>(h));
  161. }
  162. // -----------------------------------------------------------------------
  163. // Paint
  164. NanoVG::Paint::Paint() noexcept
  165. : radius(0.0f), feather(0.0f), innerColor(), outerColor(), imageId(0)
  166. {
  167. std::memset(xform, 0, sizeof(float)*6);
  168. std::memset(extent, 0, sizeof(float)*2);
  169. }
  170. NanoVG::Paint::Paint(const NVGpaint& p) noexcept
  171. : radius(p.radius), feather(p.feather), innerColor(p.innerColor), outerColor(p.outerColor), imageId(p.image)
  172. {
  173. std::memcpy(xform, p.xform, sizeof(float)*6);
  174. std::memcpy(extent, p.extent, sizeof(float)*2);
  175. }
  176. NanoVG::Paint::operator NVGpaint() const noexcept
  177. {
  178. NVGpaint p;
  179. p.radius = radius;
  180. p.feather = feather;
  181. p.innerColor = innerColor;
  182. p.outerColor = outerColor;
  183. p.image = imageId;
  184. std::memcpy(p.xform, xform, sizeof(float)*6);
  185. std::memcpy(p.extent, extent, sizeof(float)*2);
  186. return p;
  187. }
  188. // -----------------------------------------------------------------------
  189. // NanoVG
  190. NanoVG::NanoVG(int flags)
  191. : fContext(nvgCreateGL_helper(flags)),
  192. fInFrame(false),
  193. fIsSubWidget(false) {}
  194. NanoVG::NanoVG(NanoWidget* groupWidget)
  195. : fContext(groupWidget->fContext),
  196. fInFrame(false),
  197. fIsSubWidget(true) {}
  198. NanoVG::~NanoVG()
  199. {
  200. DISTRHO_SAFE_ASSERT(! fInFrame);
  201. if (fContext != nullptr && ! fIsSubWidget)
  202. nvgDeleteGL(fContext);
  203. }
  204. // -----------------------------------------------------------------------
  205. void NanoVG::beginFrame(const uint width, const uint height, const float scaleFactor)
  206. {
  207. if (fContext == nullptr) return;
  208. DISTRHO_SAFE_ASSERT_RETURN(scaleFactor > 0.0f,);
  209. DISTRHO_SAFE_ASSERT_RETURN(! fInFrame,);
  210. fInFrame = true;
  211. nvgBeginFrame(fContext, static_cast<int>(width), static_cast<int>(height), scaleFactor);
  212. }
  213. void NanoVG::beginFrame(Widget* const widget)
  214. {
  215. DISTRHO_SAFE_ASSERT_RETURN(widget != nullptr,);
  216. DISTRHO_SAFE_ASSERT_RETURN(! fInFrame,);
  217. fInFrame = true;
  218. if (fContext == nullptr)
  219. return;
  220. Window& window(widget->getParentWindow());
  221. nvgBeginFrame(fContext, static_cast<int>(window.getWidth()), static_cast<int>(window.getHeight()), 1.0f);
  222. }
  223. void NanoVG::cancelFrame()
  224. {
  225. DISTRHO_SAFE_ASSERT_RETURN(fInFrame,);
  226. if (fContext != nullptr)
  227. nvgCancelFrame(fContext);
  228. fInFrame = false;
  229. }
  230. void NanoVG::endFrame()
  231. {
  232. DISTRHO_SAFE_ASSERT_RETURN(fInFrame,);
  233. // Save current blend state
  234. GLboolean blendEnabled;
  235. GLint blendSrc, blendDst;
  236. glGetBooleanv(GL_BLEND, &blendEnabled);
  237. glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrc);
  238. glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDst);
  239. if (fContext != nullptr)
  240. nvgEndFrame(fContext);
  241. // Restore blend state
  242. if (blendEnabled)
  243. glEnable(GL_BLEND);
  244. else
  245. glDisable(GL_BLEND);
  246. glBlendFunc(blendSrc, blendDst);
  247. fInFrame = false;
  248. }
  249. // -----------------------------------------------------------------------
  250. // State Handling
  251. void NanoVG::save()
  252. {
  253. if (fContext != nullptr)
  254. nvgSave(fContext);
  255. }
  256. void NanoVG::restore()
  257. {
  258. if (fContext != nullptr)
  259. nvgRestore(fContext);
  260. }
  261. void NanoVG::reset()
  262. {
  263. if (fContext != nullptr)
  264. nvgReset(fContext);
  265. }
  266. // -----------------------------------------------------------------------
  267. // Render styles
  268. void NanoVG::strokeColor(const Color& color)
  269. {
  270. if (fContext != nullptr)
  271. nvgStrokeColor(fContext, color);
  272. }
  273. void NanoVG::strokeColor(const int red, const int green, const int blue, const int alpha)
  274. {
  275. if (fContext != nullptr)
  276. {
  277. DISTRHO_SAFE_ASSERT_RETURN(red >= 0 && red <= 255,);
  278. DISTRHO_SAFE_ASSERT_RETURN(green >= 0 && green <= 255,);
  279. DISTRHO_SAFE_ASSERT_RETURN(blue >= 0 && blue <= 255,);
  280. DISTRHO_SAFE_ASSERT_RETURN(alpha >= 0 && alpha <= 255,);
  281. nvgStrokeColor(fContext, nvgRGBA(static_cast<uchar>(red),
  282. static_cast<uchar>(green),
  283. static_cast<uchar>(blue),
  284. static_cast<uchar>(alpha)));
  285. }
  286. }
  287. void NanoVG::strokeColor(const float red, const float green, const float blue, const float alpha)
  288. {
  289. if (fContext != nullptr)
  290. nvgStrokeColor(fContext, nvgRGBAf(red, green, blue, alpha));
  291. }
  292. void NanoVG::strokePaint(const Paint& paint)
  293. {
  294. if (fContext != nullptr)
  295. nvgStrokePaint(fContext, paint);
  296. }
  297. void NanoVG::fillColor(const Color& color)
  298. {
  299. if (fContext != nullptr)
  300. nvgFillColor(fContext, color);
  301. }
  302. void NanoVG::fillColor(const int red, const int green, const int blue, const int alpha)
  303. {
  304. if (fContext != nullptr)
  305. {
  306. DISTRHO_SAFE_ASSERT_RETURN(red >= 0 && red <= 255,);
  307. DISTRHO_SAFE_ASSERT_RETURN(green >= 0 && green <= 255,);
  308. DISTRHO_SAFE_ASSERT_RETURN(blue >= 0 && blue <= 255,);
  309. DISTRHO_SAFE_ASSERT_RETURN(alpha >= 0 && alpha <= 255,);
  310. nvgFillColor(fContext, nvgRGBA(static_cast<uchar>(red),
  311. static_cast<uchar>(green),
  312. static_cast<uchar>(blue),
  313. static_cast<uchar>(alpha)));
  314. }
  315. }
  316. void NanoVG::fillColor(const float red, const float green, const float blue, const float alpha)
  317. {
  318. if (fContext != nullptr)
  319. nvgFillColor(fContext, nvgRGBAf(red, green, blue, alpha));
  320. }
  321. void NanoVG::fillPaint(const Paint& paint)
  322. {
  323. if (fContext != nullptr)
  324. nvgFillPaint(fContext, paint);
  325. }
  326. void NanoVG::miterLimit(float limit)
  327. {
  328. if (fContext == nullptr) return;
  329. DISTRHO_SAFE_ASSERT_RETURN(limit > 0.0f,);
  330. nvgMiterLimit(fContext, limit);
  331. }
  332. void NanoVG::strokeWidth(float size)
  333. {
  334. if (fContext == nullptr) return;
  335. DISTRHO_SAFE_ASSERT_RETURN(size > 0.0f,);
  336. nvgStrokeWidth(fContext, size);
  337. }
  338. void NanoVG::lineCap(NanoVG::LineCap cap)
  339. {
  340. if (fContext != nullptr)
  341. nvgLineCap(fContext, cap);
  342. }
  343. void NanoVG::lineJoin(NanoVG::LineCap join)
  344. {
  345. if (fContext != nullptr)
  346. nvgLineJoin(fContext, join);
  347. }
  348. void NanoVG::globalAlpha(float alpha)
  349. {
  350. if (fContext != nullptr)
  351. nvgGlobalAlpha(fContext, alpha);
  352. }
  353. // -----------------------------------------------------------------------
  354. // Transforms
  355. void NanoVG::resetTransform()
  356. {
  357. if (fContext != nullptr)
  358. nvgResetTransform(fContext);
  359. }
  360. void NanoVG::transform(float a, float b, float c, float d, float e, float f)
  361. {
  362. if (fContext != nullptr)
  363. nvgTransform(fContext, a, b, c, d, e, f);
  364. }
  365. void NanoVG::translate(float x, float y)
  366. {
  367. if (fContext != nullptr)
  368. nvgTranslate(fContext, x, y);
  369. }
  370. void NanoVG::rotate(float angle)
  371. {
  372. if (fContext != nullptr)
  373. nvgRotate(fContext, angle);
  374. }
  375. void NanoVG::skewX(float angle)
  376. {
  377. if (fContext == nullptr) return;
  378. DISTRHO_SAFE_ASSERT_RETURN(angle > 0.0f,);
  379. nvgSkewX(fContext, angle);
  380. }
  381. void NanoVG::skewY(float angle)
  382. {
  383. if (fContext == nullptr) return;
  384. DISTRHO_SAFE_ASSERT_RETURN(angle > 0.0f,);
  385. nvgSkewY(fContext, angle);
  386. }
  387. void NanoVG::scale(float x, float y)
  388. {
  389. if (fContext == nullptr) return;
  390. DISTRHO_SAFE_ASSERT_RETURN(d_isNotZero(x),);
  391. DISTRHO_SAFE_ASSERT_RETURN(d_isNotZero(y),);
  392. nvgScale(fContext, x, y);
  393. }
  394. void NanoVG::currentTransform(float xform[6])
  395. {
  396. if (fContext != nullptr)
  397. nvgCurrentTransform(fContext, xform);
  398. }
  399. void NanoVG::transformIdentity(float dst[6])
  400. {
  401. nvgTransformIdentity(dst);
  402. }
  403. void NanoVG::transformTranslate(float dst[6], float tx, float ty)
  404. {
  405. nvgTransformTranslate(dst, tx, ty);
  406. }
  407. void NanoVG::transformScale(float dst[6], float sx, float sy)
  408. {
  409. nvgTransformScale(dst, sx, sy);
  410. }
  411. void NanoVG::transformRotate(float dst[6], float a)
  412. {
  413. nvgTransformRotate(dst, a);
  414. }
  415. void NanoVG::transformSkewX(float dst[6], float a)
  416. {
  417. nvgTransformSkewX(dst, a);
  418. }
  419. void NanoVG::transformSkewY(float dst[6], float a)
  420. {
  421. nvgTransformSkewY(dst, a);
  422. }
  423. void NanoVG::transformMultiply(float dst[6], const float src[6])
  424. {
  425. nvgTransformMultiply(dst, src);
  426. }
  427. void NanoVG::transformPremultiply(float dst[6], const float src[6])
  428. {
  429. nvgTransformPremultiply(dst, src);
  430. }
  431. int NanoVG::transformInverse(float dst[6], const float src[6])
  432. {
  433. return nvgTransformInverse(dst, src);
  434. }
  435. void NanoVG::transformPoint(float& dstx, float& dsty, const float xform[6], float srcx, float srcy)
  436. {
  437. nvgTransformPoint(&dstx, &dsty, xform, srcx, srcy);
  438. }
  439. float NanoVG::degToRad(float deg)
  440. {
  441. return nvgDegToRad(deg);
  442. }
  443. float NanoVG::radToDeg(float rad)
  444. {
  445. return nvgRadToDeg(rad);
  446. }
  447. // -----------------------------------------------------------------------
  448. // Images
  449. NanoImage::Handle NanoVG::createImageFromFile(const char* filename, ImageFlags imageFlags)
  450. {
  451. return createImageFromFile(filename, static_cast<int>(imageFlags));
  452. }
  453. NanoImage::Handle NanoVG::createImageFromFile(const char* filename, int imageFlags)
  454. {
  455. if (fContext == nullptr) return NanoImage::Handle();
  456. DISTRHO_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', NanoImage::Handle());
  457. return NanoImage::Handle(fContext, nvgCreateImage(fContext, filename, imageFlags));
  458. }
  459. NanoImage::Handle NanoVG::createImageFromMemory(uchar* data, uint dataSize, ImageFlags imageFlags)
  460. {
  461. return createImageFromMemory(data, dataSize, static_cast<int>(imageFlags));
  462. }
  463. NanoImage::Handle NanoVG::createImageFromMemory(uchar* data, uint dataSize, int imageFlags)
  464. {
  465. if (fContext == nullptr) return NanoImage::Handle();
  466. DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, NanoImage::Handle());
  467. DISTRHO_SAFE_ASSERT_RETURN(dataSize > 0, NanoImage::Handle());
  468. return NanoImage::Handle(fContext, nvgCreateImageMem(fContext, imageFlags, data,static_cast<int>(dataSize)));
  469. }
  470. NanoImage::Handle NanoVG::createImageFromRGBA(uint w, uint h, const uchar* data, ImageFlags imageFlags)
  471. {
  472. return createImageFromRGBA(w, h, data, static_cast<int>(imageFlags));
  473. }
  474. NanoImage::Handle NanoVG::createImageFromRGBA(uint w, uint h, const uchar* data, int imageFlags)
  475. {
  476. if (fContext == nullptr) return NanoImage::Handle();
  477. DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, NanoImage::Handle());
  478. return NanoImage::Handle(fContext, nvgCreateImageRGBA(fContext,
  479. static_cast<int>(w),
  480. static_cast<int>(h), imageFlags, data));
  481. }
  482. NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, ImageFlags imageFlags, bool deleteTexture)
  483. {
  484. return createImageFromTextureHandle(textureId, w, h, static_cast<int>(imageFlags), deleteTexture);
  485. }
  486. NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, int imageFlags, bool deleteTexture)
  487. {
  488. if (fContext == nullptr) return NanoImage::Handle();
  489. DISTRHO_SAFE_ASSERT_RETURN(textureId != 0, NanoImage::Handle());
  490. if (! deleteTexture)
  491. imageFlags |= NVG_IMAGE_NODELETE;
  492. return NanoImage::Handle(fContext, nvglCreateImageFromHandle(fContext,
  493. textureId,
  494. static_cast<int>(w),
  495. static_cast<int>(h), imageFlags));
  496. }
  497. // -----------------------------------------------------------------------
  498. // Paints
  499. NanoVG::Paint NanoVG::linearGradient(float sx, float sy, float ex, float ey, const Color& icol, const Color& ocol)
  500. {
  501. if (fContext == nullptr) return Paint();
  502. return nvgLinearGradient(fContext, sx, sy, ex, ey, icol, ocol);
  503. }
  504. NanoVG::Paint NanoVG::boxGradient(float x, float y, float w, float h, float r, float f, const Color& icol, const Color& ocol)
  505. {
  506. if (fContext == nullptr) return Paint();
  507. return nvgBoxGradient(fContext, x, y, w, h, r, f, icol, ocol);
  508. }
  509. NanoVG::Paint NanoVG::radialGradient(float cx, float cy, float inr, float outr, const Color& icol, const Color& ocol)
  510. {
  511. if (fContext == nullptr) return Paint();
  512. return nvgRadialGradient(fContext, cx, cy, inr, outr, icol, ocol);
  513. }
  514. NanoVG::Paint NanoVG::imagePattern(float ox, float oy, float ex, float ey, float angle, const NanoImage& image, float alpha)
  515. {
  516. if (fContext == nullptr) return Paint();
  517. const int imageId(image.fHandle.imageId);
  518. DISTRHO_SAFE_ASSERT_RETURN(imageId != 0, Paint());
  519. return nvgImagePattern(fContext, ox, oy, ex, ey, angle, imageId, alpha);
  520. }
  521. // -----------------------------------------------------------------------
  522. // Scissoring
  523. void NanoVG::scissor(float x, float y, float w, float h)
  524. {
  525. if (fContext != nullptr)
  526. nvgScissor(fContext, x, y, w, h);
  527. }
  528. void NanoVG::intersectScissor(float x, float y, float w, float h)
  529. {
  530. if (fContext != nullptr)
  531. nvgIntersectScissor(fContext, x, y, w, h);
  532. }
  533. void NanoVG::resetScissor()
  534. {
  535. if (fContext != nullptr)
  536. nvgResetScissor(fContext);
  537. }
  538. // -----------------------------------------------------------------------
  539. // Paths
  540. void NanoVG::beginPath()
  541. {
  542. if (fContext != nullptr)
  543. nvgBeginPath(fContext);
  544. }
  545. void NanoVG::moveTo(float x, float y)
  546. {
  547. if (fContext != nullptr)
  548. nvgMoveTo(fContext, x, y);
  549. }
  550. void NanoVG::lineTo(float x, float y)
  551. {
  552. if (fContext != nullptr)
  553. nvgLineTo(fContext, x, y);
  554. }
  555. void NanoVG::bezierTo(float c1x, float c1y, float c2x, float c2y, float x, float y)
  556. {
  557. if (fContext != nullptr)
  558. nvgBezierTo(fContext, c1x, c1y, c2x, c2y, x, y);
  559. }
  560. void NanoVG::quadTo(float cx, float cy, float x, float y)
  561. {
  562. if (fContext != nullptr)
  563. nvgQuadTo(fContext, cx, cy, x, y);
  564. }
  565. void NanoVG::arcTo(float x1, float y1, float x2, float y2, float radius)
  566. {
  567. if (fContext != nullptr)
  568. nvgArcTo(fContext, x1, y1, x2, y2, radius);
  569. }
  570. void NanoVG::closePath()
  571. {
  572. if (fContext != nullptr)
  573. nvgClosePath(fContext);
  574. }
  575. void NanoVG::pathWinding(NanoVG::Winding dir)
  576. {
  577. if (fContext != nullptr)
  578. nvgPathWinding(fContext, dir);
  579. }
  580. void NanoVG::arc(float cx, float cy, float r, float a0, float a1, NanoVG::Winding dir)
  581. {
  582. if (fContext != nullptr)
  583. nvgArc(fContext, cx, cy, r, a0, a1, dir);
  584. }
  585. void NanoVG::rect(float x, float y, float w, float h)
  586. {
  587. if (fContext != nullptr)
  588. nvgRect(fContext, x, y, w, h);
  589. }
  590. void NanoVG::roundedRect(float x, float y, float w, float h, float r)
  591. {
  592. if (fContext != nullptr)
  593. nvgRoundedRect(fContext, x, y, w, h, r);
  594. }
  595. void NanoVG::ellipse(float cx, float cy, float rx, float ry)
  596. {
  597. if (fContext != nullptr)
  598. nvgEllipse(fContext, cx, cy, rx, ry);
  599. }
  600. void NanoVG::circle(float cx, float cy, float r)
  601. {
  602. if (fContext != nullptr)
  603. nvgCircle(fContext, cx, cy, r);
  604. }
  605. void NanoVG::fill()
  606. {
  607. if (fContext != nullptr)
  608. nvgFill(fContext);
  609. }
  610. void NanoVG::stroke()
  611. {
  612. if (fContext != nullptr)
  613. nvgStroke(fContext);
  614. }
  615. // -----------------------------------------------------------------------
  616. // Text
  617. NanoVG::FontId NanoVG::createFontFromFile(const char* name, const char* filename)
  618. {
  619. if (fContext == nullptr) return -1;
  620. DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1);
  621. DISTRHO_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', -1);
  622. return nvgCreateFont(fContext, name, filename);
  623. }
  624. NanoVG::FontId NanoVG::createFontFromMemory(const char* name, const uchar* data, uint dataSize, bool freeData)
  625. {
  626. if (fContext == nullptr) return -1;
  627. DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1);
  628. DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, -1);
  629. return nvgCreateFontMem(fContext, name, const_cast<uchar*>(data), static_cast<int>(dataSize), freeData);
  630. }
  631. NanoVG::FontId NanoVG::findFont(const char* name)
  632. {
  633. if (fContext == nullptr) return -1;
  634. DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1);
  635. return nvgFindFont(fContext, name);
  636. }
  637. void NanoVG::fontSize(float size)
  638. {
  639. if (fContext == nullptr) return;
  640. DISTRHO_SAFE_ASSERT_RETURN(size > 0.0f,);
  641. nvgFontSize(fContext, size);
  642. }
  643. void NanoVG::fontBlur(float blur)
  644. {
  645. if (fContext == nullptr) return;
  646. DISTRHO_SAFE_ASSERT_RETURN(blur >= 0.0f,);
  647. nvgFontBlur(fContext, blur);
  648. }
  649. void NanoVG::textLetterSpacing(float spacing)
  650. {
  651. if (fContext == nullptr) return;
  652. DISTRHO_SAFE_ASSERT_RETURN(spacing >= 0.0f,);
  653. nvgTextLetterSpacing(fContext, spacing);
  654. }
  655. void NanoVG::textLineHeight(float lineHeight)
  656. {
  657. if (fContext == nullptr) return;
  658. DISTRHO_SAFE_ASSERT_RETURN(lineHeight > 0.0f,);
  659. nvgTextLineHeight(fContext, lineHeight);
  660. }
  661. void NanoVG::textAlign(NanoVG::Align align)
  662. {
  663. if (fContext != nullptr)
  664. nvgTextAlign(fContext, align);
  665. }
  666. void NanoVG::textAlign(int align)
  667. {
  668. if (fContext != nullptr)
  669. nvgTextAlign(fContext, align);
  670. }
  671. void NanoVG::fontFaceId(FontId font)
  672. {
  673. if (fContext == nullptr) return;
  674. DISTRHO_SAFE_ASSERT_RETURN(font >= 0,);
  675. nvgFontFaceId(fContext, font);
  676. }
  677. void NanoVG::fontFace(const char* font)
  678. {
  679. if (fContext == nullptr) return;
  680. DISTRHO_SAFE_ASSERT_RETURN(font != nullptr && font[0] != '\0',);
  681. nvgFontFace(fContext, font);
  682. }
  683. float NanoVG::text(float x, float y, const char* string, const char* end)
  684. {
  685. if (fContext == nullptr) return 0.0f;
  686. DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0', 0.0f);
  687. return nvgText(fContext, x, y, string, end);
  688. }
  689. void NanoVG::textBox(float x, float y, float breakRowWidth, const char* string, const char* end)
  690. {
  691. if (fContext == nullptr) return;
  692. DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0',);
  693. nvgTextBox(fContext, x, y, breakRowWidth, string, end);
  694. }
  695. float NanoVG::textBounds(float x, float y, const char* string, const char* end, Rectangle<float>& bounds)
  696. {
  697. if (fContext == nullptr) return 0.0f;
  698. DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0', 0.0f);
  699. float b[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  700. const float ret = nvgTextBounds(fContext, x, y, string, end, b);
  701. bounds = Rectangle<float>(b[0], b[1], b[2] - b[0], b[3] - b[1]);
  702. return ret;
  703. }
  704. void NanoVG::textBoxBounds(float x, float y, float breakRowWidth, const char* string, const char* end, float bounds[4])
  705. {
  706. if (fContext == nullptr) return;
  707. DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0',);
  708. nvgTextBoxBounds(fContext, x, y, breakRowWidth, string, end, bounds);
  709. }
  710. int NanoVG::textGlyphPositions(float x, float y, const char* string, const char* end, NanoVG::GlyphPosition& positions, int maxPositions)
  711. {
  712. if (fContext == nullptr) return 0;
  713. DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0', 0);
  714. return nvgTextGlyphPositions(fContext, x, y, string, end, (NVGglyphPosition*)&positions, maxPositions);
  715. }
  716. void NanoVG::textMetrics(float* ascender, float* descender, float* lineh)
  717. {
  718. if (fContext != nullptr)
  719. nvgTextMetrics(fContext, ascender, descender, lineh);
  720. }
  721. int NanoVG::textBreakLines(const char* string, const char* end, float breakRowWidth, NanoVG::TextRow& rows, int maxRows)
  722. {
  723. if (fContext != nullptr)
  724. return nvgTextBreakLines(fContext, string, end, breakRowWidth, (NVGtextRow*)&rows, maxRows);
  725. return 0;
  726. }
  727. #ifndef DGL_NO_SHARED_RESOURCES
  728. void NanoVG::loadSharedResources()
  729. {
  730. if (nvgFindFont(fContext, NANOVG_DEJAVU_SANS_TTF) >= 0)
  731. return;
  732. using namespace dpf_resources;
  733. nvgCreateFontMem(fContext, NANOVG_DEJAVU_SANS_TTF, (const uchar*)dejavusans_ttf, dejavusans_ttf_size, 0);
  734. }
  735. #endif
  736. // -----------------------------------------------------------------------
  737. struct NanoWidget::PrivateData {
  738. NanoWidget* const self;
  739. std::vector<NanoWidget*> subWidgets;
  740. PrivateData(NanoWidget* const s)
  741. : self(s),
  742. subWidgets() {}
  743. ~PrivateData()
  744. {
  745. subWidgets.clear();
  746. }
  747. };
  748. NanoWidget::NanoWidget(Window& parent, int flags)
  749. : Widget(parent),
  750. NanoVG(flags),
  751. nData(new PrivateData(this))
  752. {
  753. pData->needsScaling = true;
  754. }
  755. NanoWidget::NanoWidget(Widget* groupWidget, int flags)
  756. : Widget(groupWidget, true),
  757. NanoVG(flags),
  758. nData(new PrivateData(this))
  759. {
  760. pData->needsScaling = true;
  761. }
  762. NanoWidget::NanoWidget(NanoWidget* groupWidget)
  763. : Widget(groupWidget, false),
  764. NanoVG(groupWidget),
  765. nData(new PrivateData(this))
  766. {
  767. pData->needsScaling = true;
  768. pData->skipDisplay = true;
  769. groupWidget->nData->subWidgets.push_back(this);
  770. }
  771. NanoWidget::~NanoWidget()
  772. {
  773. delete nData;
  774. }
  775. void NanoWidget::onDisplay()
  776. {
  777. NanoVG::beginFrame(getWidth(), getHeight());
  778. onNanoDisplay();
  779. for (std::vector<NanoWidget*>::iterator it = nData->subWidgets.begin(); it != nData->subWidgets.end(); ++it)
  780. {
  781. NanoWidget* const widget(*it);
  782. widget->onNanoDisplay();
  783. }
  784. NanoVG::endFrame();
  785. }
  786. // -----------------------------------------------------------------------
  787. END_NAMESPACE_DGL
  788. #undef final
  789. #if defined(__GNUC__) && (__GNUC__ >= 6)
  790. # pragma GCC diagnostic push
  791. # pragma GCC diagnostic ignored "-Wmisleading-indentation"
  792. # pragma GCC diagnostic ignored "-Wshift-negative-value"
  793. #endif
  794. extern "C" {
  795. #include "nanovg/nanovg.c"
  796. }
  797. #if defined(__GNUC__) && (__GNUC__ >= 6)
  798. # pragma GCC diagnostic pop
  799. #endif
  800. // -----------------------------------------------------------------------