Add a few more things for light/dark mode switch, WIP
This commit is contained in:
parent
463e5cb770
commit
13020e793d
2 changed files with 355 additions and 64 deletions
|
|
@ -50,9 +50,6 @@ std::string user(std::string filename) {
|
||||||
|
|
||||||
// get system resource, trimming "res/" prefix if we are loaded as a plugin bundle
|
// get system resource, trimming "res/" prefix if we are loaded as a plugin bundle
|
||||||
std::string system(std::string filename) {
|
std::string system(std::string filename) {
|
||||||
// Always use dark screws
|
|
||||||
if (string::endsWith(filename, "/ScrewSilver.svg"))
|
|
||||||
filename = filename.substr(0, filename.size()-10) + "Black.svg";
|
|
||||||
return system::join(systemDir, bundlePath.empty() ? filename : trim(filename));
|
return system::join(systemDir, bundlePath.empty() ? filename : trim(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace rack {
|
namespace rack {
|
||||||
namespace settings {
|
namespace settings {
|
||||||
|
|
@ -60,7 +61,7 @@ static const struct {
|
||||||
const char* const filename;
|
const char* const filename;
|
||||||
const char* shapeIdsToIgnore[5];
|
const char* shapeIdsToIgnore[5];
|
||||||
const int shapeNumberToIgnore;
|
const int shapeNumberToIgnore;
|
||||||
} svgFilesToInvert[] = {
|
} svgFilesToInvertForDarkMode[] = {
|
||||||
// MIT
|
// MIT
|
||||||
{ "/21kHz/res/Panels/D_Inf.svg", {}, -1 },
|
{ "/21kHz/res/Panels/D_Inf.svg", {}, -1 },
|
||||||
{ "/21kHz/res/Panels/PalmLoop.svg", {}, -1 },
|
{ "/21kHz/res/Panels/PalmLoop.svg", {}, -1 },
|
||||||
|
|
@ -329,7 +330,150 @@ static const struct {
|
||||||
{ "/WhatTheRack/res/WhatTheRack.svg", {}, -1 },
|
{ "/WhatTheRack/res/WhatTheRack.svg", {}, -1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline bool invertPaint(NSVGshape* const shape, NSVGpaint& paint, const char* const svgFileToInvert = nullptr)
|
static const struct {
|
||||||
|
const char* const filename;
|
||||||
|
const char* shapeIdsToIgnore[5];
|
||||||
|
const int shapeNumberToIgnore;
|
||||||
|
} svgFilesToInvertForLightMode[] = {
|
||||||
|
// GPLv3+
|
||||||
|
/* FIXME does not work very well
|
||||||
|
{ "/Autinn/res/AmpModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/BassModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/CVConverterModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/ComponentLibrary", {}, -1 },
|
||||||
|
{ "/Autinn/res/DeadbandModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/DigiModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/DiseeModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/FilModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/FlopperModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/ImpModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/JetteModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/MelodyModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/MeraModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/Mixer6Module.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/NapModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/NonModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/OxcartModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/RebelModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/RetriModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/SawModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/SjipModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/SquareModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/VibratoModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/VxyModule.svg", {}, -1 },
|
||||||
|
{ "/Autinn/res/ZodModule.svg", {}, -1 },
|
||||||
|
*/
|
||||||
|
// ??? used for testing, might get turned off
|
||||||
|
{ "/Befaco/res/panels/ABC.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/ADSR.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/ChoppingKinky.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/DualAtenuverter.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/EvenVCO.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/HexmixVCA.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/Kickall.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/Mex.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/Mixer.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/Morphader.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/Muxlicer.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/NoisePlethora.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/Percall.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/Rampage.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/STMix.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/SamplingModulator.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/SlewLimiter.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/SpringReverb.svg", {}, -1 },
|
||||||
|
{ "/Befaco/res/panels/StereoStrip.svg", {}, -1 },
|
||||||
|
// GPLv3+
|
||||||
|
{ "/Cardinal/res/AudioFile.svg", {}, -1 },
|
||||||
|
{ "/Cardinal/res/AudioToCVPitch.svg", {}, -1 },
|
||||||
|
{ "/Cardinal/res/Carla.svg", {}, -1 },
|
||||||
|
{ "/Cardinal/res/ExpanderMIDI.svg", {}, -1 },
|
||||||
|
{ "/Cardinal/res/glBars.svg", {}, -1 },
|
||||||
|
{ "/Cardinal/res/HostAudio.svg", {}, -1 },
|
||||||
|
{ "/Cardinal/res/HostCV.svg", {}, -1 },
|
||||||
|
{ "/Cardinal/res/HostMIDI.svg", {}, -1 },
|
||||||
|
{ "/Cardinal/res/HostMIDICC.svg", {}, -1 },
|
||||||
|
{ "/Cardinal/res/HostMIDIGate.svg", {}, -1 },
|
||||||
|
{ "/Cardinal/res/HostMIDIMap.svg", {}, -1 },
|
||||||
|
{ "/Cardinal/res/HostParameters.svg", {}, -1 },
|
||||||
|
{ "/Cardinal/res/HostParamsMap.svg", {}, -1 },
|
||||||
|
{ "/Cardinal/res/HostTime.svg", {}, -1 },
|
||||||
|
{ "/Cardinal/res/Ildaeil.svg", {}, -1 },
|
||||||
|
// GPLv3+
|
||||||
|
{ "/forsitan-modulare/res/alea.svg", {}, -1 },
|
||||||
|
{ "/forsitan-modulare/res/cumuli.svg", {}, -1 },
|
||||||
|
{ "/forsitan-modulare/res/deinde.svg", {}, -1 },
|
||||||
|
{ "/forsitan-modulare/res/interea.svg", {}, -1 },
|
||||||
|
{ "/forsitan-modulare/res/palette.svg", {}, -1 },
|
||||||
|
{ "/forsitan-modulare/res/pavo.svg", {}, -1 },
|
||||||
|
// GPLv3+
|
||||||
|
/* FIXME ends up transparent??
|
||||||
|
{ "/Fundamental/res/8vert.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/ADSR.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/Delay.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/LFO.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/Merge.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/MidSide.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/Mixer.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/Mutes.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/Noise.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/Octave.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/Pulses.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/Quantizer.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/Random.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/SEQ3.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/Scope.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/SequentialSwitch1.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/SequentialSwitch2.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/Split.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/Sum.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/VCA-1.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/VCA.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/VCF.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/VCMixer.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/VCO.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/WTLFO.svg", {}, -1 },
|
||||||
|
{ "/Fundamental/res/WTVCO.svg", {}, -1 },
|
||||||
|
*/
|
||||||
|
// MIT
|
||||||
|
{ "/HamptonHarmonics/res/Arp.svg", {}, -1 },
|
||||||
|
{ "/HamptonHarmonics/res/Progress.svg", {}, -1 },
|
||||||
|
// GPLv3+
|
||||||
|
{ "/LomasModules/res/AdvancedSampler.svg", {}, -1 },
|
||||||
|
{ "/LomasModules/res/GateSequencer.svg", {}, -1 },
|
||||||
|
// GPLv3+
|
||||||
|
{ "/sonusmodular/res/addiction.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/bitter.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/bymidside.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/campione.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/chainsaw.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/ctrl.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/deathcrush.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/fraction.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/harmony.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/ladrone.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/luppolo.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/luppolo3.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/micromacro.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/mrcheb.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/multimulti.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/neurosc.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/oktagon.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/osculum.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/paramath.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/piconoise.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/pith.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/pusher.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/ringo.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/scramblase.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/tropicana.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/twoff.svg", {}, -1 },
|
||||||
|
{ "/sonusmodular/res/yabp.svg", {}, -1 },
|
||||||
|
// TODO bacon, chowdsp, ???
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline
|
||||||
|
bool invertPaintForDarkMode(NSVGshape* const shape, NSVGpaint& paint, const char* const svgFileToInvert = nullptr)
|
||||||
{
|
{
|
||||||
if (paint.type == NSVG_PAINT_LINEAR_GRADIENT && svgFileToInvert != nullptr)
|
if (paint.type == NSVG_PAINT_LINEAR_GRADIENT && svgFileToInvert != nullptr)
|
||||||
{
|
{
|
||||||
|
|
@ -601,6 +745,16 @@ static inline bool invertPaint(NSVGshape* const shape, NSVGpaint& paint, const c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
bool invertPaintForLightMode(NSVGshape* const shape, NSVGpaint& paint)
|
||||||
|
{
|
||||||
|
paint.color = (paint.color & 0xff000000)
|
||||||
|
| (0xff0000 - (paint.color & 0xff0000))
|
||||||
|
| (0xff00 - (paint.color & 0xff00))
|
||||||
|
| (0xff - (paint.color & 0xff));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
NSVGimage* nsvgParseFromFileCardinal(const char* filename, const char* units, float dpi);
|
NSVGimage* nsvgParseFromFileCardinal(const char* filename, const char* units, float dpi);
|
||||||
void nsvgDeleteCardinal(NSVGimage*);
|
void nsvgDeleteCardinal(NSVGimage*);
|
||||||
|
|
@ -608,17 +762,86 @@ void nsvgDeleteCardinal(NSVGimage*);
|
||||||
|
|
||||||
struct ExtendedNSVGimage {
|
struct ExtendedNSVGimage {
|
||||||
NSVGimage* handle;
|
NSVGimage* handle;
|
||||||
|
NSVGimage* handleOrig;
|
||||||
|
NSVGimage* handleMOD;
|
||||||
NSVGshape* shapesOrig;
|
NSVGshape* shapesOrig;
|
||||||
NSVGshape* shapesDark;
|
NSVGshape* shapesMOD;
|
||||||
};
|
};
|
||||||
static std::list<ExtendedNSVGimage> loadedSVGs;
|
|
||||||
|
|
||||||
static void nsvg__duplicatePaint(NSVGpaint& dst, NSVGpaint& src)
|
static std::list<ExtendedNSVGimage> loadedDarkSVGs;
|
||||||
|
static std::list<ExtendedNSVGimage> loadedLightSVGs;
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void nsvg__duplicatePaint(NSVGpaint& dst, NSVGpaint& src)
|
||||||
{
|
{
|
||||||
if (dst.type == NSVG_PAINT_LINEAR_GRADIENT || dst.type == NSVG_PAINT_RADIAL_GRADIENT)
|
if (dst.type == NSVG_PAINT_LINEAR_GRADIENT || dst.type == NSVG_PAINT_RADIAL_GRADIENT)
|
||||||
{
|
{
|
||||||
dst.gradient = static_cast<NSVGgradient*>(malloc(sizeof(NSVGgradient)));
|
const size_t size = sizeof(NSVGgradient) + sizeof(NSVGgradientStop)*(src.gradient->nstops-1);
|
||||||
std::memcpy(dst.gradient, src.gradient, sizeof(NSVGgradient));
|
dst.gradient = static_cast<NSVGgradient*>(malloc(size));
|
||||||
|
std::memcpy(dst.gradient, src.gradient, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
NSVGshape* nsvg__duplicateShapes(NSVGshape* const orig)
|
||||||
|
{
|
||||||
|
NSVGshape* const dup = static_cast<NSVGshape*>(malloc(sizeof(NSVGshape)));
|
||||||
|
std::memcpy(dup, orig, sizeof(NSVGshape));
|
||||||
|
nsvg__duplicatePaint(dup->fill, orig->fill);
|
||||||
|
nsvg__duplicatePaint(dup->stroke, orig->stroke);
|
||||||
|
|
||||||
|
for (NSVGshape* shape2 = dup;;)
|
||||||
|
{
|
||||||
|
if (shape2->next == nullptr)
|
||||||
|
break;
|
||||||
|
|
||||||
|
NSVGshape* const shapedup = static_cast<NSVGshape*>(malloc(sizeof(NSVGshape)));
|
||||||
|
std::memcpy(shapedup, shape2->next, sizeof(NSVGshape));
|
||||||
|
nsvg__duplicatePaint(shapedup->fill, shape2->next->fill);
|
||||||
|
nsvg__duplicatePaint(shapedup->stroke, shape2->next->stroke);
|
||||||
|
shape2->next = shapedup;
|
||||||
|
shape2 = shapedup;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dup;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void deleteExtendedNSVGimage(ExtendedNSVGimage& ext)
|
||||||
|
{
|
||||||
|
if (ext.shapesMOD != nullptr)
|
||||||
|
{
|
||||||
|
// delete duplicated resources
|
||||||
|
for (NSVGshape *next, *shape = ext.shapesMOD;;)
|
||||||
|
{
|
||||||
|
next = shape->next;
|
||||||
|
|
||||||
|
nsvg__deletePaint(&shape->fill);
|
||||||
|
nsvg__deletePaint(&shape->stroke);
|
||||||
|
std::free(shape);
|
||||||
|
|
||||||
|
if (next == nullptr)
|
||||||
|
break;
|
||||||
|
|
||||||
|
shape = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// revert shapes back to original
|
||||||
|
ext.handle->shapes = ext.shapesOrig;
|
||||||
|
ext.shapesMOD = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ext.handleMOD != nullptr)
|
||||||
|
{
|
||||||
|
nsvgDelete(ext.handleMOD);
|
||||||
|
ext.handleMOD = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ext.handleOrig != nullptr)
|
||||||
|
{
|
||||||
|
std::memcpy(ext.handle, ext.handleOrig, sizeof(NSVGimage));
|
||||||
|
std::free(ext.handleOrig);
|
||||||
|
ext.handleOrig = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -626,14 +849,36 @@ NSVGimage* nsvgParseFromFileCardinal(const char* const filename, const char* con
|
||||||
{
|
{
|
||||||
if (NSVGimage* const handle = nsvgParseFromFile(filename, units, dpi))
|
if (NSVGimage* const handle = nsvgParseFromFile(filename, units, dpi))
|
||||||
{
|
{
|
||||||
bool hasDarkMode = false;
|
const size_t filenamelen = std::strlen(filename);
|
||||||
NSVGshape* shapesOrig;
|
|
||||||
NSVGshape* shapesDark;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(svgFilesToInvert)/sizeof(svgFilesToInvert[0]); ++i)
|
bool hasDarkMode = false;
|
||||||
|
bool hasLightMode = false;
|
||||||
|
NSVGimage* handleMOD = nullptr;
|
||||||
|
NSVGshape* shapesOrig;
|
||||||
|
NSVGshape* shapesMOD;
|
||||||
|
|
||||||
|
// Special case for light/dark screws
|
||||||
|
if (std::strncmp(filename + (filenamelen-16), "/ScrewSilver.svg", 16) == 0)
|
||||||
{
|
{
|
||||||
const char* const svgFileToInvert = svgFilesToInvert[i].filename;
|
const std::string blackfilename = std::string(filename).substr(0, filenamelen-10) + "Black.svg";
|
||||||
const size_t filenamelen = std::strlen(filename);
|
hasDarkMode = true;
|
||||||
|
shapesOrig = shapesMOD = nullptr;
|
||||||
|
handleMOD = nsvgParseFromFile(blackfilename.c_str(), units, dpi);
|
||||||
|
goto postparse;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::strncmp(filename + (filenamelen-15), "/ScrewBlack.svg", 15) == 0)
|
||||||
|
{
|
||||||
|
const std::string silverfilename = std::string(filename).substr(0, filenamelen-9) + "Silver.svg";
|
||||||
|
hasLightMode = true;
|
||||||
|
shapesOrig = shapesMOD = nullptr;
|
||||||
|
handleMOD = nsvgParseFromFile(silverfilename.c_str(), units, dpi);
|
||||||
|
goto postparse;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(svgFilesToInvertForDarkMode)/sizeof(svgFilesToInvertForDarkMode[0]); ++i)
|
||||||
|
{
|
||||||
|
const char* const svgFileToInvert = svgFilesToInvertForDarkMode[i].filename;
|
||||||
const size_t filterlen = std::strlen(svgFileToInvert);
|
const size_t filterlen = std::strlen(svgFileToInvert);
|
||||||
|
|
||||||
if (filenamelen < filterlen)
|
if (filenamelen < filterlen)
|
||||||
|
|
@ -641,34 +886,17 @@ NSVGimage* nsvgParseFromFileCardinal(const char* const filename, const char* con
|
||||||
if (std::strncmp(filename + (filenamelen-filterlen), svgFileToInvert, filterlen) != 0)
|
if (std::strncmp(filename + (filenamelen-filterlen), svgFileToInvert, filterlen) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const char* const* const shapeIdsToIgnore = svgFilesToInvert[i].shapeIdsToIgnore;
|
const char* const* const shapeIdsToIgnore = svgFilesToInvertForDarkMode[i].shapeIdsToIgnore;
|
||||||
const int shapeNumberToIgnore = svgFilesToInvert[i].shapeNumberToIgnore;
|
const int shapeNumberToIgnore = svgFilesToInvertForDarkMode[i].shapeNumberToIgnore;
|
||||||
int shapeCounter = 0;
|
int shapeCounter = 0;
|
||||||
|
|
||||||
hasDarkMode = true;
|
hasDarkMode = true;
|
||||||
|
handleMOD = nullptr;
|
||||||
shapesOrig = handle->shapes;
|
shapesOrig = handle->shapes;
|
||||||
|
shapesMOD = nsvg__duplicateShapes(shapesOrig);
|
||||||
// duplicate all shapes, so we can swap between original and dark mode at will
|
|
||||||
shapesDark = static_cast<NSVGshape*>(malloc(sizeof(NSVGshape)));
|
|
||||||
std::memcpy(shapesDark, shapesOrig, sizeof(NSVGshape));
|
|
||||||
nsvg__duplicatePaint(shapesDark->fill, shapesOrig->fill);
|
|
||||||
nsvg__duplicatePaint(shapesDark->stroke, shapesOrig->stroke);
|
|
||||||
|
|
||||||
for (NSVGshape* shape2 = shapesDark;;)
|
|
||||||
{
|
|
||||||
if (shape2->next == nullptr)
|
|
||||||
break;
|
|
||||||
|
|
||||||
NSVGshape* const shapedup = static_cast<NSVGshape*>(malloc(sizeof(NSVGshape)));
|
|
||||||
std::memcpy(shapedup, shape2->next, sizeof(NSVGshape));
|
|
||||||
nsvg__duplicatePaint(shapedup->fill, shape2->next->fill);
|
|
||||||
nsvg__duplicatePaint(shapedup->stroke, shape2->next->stroke);
|
|
||||||
shape2->next = shapedup;
|
|
||||||
shape2 = shapedup;
|
|
||||||
}
|
|
||||||
|
|
||||||
// shape paint inversion
|
// shape paint inversion
|
||||||
for (NSVGshape* shape = shapesDark; shape != nullptr; shape = shape->next, ++shapeCounter)
|
for (NSVGshape* shape = shapesMOD; shape != nullptr; shape = shape->next, ++shapeCounter)
|
||||||
{
|
{
|
||||||
if (shapeNumberToIgnore == shapeCounter)
|
if (shapeNumberToIgnore == shapeCounter)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -685,11 +913,37 @@ NSVGimage* nsvgParseFromFileCardinal(const char* const filename, const char* con
|
||||||
if (ignore)
|
if (ignore)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (invertPaint(shape, shape->fill, svgFileToInvert))
|
if (invertPaintForDarkMode(shape, shape->fill, svgFileToInvert))
|
||||||
invertPaint(shape, shape->stroke, svgFileToInvert);
|
invertPaintForDarkMode(shape, shape->stroke, svgFileToInvert);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
goto postparse;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(svgFilesToInvertForLightMode)/sizeof(svgFilesToInvertForLightMode[0]); ++i)
|
||||||
|
{
|
||||||
|
const char* const svgFileToInvert = svgFilesToInvertForLightMode[i].filename;
|
||||||
|
const size_t filenamelen = std::strlen(filename);
|
||||||
|
const size_t filterlen = std::strlen(svgFileToInvert);
|
||||||
|
|
||||||
|
if (filenamelen < filterlen)
|
||||||
|
continue;
|
||||||
|
if (std::strncmp(filename + (filenamelen-filterlen), svgFileToInvert, filterlen) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
hasLightMode = true;
|
||||||
|
handleMOD = nullptr;
|
||||||
|
shapesOrig = handle->shapes;
|
||||||
|
shapesMOD = nsvg__duplicateShapes(shapesOrig);
|
||||||
|
|
||||||
|
// shape paint inversion
|
||||||
|
for (NSVGshape* shape = shapesMOD; shape != nullptr; shape = shape->next)
|
||||||
|
{
|
||||||
|
if (invertPaintForLightMode(shape, shape->fill))
|
||||||
|
invertPaintForLightMode(shape, shape->stroke);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto postparse;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case for AmalgamatedHarmonics background color
|
// Special case for AmalgamatedHarmonics background color
|
||||||
|
|
@ -697,13 +951,45 @@ NSVGimage* nsvgParseFromFileCardinal(const char* const filename, const char* con
|
||||||
if (std::strstr(filename, "/AmalgamatedHarmonics/") != nullptr)
|
if (std::strstr(filename, "/AmalgamatedHarmonics/") != nullptr)
|
||||||
handle->shapes->fill.color = 0xff191919;
|
handle->shapes->fill.color = 0xff191919;
|
||||||
|
|
||||||
|
postparse:
|
||||||
|
NSVGimage* handleOrig;
|
||||||
|
|
||||||
|
if (handleMOD != nullptr)
|
||||||
|
{
|
||||||
|
handleOrig = static_cast<NSVGimage*>(malloc(sizeof(NSVGimage)));
|
||||||
|
std::memcpy(handleOrig, handle, sizeof(NSVGimage));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handleOrig = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (hasDarkMode)
|
if (hasDarkMode)
|
||||||
{
|
{
|
||||||
const ExtendedNSVGimage ext = { handle, shapesOrig, shapesDark };
|
const ExtendedNSVGimage ext = { handle, handleOrig, handleMOD, shapesOrig, shapesMOD };
|
||||||
loadedSVGs.push_back(ext);
|
loadedDarkSVGs.push_back(ext);
|
||||||
|
|
||||||
if (rack::settings::darkMode)
|
if (rack::settings::darkMode)
|
||||||
handle->shapes = shapesDark;
|
{
|
||||||
|
if (shapesMOD != nullptr)
|
||||||
|
handle->shapes = shapesMOD;
|
||||||
|
else if (handleMOD != nullptr)
|
||||||
|
std::memcpy(handle, handleMOD, sizeof(NSVGimage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasLightMode)
|
||||||
|
{
|
||||||
|
const ExtendedNSVGimage ext = { handle, handleOrig, handleMOD, shapesOrig, shapesMOD };
|
||||||
|
loadedLightSVGs.push_back(ext);
|
||||||
|
|
||||||
|
if (!rack::settings::darkMode)
|
||||||
|
{
|
||||||
|
if (shapesMOD != nullptr)
|
||||||
|
handle->shapes = shapesMOD;
|
||||||
|
else if (handleMOD != nullptr)
|
||||||
|
std::memcpy(handle, handleMOD, sizeof(NSVGimage));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
|
|
@ -714,32 +1000,27 @@ NSVGimage* nsvgParseFromFileCardinal(const char* const filename, const char* con
|
||||||
|
|
||||||
void nsvgDeleteCardinal(NSVGimage* const handle)
|
void nsvgDeleteCardinal(NSVGimage* const handle)
|
||||||
{
|
{
|
||||||
for (auto it = loadedSVGs.cbegin(), end = loadedSVGs.cend(); it != end; ++it)
|
for (auto it = loadedDarkSVGs.begin(), end = loadedDarkSVGs.end(); it != end; ++it)
|
||||||
{
|
{
|
||||||
const ExtendedNSVGimage& ext(*it);
|
ExtendedNSVGimage& ext(*it);
|
||||||
|
|
||||||
if (ext.handle != handle)
|
if (ext.handle != handle)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// delete duplicated resources
|
deleteExtendedNSVGimage(ext);
|
||||||
for (NSVGshape *next, *shape = ext.shapesDark;;)
|
loadedDarkSVGs.erase(it);
|
||||||
{
|
break;
|
||||||
next = shape->next;
|
}
|
||||||
|
|
||||||
nsvg__deletePaint(&shape->fill);
|
for (auto it = loadedLightSVGs.begin(), end = loadedLightSVGs.end(); it != end; ++it)
|
||||||
nsvg__deletePaint(&shape->stroke);
|
{
|
||||||
std::free(shape);
|
ExtendedNSVGimage& ext(*it);
|
||||||
|
|
||||||
if (next == nullptr)
|
if (ext.handle != handle)
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
shape = next;
|
deleteExtendedNSVGimage(ext);
|
||||||
}
|
loadedLightSVGs.erase(it);
|
||||||
|
|
||||||
// revert shapes back to original
|
|
||||||
handle->shapes = ext.shapesOrig;
|
|
||||||
|
|
||||||
loadedSVGs.erase(it);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -753,6 +1034,19 @@ void switchDarkMode(bool darkMode)
|
||||||
|
|
||||||
rack::settings::darkMode = darkMode;
|
rack::settings::darkMode = darkMode;
|
||||||
|
|
||||||
for (ExtendedNSVGimage& ext : loadedSVGs)
|
for (ExtendedNSVGimage& ext : loadedDarkSVGs)
|
||||||
ext.handle->shapes = darkMode ? ext.shapesDark : ext.shapesOrig;
|
{
|
||||||
|
if (ext.shapesMOD != nullptr)
|
||||||
|
ext.handle->shapes = darkMode ? ext.shapesMOD : ext.shapesOrig;
|
||||||
|
else if (ext.handleMOD != nullptr)
|
||||||
|
std::memcpy(ext.handle, darkMode ? ext.handleMOD : ext.handleOrig, sizeof(NSVGimage));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ExtendedNSVGimage& ext : loadedLightSVGs)
|
||||||
|
{
|
||||||
|
if (ext.shapesMOD != nullptr)
|
||||||
|
ext.handle->shapes = darkMode ? ext.shapesOrig : ext.shapesMOD;
|
||||||
|
else if (ext.handleMOD != nullptr)
|
||||||
|
std::memcpy(ext.handle, darkMode ? ext.handleOrig : ext.handleMOD, sizeof(NSVGimage));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue