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.

990 lines
27KB

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