@@ -141,6 +141,7 @@ struct SVGKnob : Knob, FramebufferWidget { | |||||
SVGKnob(); | SVGKnob(); | ||||
void setSVG(std::shared_ptr<SVG> svg); | void setSVG(std::shared_ptr<SVG> svg); | ||||
void step(); | void step(); | ||||
void draw(NVGcontext *vg); | |||||
void onChange(); | void onChange(); | ||||
}; | }; | ||||
@@ -180,15 +181,16 @@ struct MomentarySwitch : virtual Switch { | |||||
// ports | // ports | ||||
//////////////////// | //////////////////// | ||||
struct Port : OpaqueWidget, SpriteWidget { | |||||
struct Port : OpaqueWidget { | |||||
enum PortType { | enum PortType { | ||||
DEFAULT, | |||||
INPUT, | INPUT, | ||||
OUTPUT | OUTPUT | ||||
}; | }; | ||||
Module *module = NULL; | Module *module = NULL; | ||||
WireWidget *connectedWire = NULL; | WireWidget *connectedWire = NULL; | ||||
PortType type; | |||||
PortType type = DEFAULT; | |||||
int portId; | int portId; | ||||
Port(); | Port(); | ||||
@@ -204,6 +206,21 @@ struct Port : OpaqueWidget, SpriteWidget { | |||||
void onDragLeave(Widget *origin); | void onDragLeave(Widget *origin); | ||||
}; | }; | ||||
struct SpritePort : Port, SpriteWidget { | |||||
void draw(NVGcontext *vg) { | |||||
Port::draw(vg); | |||||
SpriteWidget::draw(vg); | |||||
} | |||||
}; | |||||
struct SVGPort : Port, FramebufferWidget { | |||||
SVGWidget *sw; | |||||
SVGPort(); | |||||
void setSVG(std::shared_ptr<SVG> svg); | |||||
void draw(NVGcontext *vg); | |||||
}; | |||||
//////////////////// | //////////////////// | ||||
// scene | // scene | ||||
//////////////////// | //////////////////// | ||||
@@ -24,15 +24,239 @@ extern const NVGcolor colors[NUM_COLORS]; | |||||
// Knobs | // Knobs | ||||
//////////////////// | //////////////////// | ||||
struct SynthTechAlco : SpriteKnob { | |||||
struct Rogan : SVGKnob { | |||||
Rogan() { | |||||
minAngle = -0.75*M_PI; | |||||
maxAngle = 0.75*M_PI; | |||||
} | |||||
}; | |||||
struct Rogan6PS : Rogan { | |||||
Rogan6PS() { | |||||
box.size = Vec(89, 89); | |||||
minAngle = -0.83*M_PI; | |||||
maxAngle = 0.83*M_PI; | |||||
} | |||||
}; | |||||
struct Rogan5PS : Rogan { | |||||
Rogan5PS() { | |||||
box.size = Vec(60, 60); | |||||
} | |||||
}; | |||||
struct Rogan3PS : Rogan { | |||||
Rogan3PS() { | |||||
box.size = Vec(52, 52); | |||||
} | |||||
}; | |||||
struct Rogan3P : Rogan { | |||||
Rogan3P() { | |||||
box.size = Vec(42, 42); | |||||
} | |||||
}; | |||||
struct Rogan2S : Rogan { | |||||
Rogan2S() { | |||||
box.size = Vec(43, 43); | |||||
} | |||||
}; | |||||
struct Rogan2PS : Rogan { | |||||
Rogan2PS() { | |||||
box.size = Vec(43, 43); | |||||
} | |||||
}; | |||||
struct Rogan2P : Rogan { | |||||
Rogan2P() { | |||||
box.size = Vec(34, 34); | |||||
} | |||||
}; | |||||
struct Rogan1PS : Rogan { | |||||
Rogan1PS() { | |||||
box.size = Vec(40, 40); | |||||
} | |||||
}; | |||||
struct Rogan1P : Rogan { | |||||
Rogan1P() { | |||||
box.size = Vec(31, 31); | |||||
} | |||||
}; | |||||
struct Rogan6PSWhite : Rogan6PS { | |||||
Rogan6PSWhite() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan6PSWhite.svg")); | |||||
} | |||||
}; | |||||
struct Rogan5PSGray : Rogan5PS { | |||||
Rogan5PSGray() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan5PSGray.svg")); | |||||
} | |||||
}; | |||||
struct Rogan3PSBlue : Rogan3PS { | |||||
Rogan3PSBlue() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan3PSBlue.svg")); | |||||
} | |||||
}; | |||||
struct Rogan3PSRed : Rogan3PS { | |||||
Rogan3PSRed() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan3PSRed.svg")); | |||||
} | |||||
}; | |||||
struct Rogan3PSGreen : Rogan3PS { | |||||
Rogan3PSGreen() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan3PSGreen.svg")); | |||||
} | |||||
}; | |||||
struct Rogan3PSWhite : Rogan3PS { | |||||
Rogan3PSWhite() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan3PSWhite.svg")); | |||||
} | |||||
}; | |||||
struct Rogan3PBlue : Rogan3P { | |||||
Rogan3PBlue() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan3PBlue.svg")); | |||||
} | |||||
}; | |||||
struct Rogan3PRed : Rogan3P { | |||||
Rogan3PRed() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan3PRed.svg")); | |||||
} | |||||
}; | |||||
struct Rogan3PGreen : Rogan3P { | |||||
Rogan3PGreen() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan3PGreen.svg")); | |||||
} | |||||
}; | |||||
struct Rogan3PWhite : Rogan3P { | |||||
Rogan3PWhite() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan3PWhite.svg")); | |||||
} | |||||
}; | |||||
struct Rogan2SGray : Rogan2S { | |||||
Rogan2SGray() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan2SGray.svg")); | |||||
} | |||||
}; | |||||
struct Rogan2PSBlue : Rogan2PS { | |||||
Rogan2PSBlue() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan2PSBlue.svg")); | |||||
} | |||||
}; | |||||
struct Rogan2PSRed : Rogan2PS { | |||||
Rogan2PSRed() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan2PSRed.svg")); | |||||
} | |||||
}; | |||||
struct Rogan2PSGreen : Rogan2PS { | |||||
Rogan2PSGreen() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan2PSGreen.svg")); | |||||
} | |||||
}; | |||||
struct Rogan2PSWhite : Rogan2PS { | |||||
Rogan2PSWhite() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan2PSWhite.svg")); | |||||
} | |||||
}; | |||||
struct Rogan2PBlue : Rogan2P { | |||||
Rogan2PBlue() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan2PBlue.svg")); | |||||
} | |||||
}; | |||||
struct Rogan2PRed : Rogan2P { | |||||
Rogan2PRed() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan2PRed.svg")); | |||||
} | |||||
}; | |||||
struct Rogan2PGreen : Rogan2P { | |||||
Rogan2PGreen() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan2PGreen.svg")); | |||||
} | |||||
}; | |||||
struct Rogan2PWhite : Rogan2P { | |||||
Rogan2PWhite() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan2PWhite.svg")); | |||||
} | |||||
}; | |||||
struct Rogan1PSBlue : Rogan1PS { | |||||
Rogan1PSBlue() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan1PSBlue.svg")); | |||||
} | |||||
}; | |||||
struct Rogan1PSRed : Rogan1PS { | |||||
Rogan1PSRed() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan1PSRed.svg")); | |||||
} | |||||
}; | |||||
struct Rogan1PSGreen : Rogan1PS { | |||||
Rogan1PSGreen() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan1PSGreen.svg")); | |||||
} | |||||
}; | |||||
struct Rogan1PSWhite : Rogan1PS { | |||||
Rogan1PSWhite() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan1PSWhite.svg")); | |||||
} | |||||
}; | |||||
struct Rogan1PBlue : Rogan1P { | |||||
Rogan1PBlue() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan1PBlue.svg")); | |||||
} | |||||
}; | |||||
struct Rogan1PRed : Rogan1P { | |||||
Rogan1PRed() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan1PRed.svg")); | |||||
} | |||||
}; | |||||
struct Rogan1PGreen : Rogan1P { | |||||
Rogan1PGreen() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan1PGreen.svg")); | |||||
} | |||||
}; | |||||
struct Rogan1PWhite : Rogan1P { | |||||
Rogan1PWhite() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Rogan1PWhite.svg")); | |||||
} | |||||
}; | |||||
struct SynthTechAlco : SVGKnob { | |||||
SynthTechAlco() { | SynthTechAlco() { | ||||
box.size = Vec(45, 45); | box.size = Vec(45, 45); | ||||
spriteOffset = Vec(-3, -2); | |||||
spriteSize = Vec(51, 51); | |||||
minIndex = 49; | |||||
maxIndex = -51; | |||||
spriteCount = 120; | |||||
spriteImage = Image::load("res/ComponentLibrary/SynthTechAlco.png"); | |||||
minAngle = -0.82*M_PI; | |||||
maxAngle = 0.82*M_PI; | |||||
setSVG(SVG::load("res/ComponentLibrary/SynthTechAlco.svg")); | |||||
} | } | ||||
}; | }; | ||||
@@ -62,6 +286,15 @@ struct Davies1900hRedKnob : Davies1900hKnob { | |||||
} | } | ||||
}; | }; | ||||
struct Trimpot : SVGKnob { | |||||
Trimpot() { | |||||
box.size = Vec(17, 17); | |||||
minAngle = -0.75*M_PI; | |||||
maxAngle = 0.75*M_PI; | |||||
setSVG(SVG::load("res/ComponentLibrary/Trimpot.svg")); | |||||
} | |||||
}; | |||||
struct BefacoBigKnob : SVGKnob { | struct BefacoBigKnob : SVGKnob { | ||||
BefacoBigKnob() { | BefacoBigKnob() { | ||||
box.size = Vec(75, 75); | box.size = Vec(75, 75); | ||||
@@ -96,30 +329,33 @@ struct BefacoSlidePot : SpriteKnob { | |||||
// Jacks | // Jacks | ||||
//////////////////// | //////////////////// | ||||
struct PJ301MPort : Port { | |||||
struct PJ301MPort : SpritePort { | |||||
PJ301MPort() { | PJ301MPort() { | ||||
box.size = Vec(24, 24); | box.size = Vec(24, 24); | ||||
spriteOffset = Vec(-2, -2); | spriteOffset = Vec(-2, -2); | ||||
spriteSize = Vec(30, 30); | spriteSize = Vec(30, 30); | ||||
spriteImage = Image::load("res/ComponentLibrary/PJ301M.png"); | spriteImage = Image::load("res/ComponentLibrary/PJ301M.png"); | ||||
// setSVG(SVG::load("res/ComponentLibrary/PJ301M.svg")); | |||||
} | } | ||||
}; | }; | ||||
struct PJ3410Port : Port { | |||||
struct PJ3410Port : SpritePort { | |||||
PJ3410Port() { | PJ3410Port() { | ||||
box.size = Vec(32, 31); | box.size = Vec(32, 31); | ||||
spriteOffset = Vec(-1, -1); | spriteOffset = Vec(-1, -1); | ||||
spriteSize = Vec(36, 36); | spriteSize = Vec(36, 36); | ||||
spriteImage = Image::load("res/ComponentLibrary/PJ3410.png"); | spriteImage = Image::load("res/ComponentLibrary/PJ3410.png"); | ||||
// setSVG(SVG::load("res/ComponentLibrary/PJ3410.svg")); | |||||
} | } | ||||
}; | }; | ||||
struct CL1362Port : Port { | |||||
struct CL1362Port : SpritePort { | |||||
CL1362Port() { | CL1362Port() { | ||||
box.size = Vec(33, 29); | box.size = Vec(33, 29); | ||||
spriteOffset = Vec(-2, -2); | spriteOffset = Vec(-2, -2); | ||||
spriteSize = Vec(39, 36); | spriteSize = Vec(39, 36); | ||||
spriteImage = Image::load("res/ComponentLibrary/CL1362.png"); | spriteImage = Image::load("res/ComponentLibrary/CL1362.png"); | ||||
// setSVG(SVG::load("res/ComponentLibrary/CL1362.svg")); | |||||
} | } | ||||
}; | }; | ||||
@@ -5,6 +5,53 @@ | |||||
namespace rack { | namespace rack { | ||||
//////////////////// | |||||
// integer functions | |||||
//////////////////// | |||||
inline int mini(int a, int b) { | |||||
return a < b ? a : b; | |||||
} | |||||
inline int maxi(int a, int b) { | |||||
return a > b ? a : b; | |||||
} | |||||
inline int absi(int a) { | |||||
return a >= 0 ? a : -a; | |||||
} | |||||
// Euclidean modulus, always returns 0 <= mod < base for positive base | |||||
// Assumes this architecture's division is non-Euclidean | |||||
inline int eucmod(int a, int base) { | |||||
int mod = a % base; | |||||
return mod < 0 ? mod + base : mod; | |||||
} | |||||
inline int log2i(int n) { | |||||
int i = 0; | |||||
while (n >>= 1) { | |||||
i++; | |||||
} | |||||
return i; | |||||
} | |||||
inline bool ispow2(int n) { | |||||
return n > 0 && (n & (n - 1)) == 0; | |||||
} | |||||
//////////////////// | |||||
// float functions | |||||
//////////////////// | |||||
inline float radtodeg(float x) { | |||||
return x * (180.0 / M_PI); | |||||
} | |||||
inline float degtorad(float x) { | |||||
return x * (M_PI / 180.0); | |||||
} | |||||
/** Limits a value between a minimum and maximum | /** Limits a value between a minimum and maximum | ||||
If min > max for some reason, returns min | If min > max for some reason, returns min | ||||
*/ | */ | ||||
@@ -31,14 +78,6 @@ inline float crossf(float a, float b, float frac) { | |||||
return (1.0 - frac) * a + frac * b; | return (1.0 - frac) * a + frac * b; | ||||
} | } | ||||
inline int mini(int a, int b) { | |||||
return a < b ? a : b; | |||||
} | |||||
inline int maxi(int a, int b) { | |||||
return a > b ? a : b; | |||||
} | |||||
inline float quadraticBipolar(float x) { | inline float quadraticBipolar(float x) { | ||||
float x2 = x*x; | float x2 = x*x; | ||||
return x >= 0.0 ? x2 : -x2; | return x >= 0.0 ? x2 : -x2; | ||||
@@ -92,25 +131,6 @@ inline float interpf(const float *p, float x) { | |||||
return crossf(p[xi], p[xi+1], xf); | return crossf(p[xi], p[xi+1], xf); | ||||
} | } | ||||
// Euclidean modulus, always returns 0 <= mod < base for positive base | |||||
// Assumes this architecture's division is non-Euclidean | |||||
inline int eucmod(int a, int base) { | |||||
int mod = a % base; | |||||
return mod < 0 ? mod + base : mod; | |||||
} | |||||
inline int log2i(int n) { | |||||
int i = 0; | |||||
while (n >>= 1) { | |||||
i++; | |||||
} | |||||
return i; | |||||
} | |||||
inline bool ispow2(int n) { | |||||
return n > 0 && (n & (n - 1)) == 0; | |||||
} | |||||
//////////////////// | //////////////////// | ||||
// 2D float vector | // 2D float vector | ||||
//////////////////// | //////////////////// | ||||
@@ -23,11 +23,13 @@ void ModuleWidget::setModule(Module *module) { | |||||
} | } | ||||
void ModuleWidget::addInput(Port *input) { | void ModuleWidget::addInput(Port *input) { | ||||
assert(input->type == Port::INPUT); | |||||
inputs.push_back(input); | inputs.push_back(input); | ||||
addChild(input); | addChild(input); | ||||
} | } | ||||
void ModuleWidget::addOutput(Port *output) { | void ModuleWidget::addOutput(Port *output) { | ||||
assert(output->type == Port::OUTPUT); | |||||
outputs.push_back(output); | outputs.push_back(output); | ||||
addChild(output); | addChild(output); | ||||
} | } | ||||
@@ -24,7 +24,6 @@ void Port::draw(NVGcontext *vg) { | |||||
if (type == INPUT ? gRackWidget->activeWire->inputPort : gRackWidget->activeWire->outputPort) | if (type == INPUT ? gRackWidget->activeWire->inputPort : gRackWidget->activeWire->outputPort) | ||||
nvgGlobalAlpha(vg, 0.5); | nvgGlobalAlpha(vg, 0.5); | ||||
} | } | ||||
SpriteWidget::draw(vg); | |||||
} | } | ||||
void Port::onMouseDown(int button) { | void Port::onMouseDown(int button) { | ||||
@@ -35,6 +35,26 @@ void SVGKnob::step() { | |||||
FramebufferWidget::step(); | FramebufferWidget::step(); | ||||
} | } | ||||
void SVGKnob::draw(NVGcontext *vg) { | |||||
// Draw circular shadow below knob | |||||
// TODO This is a hack. Make a CircularShadow its own class | |||||
{ | |||||
nvgBeginPath(vg); | |||||
float margin = 5.0; | |||||
nvgRect(vg, -margin, -margin, box.size.x + 2*margin, box.size.y + 2*margin); | |||||
nvgFillColor(vg, nvgRGBAf(0.0, 0.0, 0.0, 0.25)); | |||||
Vec c = box.size.div(2.0); | |||||
float radius = c.x - 1; | |||||
NVGcolor icol = nvgRGBAf(0.0, 0.0, 0.0, 0.25); | |||||
NVGcolor ocol = nvgRGBAf(0.0, 0.0, 0.0, 0.0); | |||||
NVGpaint paint = nvgRadialGradient(vg, c.x, c.y + 1, radius, radius + 3, icol, ocol); | |||||
nvgFillPaint(vg, paint); | |||||
nvgFill(vg); | |||||
} | |||||
FramebufferWidget::draw(vg); | |||||
} | |||||
void SVGKnob::onChange() { | void SVGKnob::onChange() { | ||||
dirty = true; | dirty = true; | ||||
ParamWidget::onChange(); | ParamWidget::onChange(); | ||||
@@ -0,0 +1,23 @@ | |||||
#include "app.hpp" | |||||
namespace rack { | |||||
SVGPort::SVGPort() { | |||||
sw = new SVGWidget(); | |||||
setScene(sw); | |||||
} | |||||
void SVGPort::setSVG(std::shared_ptr<SVG> svg) { | |||||
sw->svg = svg; | |||||
sw->wrap(); | |||||
} | |||||
void SVGPort::draw(NVGcontext *vg) { | |||||
Port::draw(vg); | |||||
FramebufferWidget::draw(vg); | |||||
} | |||||
} // namespace rack |
@@ -1,31 +1,42 @@ | |||||
#include "widgets.hpp" | #include "widgets.hpp" | ||||
// #define DEBUG_ONLY(x) x | |||||
#define DEBUG_ONLY(x) | |||||
namespace rack { | namespace rack { | ||||
static NVGcolor getNVGColor(int color) { | |||||
return nvgRGBA((color >> 0) & 0xff, (color >> 8) & 0xff, (color >> 16) & 0xff, (color >> 24) & 0xff); | |||||
// return nvgRGBA((color >> 24) & 0xff, (color >> 16) & 0xff, (color >> 8) & 0xff, (color) & 0xff); | |||||
static NVGcolor getNVGColor(uint32_t color) { | |||||
return nvgRGBA( | |||||
(color >> 0) & 0xff, | |||||
(color >> 8) & 0xff, | |||||
(color >> 16) & 0xff, | |||||
(color >> 24) & 0xff); | |||||
} | } | ||||
static void drawSVG(NVGcontext *vg, NSVGimage *svg) { | static void drawSVG(NVGcontext *vg, NSVGimage *svg) { | ||||
for (NSVGshape *shape = svg->shapes; shape; shape = shape->next) { | |||||
// printf(" new shape: id \"%s\", fillrule %d\n", shape->id, shape->fillRule); | |||||
DEBUG_ONLY(printf("new image: %g x %g px\n", svg->width, svg->height);) | |||||
int shapeIndex = 0; | |||||
for (NSVGshape *shape = svg->shapes; shape; shape = shape->next, shapeIndex++) { | |||||
DEBUG_ONLY(printf(" new shape: %d id \"%s\", fillrule %d\n", shapeIndex, shape->id, shape->fillRule);) | |||||
if (!(shape->flags & NSVG_FLAGS_VISIBLE)) | if (!(shape->flags & NSVG_FLAGS_VISIBLE)) | ||||
continue; | continue; | ||||
nvgSave(vg); | nvgSave(vg); | ||||
nvgGlobalAlpha(vg, shape->opacity); | |||||
if (shape->opacity < 1.0) | |||||
nvgGlobalAlpha(vg, shape->opacity); | |||||
nvgStrokeWidth(vg, shape->strokeWidth); | nvgStrokeWidth(vg, shape->strokeWidth); | ||||
// strokeDashOffset, strokeDashArray, strokeDashCount not supported | |||||
// strokeLineJoin, strokeLineCap not supported | |||||
// strokeDashOffset, strokeDashArray, strokeDashCount not yet supported | |||||
// strokeLineJoin, strokeLineCap not yet supported | |||||
// Build path | // Build path | ||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
for (NSVGpath *path = shape->paths; path; path = path->next) { | for (NSVGpath *path = shape->paths; path; path = path->next) { | ||||
// printf(" new path: %d points, %s\n", path->npts, path->closed ? "closed" : "notclosed"); | |||||
DEBUG_ONLY(printf(" new path: %d points, %s\n", path->npts, path->closed ? "closed" : "open");) | |||||
nvgMoveTo(vg, path->pts[0], path->pts[1]); | nvgMoveTo(vg, path->pts[0], path->pts[1]); | ||||
for (int i = 1; i < path->npts; i += 3) { | for (int i = 1; i < path->npts; i += 3) { | ||||
@@ -37,7 +48,6 @@ static void drawSVG(NVGcontext *vg, NSVGimage *svg) { | |||||
if (path->closed) | if (path->closed) | ||||
nvgClosePath(vg); | nvgClosePath(vg); | ||||
if (path->next) | if (path->next) | ||||
nvgPathWinding(vg, NVG_HOLE); | nvgPathWinding(vg, NVG_HOLE); | ||||
} | } | ||||
@@ -48,7 +58,7 @@ static void drawSVG(NVGcontext *vg, NSVGimage *svg) { | |||||
case NSVG_PAINT_COLOR: { | case NSVG_PAINT_COLOR: { | ||||
NVGcolor color = getNVGColor(shape->fill.color); | NVGcolor color = getNVGColor(shape->fill.color); | ||||
nvgFillColor(vg, color); | nvgFillColor(vg, color); | ||||
// printf(" fill color (%f %f %f %f)\n", color.r, color.g, color.b, color.a); | |||||
DEBUG_ONLY(printf(" fill color (%g, %g, %g, %g)\n", color.r, color.g, color.b, color.a);) | |||||
} break; | } break; | ||||
case NSVG_PAINT_LINEAR_GRADIENT: { | case NSVG_PAINT_LINEAR_GRADIENT: { | ||||
// NSVGgradient *g = shape->fill.gradient; | // NSVGgradient *g = shape->fill.gradient; | ||||
@@ -63,8 +73,8 @@ static void drawSVG(NVGcontext *vg, NSVGimage *svg) { | |||||
switch (shape->stroke.type) { | switch (shape->stroke.type) { | ||||
case NSVG_PAINT_COLOR: { | case NSVG_PAINT_COLOR: { | ||||
NVGcolor color = getNVGColor(shape->stroke.color); | NVGcolor color = getNVGColor(shape->stroke.color); | ||||
nvgFillColor(vg, color); | |||||
// printf(" stroke color (%f %f %f %f)\n", color.r, color.g, color.b, color.a); | |||||
nvgStrokeColor(vg, color); | |||||
DEBUG_ONLY(printf(" stroke color (%g, %g, %g, %g)\n", color.r, color.g, color.b, color.a);) | |||||
} break; | } break; | ||||
case NSVG_PAINT_LINEAR_GRADIENT: { | case NSVG_PAINT_LINEAR_GRADIENT: { | ||||
// NSVGgradient *g = shape->stroke.gradient; | // NSVGgradient *g = shape->stroke.gradient; | ||||
@@ -76,6 +86,8 @@ static void drawSVG(NVGcontext *vg, NSVGimage *svg) { | |||||
nvgRestore(vg); | nvgRestore(vg); | ||||
} | } | ||||
DEBUG_ONLY(printf("\n");) | |||||
} | } | ||||
@@ -87,7 +99,9 @@ void SVGWidget::wrap() { | |||||
} | } | ||||
void SVGWidget::draw(NVGcontext *vg) { | void SVGWidget::draw(NVGcontext *vg) { | ||||
drawSVG(vg, svg->handle); | |||||
if (svg && svg->handle) { | |||||
drawSVG(vg, svg->handle); | |||||
} | |||||
} | } | ||||