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.

702 lines
22KB

  1. /*
  2. * DISTRHO Cardinal Plugin
  3. * Copyright (C) 2021 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 3 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the LICENSE file.
  16. */
  17. #define STDIO_OVERRIDE Rackdep
  18. #include <cstdio>
  19. #include <cstring>
  20. #include "nanovg.h"
  21. // fix bogaudio build, another missing symbol
  22. #ifndef NDEBUG
  23. namespace bogaudio {
  24. struct FollowerBase {
  25. static float efGainMaxDecibelsDebug;
  26. };
  27. float FollowerBase::efGainMaxDecibelsDebug = 12.0f;
  28. }
  29. #endif
  30. // Special nvgRGB for blank panels
  31. extern "C" {
  32. NVGcolor nvgRGBblank(unsigned char, unsigned char, unsigned char)
  33. {
  34. return nvgRGB(0x20, 0x20, 0x20);
  35. }
  36. }
  37. // Compile those nice implementation-in-header little libraries
  38. #define NANOSVG_IMPLEMENTATION
  39. #define NANOSVG_ALL_COLOR_KEYWORDS
  40. #undef nsvgParseFromFile
  41. #include <nanosvg.h>
  42. // Custom Cardinal filtering
  43. static const struct {
  44. const char* const filename;
  45. const char* shapes[8];
  46. } pathsToFilterOut[] = {
  47. // Core will be removed soon, so this part doesnt matter
  48. {
  49. "/Core/Audio2.svg",
  50. {
  51. "af0e935f-6d5d-444c-895d-4ef87ed070e2",
  52. "a86c2c4c-97ac-4697-a68a-6850586e2c02",
  53. "bcf7f738-a2ee-4f24-a05e-79080795ecac",
  54. "a97fec2c-c9d1-4f34-979d-c2ed13bb4b13"
  55. }
  56. },
  57. {
  58. "/Core/Audio8.svg",
  59. {
  60. "a0f6228c-5a83-4e0f-aae7-549956d6c592",
  61. "ab26ff62-9ae1-4a5d-a800-ae8a9605590e",
  62. "a5905f87-4917-4633-8c97-2c26610c8dd4",
  63. "b9c0a0ed-e7c4-4727-8d9a-2f8d91fb0687"
  64. }
  65. },
  66. {
  67. "/Core/Audio16.svg",
  68. {
  69. "b1f50144-7f61-4995-a84e-7c733562b87a",
  70. "bc1bc3f6-2589-483f-a045-f4d5b20fb1bb",
  71. "aa22e3a2-cd01-4140-bbb6-d7011a95a8a2",
  72. "ea03e764-3d44-4889-a575-96635de1afbe"
  73. }
  74. },
  75. {
  76. "/Core/CV_MIDI.svg",
  77. {
  78. "bccecf5a-8b5e-488a-8cf7-650646675413",
  79. "e23862c8-ee12-4114-8f76-5ec17e2f6556",
  80. "ecee65f0-2e8f-465d-a3f5-7c42fd129ac0",
  81. "e5f4878f-ccca-4a7b-9150-00a37e0f7a74"
  82. }
  83. },
  84. {
  85. "/Core/CV_MIDICC.svg",
  86. {
  87. "a00f3f95-93a1-4715-a488-46304d54fe4f",
  88. "a08adb03-865c-43cd-8cb5-971a122dc23b",
  89. "acc2b450-a2fc-418e-a77e-156a2488ec7a",
  90. "e06020ad-ee93-4ba3-893c-67c2998ab6cb"
  91. }
  92. },
  93. {
  94. "/Core/Gate_MIDI.svg",
  95. {
  96. "f2d57f2b-4ac3-4488-87ca-eb36011b7ce2",
  97. "bc89b1d7-8b88-4c7a-af75-dfc0ea49931b",
  98. "a11340bf-b366-408c-b4b3-38117f4076dc",
  99. "aa3e2e62-1159-407f-836f-d2ff19be0436"
  100. }
  101. },
  102. {
  103. "/Core/MIDI_CV.svg",
  104. {
  105. "fca6f6f9-431a-4f4f-9eb9-85798d95f9ff",
  106. "a520f07d-0c80-4572-aabf-aa329a17c02b",
  107. "b824fab4-8a48-404a-b94f-d27f4404ee73",
  108. "beded7b3-65dd-4587-af53-097e8e4afb82"
  109. }
  110. },
  111. {
  112. "/Core/MIDI_Gate.svg",
  113. {
  114. "fb3f5bb1-31c5-4a85-95ef-a09d670df926",
  115. "a32f20f9-d55f-46ad-b898-7dc335b20780",
  116. "bf8ce0d6-d9b5-4e48-bf72-dd6ddd7e4866",
  117. "ba9e0012-4a65-4add-bd98-ba3570579a83"
  118. }
  119. },
  120. {
  121. "/Core/MIDICC_CV.svg",
  122. {
  123. "bc30b86e-2d28-4d36-a374-69ba5693476f",
  124. "ffe265e3-2ac1-4b6b-8361-c3aaecd0b08f",
  125. "e822d5df-0aee-4ddb-9c3d-a6878d3d06e2",
  126. "b4f0f926-0fae-49be-b7d9-5bd02e5798af"
  127. }
  128. },
  129. {
  130. "/Core/MIDIMap.svg",
  131. {
  132. "b3405776-74b5-4087-a983-4efe1be00b3e",
  133. "bd42b57c-2a9e-4cc7-a268-70bc560923d7",
  134. "e2520435-d4b5-45d8-8264-c033ec31cfb4",
  135. "f774ab20-064d-4751-baa5-11632dd31e08"
  136. }
  137. },
  138. {
  139. "/Core/Notes.svg",
  140. {
  141. "b4cb817a-ff42-4dfc-8866-e3d83608b518",
  142. "aa48af94-af91-4b1f-b663-ef6af4b5cf3b",
  143. "a3b43b3b-5987-49ba-834a-210c6d95bb7d",
  144. "a58877fa-d57b-4d74-bbda-a883bf30a365"
  145. }
  146. },
  147. /*
  148. // CC-BY-NC-ND-4.0, needs permission
  149. {
  150. "/Fundamental/8vert.svg",
  151. {"path17","path21","circle15","path19"}
  152. },
  153. {
  154. "/Fundamental/ADSR.svg",
  155. {"path12","path16","circle18","path14"}
  156. },
  157. {
  158. "/Fundamental/Delay.svg",
  159. {"path14","path18","circle20","path16"}
  160. },
  161. {
  162. "/Fundamental/LFO.svg",
  163. {"path14","path18","circle20","path16"}
  164. },
  165. {
  166. "/Fundamental/Merge.svg",
  167. {"path16","path20","circle14","path18",
  168. "path26","path30","circle24","path28"}
  169. },
  170. {
  171. "/Fundamental/MidSide.svg",
  172. {"path23","path27","circle21","path25",
  173. "path33","path37","circle31","path35"}
  174. },
  175. {
  176. "/Fundamental/Mixer.svg",
  177. {"path14","path18","circle12","path16"}
  178. },
  179. {
  180. "/Fundamental/Mutes.svg",
  181. {"path17","path21","circle15","path19"}
  182. },
  183. {
  184. "/Fundamental/Noise.svg",
  185. {"path14","path18","circle12","path16"}
  186. },
  187. {
  188. "/Fundamental/Octave.svg",
  189. {"path14","path18","circle12","path16"}
  190. },
  191. {
  192. "/Fundamental/Pulses.svg",
  193. {"path14","path18","circle12","path16"}
  194. },
  195. {
  196. "/Fundamental/Quantizer.svg",
  197. {"path14","path18","circle12","path16"}
  198. },
  199. {
  200. "/Fundamental/Random.svg",
  201. {"path58","path62","circle64","path60"}
  202. },
  203. {
  204. "/Fundamental/Scope.svg",
  205. {"path14","path18","circle20","path16"}
  206. },
  207. {
  208. "/Fundamental/SEQ3.svg",
  209. {"path16","path20","circle22","path18"}
  210. },
  211. {
  212. "/Fundamental/SequentialSwitch1.svg",
  213. {"path17","path21","circle15","path19"}
  214. },
  215. {
  216. "/Fundamental/SequentialSwitch2.svg",
  217. {"path17","path21","circle15","path19"}
  218. },
  219. {
  220. "/Fundamental/Split.svg",
  221. {"path18","path22","circle16","path20",
  222. "path28","path32","circle26","path30"}
  223. },
  224. {
  225. "/Fundamental/Sum.svg",
  226. {"path24","path28","circle22","path26"}
  227. },
  228. {
  229. "/Fundamental/Unity.svg",
  230. {"path21219","path21223","path21217","path21221"}
  231. },
  232. {
  233. "/Fundamental/VCA-1.svg",
  234. {"path16","path20","circle14","path18"}
  235. },
  236. {
  237. "/Fundamental/VCF.svg",
  238. {"path12","path16","circle18","path14"}
  239. },
  240. {
  241. "/Fundamental/VCMixer.svg",
  242. {"path12","path16","circle18","path14"}
  243. },
  244. {
  245. "/Fundamental/VCO.svg",
  246. {"path14","path18","circle20","path16"}
  247. },
  248. {
  249. "/Fundamental/Viz.svg",
  250. {"path14","path18","circle12","path16"}
  251. },
  252. {
  253. "/Fundamental/WTLFO.svg",
  254. {"path12","path16","circle18","path14"}
  255. },
  256. {
  257. "/Fundamental/WTVCO.svg",
  258. {"path12","path16","circle18","path14"}
  259. },
  260. */
  261. };
  262. static const struct {
  263. const char* const filename;
  264. const char* shapeIdsToIgnore[5];
  265. const int shapeNumberToIgnore;
  266. } svgFilesToInvert[] = {
  267. // MIT
  268. { "/21kHz/Panels/D_Inf.svg", {}, -1 },
  269. { "/21kHz/Panels/PalmLoop.svg", {}, -1 },
  270. { "/21kHz/Panels/TachyonEntangler.svg", {}, -1 },
  271. // CC-BY-NC-SA-4.0
  272. { "/AnimatedCircuits/FoldingLight.svg", {}, -1 },
  273. { "/AnimatedCircuits/Knob_Black_Light_21.svg", {}, -1 },
  274. /*
  275. // Custom, needs permission
  276. { "/AudibleInstruments/Blinds.svg", {}, -1 },
  277. { "/AudibleInstruments/Braids.svg", {}, -1 },
  278. { "/AudibleInstruments/Branches.svg", {}, -1 },
  279. { "/AudibleInstruments/Clouds.svg", {}, -1 },
  280. { "/AudibleInstruments/Elements.svg", {}, -1 },
  281. { "/AudibleInstruments/Frames.svg", {}, -1 },
  282. { "/AudibleInstruments/Kinks.svg", {}, -1 },
  283. { "/AudibleInstruments/Links.svg", {}, -1 },
  284. { "/AudibleInstruments/Marbles.svg", {}, -1 },
  285. { "/AudibleInstruments/Peaks.svg", {}, -1 },
  286. { "/AudibleInstruments/Plaits.svg", {}, -1 },
  287. { "/AudibleInstruments/Rings.svg", {}, -1 },
  288. { "/AudibleInstruments/Ripples.svg", {}, -1 },
  289. { "/AudibleInstruments/Shades.svg", {}, -1 },
  290. { "/AudibleInstruments/Sheep.svg", {}, -1 },
  291. { "/AudibleInstruments/Shelves.svg", {}, -1 },
  292. { "/AudibleInstruments/Stages.svg", {}, -1 },
  293. { "/AudibleInstruments/Streams.svg", {}, -1 },
  294. { "/AudibleInstruments/Tides.svg", {}, -1 },
  295. { "/AudibleInstruments/Tides2.svg", {}, -1 },
  296. { "/AudibleInstruments/Veils.svg", {}, -1 },
  297. { "/AudibleInstruments/Warps.svg", {}, -1 },
  298. */
  299. /*
  300. // CC-BY-NC-ND-4.0, needs permission
  301. { "/Bidoo/ACNE.svg", {}, -1 },
  302. { "/Bidoo/ANTN.svg", {}, -1 },
  303. { "/Bidoo/BAFIS.svg", {}, -1 },
  304. { "/Bidoo/BANCAU.svg", {}, -1 },
  305. { "/Bidoo/BAR.svg", {"rect833"}, -1 },
  306. { "/Bidoo/BISTROT.svg", {}, -1 },
  307. { "/Bidoo/BORDL.svg", {"rect959-3-0-7-5","rect959-3-0-7","rect959-3-0","rect959-3"}, -1 },
  308. { "/Bidoo/CANARD.svg", {"rect959-3-7"}, -1 },
  309. { "/Bidoo/CHUTE.svg", {}, -1 },
  310. { "/Bidoo/DFUZE.svg", {}, -1 },
  311. { "/Bidoo/DIKTAT.svg", {"rect843","rect843-0","rect843-0-8"}, -1 },
  312. { "/Bidoo/DILEMO.svg", {}, -1 },
  313. { "/Bidoo/DTROY.svg", {"rect959-3"}, -1 },
  314. { "/Bidoo/DUKE.svg", {}, -1 },
  315. { "/Bidoo/EDSAROS.svg", {"rect959-3-7","rect959-3-7-8","rect959-3-7-8-1","rect959-3-7-8-1-4"}, -1 },
  316. { "/Bidoo/EMILE.svg", {}, -1 },
  317. { "/Bidoo/FLAME.svg", {}, -1 },
  318. { "/Bidoo/FORK.svg", {}, -1 },
  319. { "/Bidoo/FREIN.svg", {}, -1 },
  320. { "/Bidoo/HCTIP.svg", {}, -1 },
  321. { "/Bidoo/HUITRE.svg", {}, -1 },
  322. { "/Bidoo/LAMBDA.svg", {}, -1 },
  323. { "/Bidoo/LATE.svg", {}, -1 },
  324. { "/Bidoo/LIMBO.svg", {}, -1 },
  325. { "/Bidoo/LIMONADE.svg", {"rect839","rect839-6"}, -1 },
  326. { "/Bidoo/LOURDE.svg", {"rect847","rect847-7","rect847-5","rect847-3"}, -1 },
  327. { "/Bidoo/MAGMA.svg", {}, -1 },
  328. { "/Bidoo/MINIBAR.svg", {"rect833"}, -1 },
  329. { "/Bidoo/MOIRE.svg", {"rect843","rect843-7"}, -1 },
  330. { "/Bidoo/MS.svg", {}, -1 },
  331. { "/Bidoo/MU.svg", {"rect864"}, -1 },
  332. { "/Bidoo/OAI.svg", {}, -1 },
  333. { "/Bidoo/OUAIVE.svg", {"rect959-3-7"}, -1 },
  334. { "/Bidoo/PERCO.svg", {}, -1 },
  335. { "/Bidoo/PILOT.svg", {"rect843-6-4-5","rect843","rect843-4","rect843-6-4","rect843-6-7"}, -1 },
  336. { "/Bidoo/POUPRE.svg", {}, -1 },
  337. { "/Bidoo/RABBIT.svg", {}, -1 },
  338. { "/Bidoo/REI.svg", {}, -1 },
  339. { "/Bidoo/SIGMA.svg", {}, -1 },
  340. { "/Bidoo/SPORE.svg", {}, -1 },
  341. { "/Bidoo/TIARE.svg", {}, -1 },
  342. { "/Bidoo/TOCANTE.svg", {"rect843"}, -1 },
  343. { "/Bidoo/VOID.svg", {}, -1 },
  344. { "/Bidoo/ZINC.svg", {}, -1 },
  345. { "/Bidoo/ZOUMAI.svg", {}, -1 },
  346. */
  347. /*
  348. // BSD-3-Clause ??
  349. { "/cf/ALGEBRA.svg", {}, -1 },
  350. { "/cf/BUFFER.svg", {}, -1 },
  351. { "/cf/CHOKE.svg", {}, -1 },
  352. { "/cf/CUBE.svg", {}, -1 },
  353. { "/cf/CUTS.svg", {}, -1 },
  354. { "/cf/DISTO.svg", {}, -1 },
  355. { "/cf/EACH.svg", {}, -1 },
  356. { "/cf/FOUR.svg", {}, -1 },
  357. { "/cf/FUNKTION.svg", {}, -1 },
  358. { "/cf/L3DS3Q.svg", {}, 3 },
  359. { "/cf/LABEL.svg", {}, -1 },
  360. { "/cf/LEDS.svg", {}, -1 },
  361. { "/cf/LEDSEQ.svg", {}, 3 },
  362. { "/cf/MASTER.svg", {}, -1 },
  363. { "/cf/METRO.svg", {}, -1 },
  364. { "/cf/MONO.svg", {}, -1 },
  365. { "/cf/PATCH.svg", {}, -1 },
  366. { "/cf/PEAK.svg", {}, -1 },
  367. { "/cf/PLAY.svg", {}, -1 },
  368. { "/cf/PLAYER.svg", {}, -1 },
  369. { "/cf/SLIDERSEQ.svg", {}, -1 },
  370. { "/cf/STEPS.svg", {}, -1 },
  371. { "/cf/STEREO.svg", {}, -1 },
  372. { "/cf/SUB.svg", {}, -1 },
  373. { "/cf/trSEQ.svg", {}, -1 },
  374. { "/cf/VARIABLE.svg", {}, -1 },
  375. */
  376. // CC0-1.0
  377. { "/DrumKit/Baronial.svg", {}, -1 },
  378. { "/DrumKit/BD9.svg", {}, -1 },
  379. { "/DrumKit/ClosedHH.svg", {}, -1 },
  380. { "/DrumKit/CR78.svg", {}, -1 },
  381. { "/DrumKit/DMX.svg", {}, -1 },
  382. { "/DrumKit/Gnome.svg", {}, -1 },
  383. { "/DrumKit/Marionette.svg", {}, -1 },
  384. { "/DrumKit/OpenHH.svg", {}, -1 },
  385. { "/DrumKit/SBD.svg", {}, -1 },
  386. { "/DrumKit/Sequencer.svg", {}, -1 },
  387. { "/DrumKit/Snare.svg", {}, -1 },
  388. { "/DrumKit/Tomi.svg", {}, -1 },
  389. { "/ESeries/E340.svg", {}, -1 },
  390. /*
  391. // CC-BY-NC-ND-4.0, needs permission
  392. { "/Fundamental/VCA.svg", {}, -1 },
  393. */
  394. // CC0-1.0
  395. { "/HetrickCV/1OpChaos.svg", {}, -1},
  396. { "/HetrickCV/2OpChaos.svg", {}, -1},
  397. { "/HetrickCV/2To4.svg", {}, -1},
  398. { "/HetrickCV/3OpChaos.svg", {}, -1},
  399. { "/HetrickCV/ASR.svg", {}, -1},
  400. { "/HetrickCV/AToD.svg", {}, -1},
  401. { "/HetrickCV/BinaryGate.svg", {}, -1},
  402. { "/HetrickCV/BinaryNoise.svg", {}, -1},
  403. { "/HetrickCV/Bitshift.svg", {}, -1},
  404. { "/HetrickCV/Boolean3.svg", {}, -1},
  405. { "/HetrickCV/ChaoticAttractors.svg", {}, -1},
  406. { "/HetrickCV/ClockedNoise.svg", {}, -1},
  407. { "/HetrickCV/Comparator.svg", {}, -1},
  408. { "/HetrickCV/Contrast.svg", {}, -1},
  409. { "/HetrickCV/Crackle.svg", {}, -1},
  410. { "/HetrickCV/DataCompander.svg", {}, -1},
  411. { "/HetrickCV/Delta.svg", {}, -1},
  412. { "/HetrickCV/DToA.svg", {}, -1},
  413. { "/HetrickCV/Dust.svg", {}, -1},
  414. { "/HetrickCV/Exponent.svg", {}, -1},
  415. { "/HetrickCV/FBSineChaos.svg", {}, -1},
  416. { "/HetrickCV/FlipFlop.svg", {}, -1},
  417. { "/HetrickCV/FlipPan.svg", {}, -1},
  418. { "/HetrickCV/GateJunction.svg", {}, -1},
  419. { "/HetrickCV/Gingerbread.svg", {}, -1},
  420. { "/HetrickCV/LogicCombiner.svg", {}, -1},
  421. { "/HetrickCV/LogicInverter.svg", {}, -1},
  422. { "/HetrickCV/MidSide.svg", {}, -1},
  423. { "/HetrickCV/MinMax.svg", {}, -1},
  424. { "/HetrickCV/RandomGates.svg", {}, -1},
  425. { "/HetrickCV/Rotator.svg", {}, -1},
  426. { "/HetrickCV/Rungler.svg", {}, -1},
  427. { "/HetrickCV/Scanner.svg", {}, -1},
  428. { "/HetrickCV/TrigShaper.svg", {}, -1},
  429. { "/HetrickCV/Waveshape.svg", {}, -1},
  430. { "/HetrickCV/XYToPolar.svg", {}, -1},
  431. { "/HetrickCV/Blanks/BlankPanel1.svg", {}, -1},
  432. { "/HetrickCV/Blanks/BlankPanel2.svg", {}, -1},
  433. { "/HetrickCV/Blanks/BlankPanel3.svg", {}, -1},
  434. { "/HetrickCV/Blanks/BlankPanel5.svg", {}, -1},
  435. { "/HetrickCV/Blanks/BlankPanel6.svg", {}, -1},
  436. { "/HetrickCV/Blanks/BlankPanel7.svg", {}, -1},
  437. { "/HetrickCV/Blanks/BlankPanel8.svg", {}, -1},
  438. // BSD-3-Clause
  439. { "/JW-Modules/Add5.svg", {}, -1 },
  440. { "/JW-Modules/BlankPanel1hp.svg", {}, -1 },
  441. { "/JW-Modules/BlankPanelLarge.svg", {}, -1 },
  442. { "/JW-Modules/BlankPanelMedium.svg", {}, -1 },
  443. { "/JW-Modules/BlankPanelSmall.svg", {}, -1 },
  444. { "/JW-Modules/BouncyBalls.svg", {}, -1 },
  445. { "/JW-Modules/D1v1de.svg", {}, -1 },
  446. { "/JW-Modules/DivSeq.svg", {}, -1 },
  447. { "/JW-Modules/EightSeq.svg", {}, -1 },
  448. { "/JW-Modules/GridSeq.svg", {}, -1 },
  449. { "/JW-Modules/MinMax.svg", {"path38411"}, -1 },
  450. { "/JW-Modules/NoteSeq.svg", {}, -1 },
  451. { "/JW-Modules/NoteSeq16.svg", {}, -1 },
  452. { "/JW-Modules/NoteSeqFu.svg", {}, -1 },
  453. { "/JW-Modules/OnePattern.svg", {}, -1 },
  454. { "/JW-Modules/Patterns.svg", {}, -1 },
  455. { "/JW-Modules/Pres1t.svg", {}, -1 },
  456. { "/JW-Modules/PT.svg", {}, -1 },
  457. { "/JW-Modules/Str1ker.svg", {"rect2094","rect995","rect169"}, -1 },
  458. { "/JW-Modules/Trigs.svg", {}, -1 },
  459. { "/JW-Modules/WavHeadPanel.svg", {}, -1 },
  460. { "/JW-Modules/XYPad.svg", {}, -1 },
  461. // EUPL-1.2
  462. { "/LittleUtils/Bias_Semitone.svg", {}, -1 },
  463. { "/LittleUtils/ButtonModule.svg", {}, -1 },
  464. { "/LittleUtils/MulDiv.svg", {}, -1 },
  465. { "/LittleUtils/PulseGenerator.svg", {}, -1 },
  466. { "/LittleUtils/TeleportIn.svg", {}, -1 },
  467. { "/LittleUtils/TeleportOut.svg", {}, -1 },
  468. };
  469. static inline void removeShape(NSVGimage* const handle, const char* const id)
  470. {
  471. if (id == nullptr)
  472. return;
  473. for (NSVGshape *shape = handle->shapes, *old = nullptr; shape != nullptr; old = shape, shape = shape->next)
  474. {
  475. if (std::strcmp(shape->id, id) != 0)
  476. continue;
  477. if (old != nullptr)
  478. old->next = shape->next;
  479. else
  480. handle->shapes = shape->next;
  481. nsvg__deletePaths(shape->paths);
  482. free(shape);
  483. return;
  484. }
  485. printf("NOTICE: failed to find '%s' shape to remove\n", id);
  486. }
  487. static inline bool invertPaint(NSVGpaint& paint, const char* const svgFileToInvert = nullptr)
  488. {
  489. // Special case for DrumKit background grandient
  490. if (paint.type == NSVG_PAINT_LINEAR_GRADIENT && svgFileToInvert != nullptr && std::strncmp(svgFileToInvert, "/DrumKit/", 9) == 0)
  491. {
  492. paint.type = NSVG_PAINT_COLOR;
  493. paint.color = 0xff191919;
  494. return true;
  495. }
  496. if (paint.type == NSVG_PAINT_NONE)
  497. return true;
  498. if (paint.type != NSVG_PAINT_COLOR)
  499. return false;
  500. // Special case for Bidoo red color
  501. if (paint.color == 0xff001fcd && svgFileToInvert != nullptr && std::strncmp(svgFileToInvert, "/Bidoo/", 7) == 0)
  502. {
  503. paint.color = 0xcf8b94c4;
  504. return true;
  505. }
  506. // Special case for AnimatedCircuits logo
  507. if (paint.color == 0xff303030 && svgFileToInvert != nullptr && std::strncmp(svgFileToInvert, "/AnimatedCircuits/", 18) == 0)
  508. {
  509. paint.color = 0xffefefef;
  510. return true;
  511. }
  512. // Special case for JW-Modules colors
  513. if (svgFileToInvert != nullptr && std::strncmp(svgFileToInvert, "/JW-Modules/", 12) == 0)
  514. {
  515. switch (paint.color)
  516. {
  517. // do nothing
  518. case 0x320997ff:
  519. case 0x32099aff:
  520. case 0x3209f1ff:
  521. case 0x3209f3ff:
  522. case 0x32fc1a8f:
  523. case 0x32fc1a90:
  524. case 0x32fc9418:
  525. case 0x32fc9619:
  526. case 0xc7fc9619:
  527. case 0xff050505:
  528. case 0xffead7be:
  529. case 0xfff7a540:
  530. case 0xfffa9c2a:
  531. case 0xfffc9619:
  532. case 0xfffcb654:
  533. case 0xfffd9c17:
  534. case 0xffffffff:
  535. return false;
  536. // make more transparent
  537. case 0xffbad6eb:
  538. case 0xffbae8eb:
  539. case 0xffeabed5:
  540. case 0xffead6bd:
  541. paint.color = 0x32000000 | (paint.color & 0xffffff);
  542. return true;
  543. // make it more white
  544. case 0xffa0a0a0:
  545. paint.color = 0xffc0c0c0;
  546. return true;
  547. }
  548. }
  549. switch (paint.color)
  550. {
  551. // scopes or other special things (do nothing)
  552. case 0x40ffffff:
  553. case 0xff004200:
  554. case 0xff2b281e:
  555. case 0xff2d2827:
  556. case 0xff303030:
  557. case 0xff362c23:
  558. case 0xff40352c:
  559. case 0xff5735d9:
  560. case 0xff5935d8:
  561. case 0xff5c26d9:
  562. case 0xff6140db:
  563. case 0xffa09400:
  564. case 0xffa19400:
  565. case 0xffa7a100:
  566. case 0xffa8a200:
  567. case 0xffaba102:
  568. case 0xff22a5e9:
  569. case 0xff6140da:
  570. case 0xff119ee6:
  571. case 0xff2432ed:
  572. case 0xff0095fe:
  573. case 0xff4d9a4d:
  574. case 0xff4d4d9a:
  575. // AnimatedCircuits FoldingLight.svg
  576. case 0xffa0783c:
  577. return false;
  578. // pure black (convert to not quite pure white)
  579. case 0xff000000:
  580. paint.color = 0xffd0d0d0;
  581. return true;
  582. // all others (direct invert)
  583. default:
  584. paint.color = (paint.color & 0xff000000)
  585. | (0xff0000 - (paint.color & 0xff0000))
  586. | (0xff00 - (paint.color & 0xff00))
  587. | (0xff - (paint.color & 0xff));
  588. return true;
  589. }
  590. }
  591. extern "C" {
  592. NSVGimage* nsvgParseFromFileCardinal(const char* filename, const char* units, float dpi);
  593. }
  594. NSVGimage* nsvgParseFromFileCardinal(const char* const filename, const char* const units, const float dpi)
  595. {
  596. if (NSVGimage* const handle = nsvgParseFromFile(filename, units, dpi))
  597. {
  598. for (size_t i = 0; i < sizeof(pathsToFilterOut)/sizeof(pathsToFilterOut[0]); ++i)
  599. {
  600. const char* const pathToFilterOut = pathsToFilterOut[i].filename;
  601. const size_t filenamelen = std::strlen(filename);
  602. const size_t filterlen = std::strlen(pathToFilterOut);
  603. if (filenamelen < filterlen)
  604. continue;
  605. if (std::strncmp(filename + (filenamelen-filterlen), pathToFilterOut, filterlen) != 0)
  606. continue;
  607. puts("Removing CC-ND deadlock from file...");
  608. removeShape(handle, pathsToFilterOut[i].shapes[0]);
  609. removeShape(handle, pathsToFilterOut[i].shapes[1]);
  610. removeShape(handle, pathsToFilterOut[i].shapes[2]);
  611. removeShape(handle, pathsToFilterOut[i].shapes[3]);
  612. removeShape(handle, pathsToFilterOut[i].shapes[4]);
  613. removeShape(handle, pathsToFilterOut[i].shapes[5]);
  614. removeShape(handle, pathsToFilterOut[i].shapes[6]);
  615. removeShape(handle, pathsToFilterOut[i].shapes[7]);
  616. for (NSVGshape* shape = handle->shapes; shape != nullptr; shape = shape->next)
  617. {
  618. invertPaint(shape->fill);
  619. invertPaint(shape->stroke);
  620. }
  621. // replace white background
  622. handle->shapes->fill.type = NSVG_PAINT_COLOR;
  623. handle->shapes->fill.color = 0xff202020;
  624. handle->shapes->stroke.type = NSVG_PAINT_NONE;
  625. return handle;
  626. }
  627. for (size_t i = 0; i < sizeof(svgFilesToInvert)/sizeof(svgFilesToInvert[0]); ++i)
  628. {
  629. const char* const svgFileToInvert = svgFilesToInvert[i].filename;
  630. const size_t filenamelen = std::strlen(filename);
  631. const size_t filterlen = std::strlen(svgFileToInvert);
  632. if (filenamelen < filterlen)
  633. continue;
  634. if (std::strncmp(filename + (filenamelen-filterlen), svgFileToInvert, filterlen) != 0)
  635. continue;
  636. const char* const* const shapeIdsToIgnore = svgFilesToInvert[i].shapeIdsToIgnore;
  637. const int shapeNumberToIgnore = svgFilesToInvert[i].shapeNumberToIgnore;
  638. int shapeCounter = 0;
  639. for (NSVGshape* shape = handle->shapes; shape != nullptr; shape = shape->next, ++shapeCounter)
  640. {
  641. if (shapeNumberToIgnore == shapeCounter)
  642. continue;
  643. bool ignore = false;
  644. for (size_t j = 0; j < 5 && shapeIdsToIgnore[j] != nullptr; ++j)
  645. {
  646. if (std::strcmp(shape->id, shapeIdsToIgnore[j]) == 0)
  647. {
  648. ignore = true;
  649. break;
  650. }
  651. }
  652. if (ignore)
  653. continue;
  654. if (invertPaint(shape->fill, svgFileToInvert))
  655. invertPaint(shape->stroke, svgFileToInvert);
  656. }
  657. return handle;
  658. }
  659. // Special case for AmalgamatedHarmonics background color
  660. if (handle->shapes != nullptr && handle->shapes->fill.color == 0xff000000)
  661. if (std::strstr(filename, "/AmalgamatedHarmonics/") != nullptr)
  662. handle->shapes->fill.color = 0xff191919;
  663. return handle;
  664. }
  665. return nullptr;
  666. }