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.

CairoWidget.hpp 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * DISTRHO Plugin Toolkit (DPT)
  3. * Copyright (C) 2012-2013 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. #ifndef DGL_CAIRO_WIDGET_HPP_INCLUDED
  17. #define DGL_CAIRO_WIDGET_HPP_INCLUDED
  18. #include "Widget.hpp"
  19. #include <cairo.h>
  20. #include <cstdio>
  21. START_NAMESPACE_DGL
  22. // -----------------------------------------------------------------------
  23. class CairoWidget : public Widget
  24. {
  25. public:
  26. CairoWidget(Window& parent)
  27. : Widget(parent),
  28. fContext(nullptr),
  29. fSurface(nullptr),
  30. fTextureId(0)
  31. {
  32. }
  33. virtual void setWidth(int width) override
  34. {
  35. if (fArea.getWidth() == width)
  36. return;
  37. Widget::setWidth(width);
  38. _recreateSurface();
  39. }
  40. virtual void setHeight(int height) override
  41. {
  42. if (fArea.getHeight() == height)
  43. return;
  44. Widget::setHeight(height);
  45. _recreateSurface();
  46. }
  47. virtual void setSize(const Size<int>& size) override
  48. {
  49. if (fArea.getSize() == size)
  50. return;
  51. Widget::setSize(size);
  52. _recreateSurface();
  53. }
  54. void setSize(int width, int height)
  55. {
  56. setSize(Size<int>(width, height));
  57. }
  58. protected:
  59. virtual void cairoDisplay(cairo_t* const context) = 0;
  60. private:
  61. void onDisplay() override
  62. {
  63. // wait for sizing
  64. if (fSurface == nullptr || fContext == nullptr)
  65. {
  66. printf("invalid surface\n");
  67. return;
  68. }
  69. if (fTextureId == 0)
  70. glGenTextures(1, &fTextureId);
  71. if (fTextureId == 0)
  72. {
  73. // TODO: invalidate widget
  74. printf("invalid texture\n");
  75. return;
  76. }
  77. #if 1
  78. const int x = getX();
  79. const int y = getY();
  80. const int width = getWidth();
  81. const int height = getHeight();
  82. // draw cairo stuff
  83. cairoDisplay(fContext);
  84. // get cairo surface data (RGB24)
  85. unsigned char* const surfaceData = cairo_image_surface_get_data(fSurface);
  86. // enable GL texture
  87. glEnable(GL_TEXTURE_RECTANGLE_ARB);
  88. // set texture params
  89. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  90. glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  91. glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  92. // bind texture to surface data
  93. glBindTexture(GL_TEXTURE_RECTANGLE_ARB, fTextureId);
  94. glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, surfaceData);
  95. // draw the texture
  96. // glBegin(GL_QUADS);
  97. // glTexCoord2f(0.0f, 0.0f);
  98. // glVertex2i(x, y);
  99. //
  100. // glTexCoord2f(1.0f, 0.0f);
  101. // glVertex2i(x+width, y);
  102. //
  103. // glTexCoord2f(1.0f, 1.0f);
  104. // glVertex2i(x+width, y+height);
  105. //
  106. // glTexCoord2f(0.0f, 1.0f);
  107. // glVertex2i(x, y+height);
  108. // glEnd();
  109. glBegin(GL_QUADS);
  110. //glTexCoord2i(x, y);
  111. glTexCoord2i(0, 0);
  112. glVertex2i(x, y);
  113. //glTexCoord2i(x+width, y);
  114. glTexCoord2i(width, 0);
  115. glVertex2i(x+width, y);
  116. //glTexCoord2i(x+width, y+height);
  117. glTexCoord2i(width, height);
  118. glVertex2i(x+width, y+height);
  119. //glTexCoord2i(x, y+height);
  120. glTexCoord2i(0, height);
  121. glVertex2i(x, y+height);
  122. glEnd();
  123. // cleanup
  124. glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
  125. glDisable(GL_TEXTURE_RECTANGLE_ARB);
  126. #endif
  127. }
  128. void onClose() override
  129. {
  130. if (fContext != nullptr)
  131. {
  132. cairo_destroy(fContext);
  133. fContext = nullptr;
  134. }
  135. if (fSurface != nullptr)
  136. {
  137. cairo_surface_destroy(fSurface);
  138. fSurface = nullptr;
  139. }
  140. if (fTextureId != 0)
  141. {
  142. glDeleteTextures(1, &fTextureId);
  143. fTextureId = 0;
  144. }
  145. }
  146. void _recreateSurface()
  147. {
  148. if (fContext != nullptr)
  149. cairo_destroy(fContext);
  150. if (fSurface != nullptr)
  151. cairo_surface_destroy(fSurface);
  152. fSurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, fArea.getWidth(), fArea.getHeight());
  153. if (fSurface != nullptr)
  154. fContext = cairo_create(fSurface);
  155. else
  156. fContext = nullptr;
  157. }
  158. private:
  159. cairo_t* fContext;
  160. cairo_surface_t* fSurface;
  161. GLuint fTextureId;
  162. };
  163. // -----------------------------------------------------------------------
  164. END_NAMESPACE_DGL
  165. #endif // DGL_CAIRO_WIDGET_HPP_INCLUDED