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.

133 lines
3.8KB

  1. #include "widgets.hpp"
  2. // #define DEBUG_ONLY(x) x
  3. #define DEBUG_ONLY(x)
  4. namespace rack {
  5. static NVGcolor getNVGColor(uint32_t color) {
  6. return nvgRGBA(
  7. (color >> 0) & 0xff,
  8. (color >> 8) & 0xff,
  9. (color >> 16) & 0xff,
  10. (color >> 24) & 0xff);
  11. }
  12. static void drawSVG(NVGcontext *vg, NSVGimage *svg) {
  13. DEBUG_ONLY(printf("new image: %g x %g px\n", svg->width, svg->height);)
  14. int shapeIndex = 0;
  15. for (NSVGshape *shape = svg->shapes; shape; shape = shape->next, shapeIndex++) {
  16. DEBUG_ONLY(printf(" new shape: %d id \"%s\", fillrule %d, from (%f, %f) to (%f, %f)\n", shapeIndex, shape->id, shape->fillRule, shape->bounds[0], shape->bounds[1], shape->bounds[2], shape->bounds[3]);)
  17. if (!(shape->flags & NSVG_FLAGS_VISIBLE))
  18. continue;
  19. nvgSave(vg);
  20. if (shape->opacity < 1.0)
  21. nvgGlobalAlpha(vg, shape->opacity);
  22. // Build path
  23. nvgBeginPath(vg);
  24. for (NSVGpath *path = shape->paths; path; path = path->next) {
  25. DEBUG_ONLY(printf(" new path: %d points, %s, from (%f, %f) to (%f, %f)\n", path->npts, path->closed ? "closed" : "open", path->bounds[0], path->bounds[1], path->bounds[2], path->bounds[3]);)
  26. nvgMoveTo(vg, path->pts[0], path->pts[1]);
  27. for (int i = 1; i < path->npts; i += 3) {
  28. float *p = &path->pts[2*i];
  29. nvgBezierTo(vg, p[0], p[1], p[2], p[3], p[4], p[5]);
  30. // nvgLineTo(vg, p[4], p[5]);
  31. }
  32. if (path->closed)
  33. nvgClosePath(vg);
  34. // if ()
  35. // nvgPathWinding(vg, NVG_SOLID);
  36. // else
  37. // nvgPathWinding(vg, NVG_HOLE);
  38. }
  39. // Fill shape
  40. if (shape->fill.type) {
  41. switch (shape->fill.type) {
  42. case NSVG_PAINT_COLOR: {
  43. NVGcolor color = getNVGColor(shape->fill.color);
  44. nvgFillColor(vg, color);
  45. DEBUG_ONLY(printf(" fill color (%g, %g, %g, %g)\n", color.r, color.g, color.b, color.a);)
  46. } break;
  47. case NSVG_PAINT_LINEAR_GRADIENT: {
  48. NSVGgradient *g = shape->fill.gradient;
  49. DEBUG_ONLY(printf(" linear gradient: %f\t%f\n", g->fx, g->fy);)
  50. } break;
  51. case NSVG_PAINT_RADIAL_GRADIENT: {
  52. NSVGgradient *g = shape->fill.gradient;
  53. DEBUG_ONLY(printf(" radial gradient: %f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n", g->fx, g->fy, g->xform[0], g->xform[1], g->xform[2], g->xform[3], g->xform[4], g->xform[5]);)
  54. for (int i = 0; i < g->nstops; i++) {
  55. DEBUG_ONLY(printf(" stop: #%08x\t%f\n", g->stops[i].color, g->stops[i].offset);)
  56. }
  57. assert(g->nstops >= 1);
  58. NVGcolor color0 = getNVGColor(g->stops[0].color);
  59. NVGcolor color1 = getNVGColor(g->stops[g->nstops - 1].color);
  60. float inverse[6];
  61. Rect shapeBox = Rect::fromMinMax(Vec(shape->bounds[0], shape->bounds[1]), Vec(shape->bounds[2], shape->bounds[3]));
  62. nvgTransformInverse(inverse, g->xform);
  63. Vec c;
  64. nvgTransformPoint(&c.x, &c.y, inverse, 5, 5);
  65. printf("%f %f\n", c.x, c.y);
  66. NVGpaint paint = nvgRadialGradient(vg, c.x, c.y, 0.0, 160, color0, color1);
  67. nvgFillPaint(vg, paint);
  68. } break;
  69. }
  70. nvgFill(vg);
  71. }
  72. // Stroke shape
  73. nvgStrokeWidth(vg, shape->strokeWidth);
  74. // strokeDashOffset, strokeDashArray, strokeDashCount not yet supported
  75. // strokeLineJoin, strokeLineCap not yet supported
  76. if (shape->stroke.type) {
  77. switch (shape->stroke.type) {
  78. case NSVG_PAINT_COLOR: {
  79. NVGcolor color = getNVGColor(shape->stroke.color);
  80. nvgStrokeColor(vg, color);
  81. DEBUG_ONLY(printf(" stroke color (%g, %g, %g, %g)\n", color.r, color.g, color.b, color.a);)
  82. } break;
  83. case NSVG_PAINT_LINEAR_GRADIENT: {
  84. // NSVGgradient *g = shape->stroke.gradient;
  85. // printf(" lin grad: %f\t%f\n", g->fx, g->fy);
  86. } break;
  87. }
  88. nvgStroke(vg);
  89. }
  90. nvgRestore(vg);
  91. }
  92. DEBUG_ONLY(printf("\n");)
  93. }
  94. void SVGWidget::wrap() {
  95. if (svg && svg->handle) {
  96. box.size = Vec(svg->handle->width, svg->handle->height);
  97. }
  98. else {
  99. box.size = Vec();
  100. }
  101. }
  102. void SVGWidget::draw(NVGcontext *vg) {
  103. if (svg && svg->handle) {
  104. drawSVG(vg, svg->handle);
  105. }
  106. }
  107. } // namespace rack