Audio plugin host https://kx.studio/carla
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.

NanoVG.cpp 24KB

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