The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

343 lines
9.7KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. #include "../Application/jucer_Headers.h"
  19. #include "jucer_JucerDocument.h"
  20. //==============================================================================
  21. BinaryResources::BinaryResources()
  22. {
  23. }
  24. BinaryResources::~BinaryResources()
  25. {
  26. }
  27. BinaryResources& BinaryResources::operator= (const BinaryResources& other)
  28. {
  29. for (auto* r : other.resources)
  30. add (r->name, r->originalFilename, r->data);
  31. return *this;
  32. }
  33. void BinaryResources::changed()
  34. {
  35. if (document != nullptr)
  36. {
  37. document->changed();
  38. document->refreshAllPropertyComps();
  39. }
  40. }
  41. //==============================================================================
  42. void BinaryResources::clear()
  43. {
  44. if (resources.size() > 0)
  45. {
  46. resources.clear();
  47. changed();
  48. }
  49. }
  50. StringArray BinaryResources::getResourceNames() const
  51. {
  52. StringArray s;
  53. for (auto* r : resources)
  54. s.add (r->name);
  55. return s;
  56. }
  57. BinaryResources::BinaryResource* BinaryResources::findResource (const String& name) const noexcept
  58. {
  59. for (auto* r : resources)
  60. if (r->name == name)
  61. return r;
  62. return nullptr;
  63. }
  64. const BinaryResources::BinaryResource* BinaryResources::getResource (const String& name) const
  65. {
  66. return findResource (name);
  67. }
  68. const BinaryResources::BinaryResource* BinaryResources::getResourceForFile (const File& file) const
  69. {
  70. for (auto* r : resources)
  71. if (r->originalFilename == file.getFullPathName())
  72. return r;
  73. return nullptr;
  74. }
  75. bool BinaryResources::add (const String& name, const File& file)
  76. {
  77. MemoryBlock mb;
  78. if (! file.loadFileAsData (mb))
  79. return false;
  80. add (name, file.getFullPathName(), mb);
  81. return true;
  82. }
  83. void BinaryResources::add (const String& name, const String& originalFileName, const MemoryBlock& data)
  84. {
  85. auto* r = findResource (name);
  86. if (r == nullptr)
  87. {
  88. resources.add (r = new BinaryResource());
  89. r->name = name;
  90. }
  91. r->originalFilename = originalFileName;
  92. r->data = data;
  93. r->drawable.reset();
  94. changed();
  95. }
  96. bool BinaryResources::reload (const int index)
  97. {
  98. return resources[index] != nullptr
  99. && add (resources [index]->name,
  100. File (resources [index]->originalFilename));
  101. }
  102. String BinaryResources::browseForResource (const String& title,
  103. const String& wildcard,
  104. const File& fileToStartFrom,
  105. const String& resourceToReplace)
  106. {
  107. FileChooser fc (title, fileToStartFrom, wildcard);
  108. if (fc.browseForFileToOpen())
  109. {
  110. String name (resourceToReplace);
  111. if (name.isEmpty())
  112. name = findUniqueName (fc.getResult().getFileName());
  113. if (! add (name, fc.getResult()))
  114. {
  115. AlertWindow::showMessageBox (AlertWindow::WarningIcon,
  116. TRANS("Adding Resource"),
  117. TRANS("Failed to load the file!"));
  118. name.clear();
  119. }
  120. return name;
  121. }
  122. return {};
  123. }
  124. String BinaryResources::findUniqueName (const String& rootName) const
  125. {
  126. auto nameRoot = build_tools::makeValidIdentifier (rootName, true, true, false);
  127. auto name = nameRoot;
  128. auto names = getResourceNames();
  129. int suffix = 1;
  130. while (names.contains (name))
  131. name = nameRoot + String (++suffix);
  132. return name;
  133. }
  134. void BinaryResources::remove (int i)
  135. {
  136. if (resources[i] != nullptr)
  137. {
  138. resources.remove (i);
  139. changed();
  140. }
  141. }
  142. const Drawable* BinaryResources::getDrawable (const String& name) const
  143. {
  144. if (auto* res = const_cast<BinaryResources::BinaryResource*> (getResource (name)))
  145. {
  146. if (res->drawable == nullptr && res->data.getSize() > 0)
  147. res->drawable = Drawable::createFromImageData (res->data.getData(),
  148. res->data.getSize());
  149. return res->drawable.get();
  150. }
  151. return nullptr;
  152. }
  153. Image BinaryResources::getImageFromCache (const String& name) const
  154. {
  155. if (auto* res = getResource (name))
  156. if (res->data.getSize() > 0)
  157. return ImageCache::getFromMemory (res->data.getData(), (int) res->data.getSize());
  158. return {};
  159. }
  160. void BinaryResources::loadFromCpp (const File& cppFileLocation, const String& cppFile)
  161. {
  162. StringArray cpp;
  163. cpp.addLines (cppFile);
  164. clear();
  165. for (int i = 0; i < cpp.size(); ++i)
  166. {
  167. if (cpp[i].contains ("JUCER_RESOURCE:"))
  168. {
  169. StringArray tokens;
  170. tokens.addTokens (cpp[i].fromFirstOccurrenceOf (":", false, false), ",", "\"'");
  171. tokens.trim();
  172. tokens.removeEmptyStrings();
  173. auto resourceName = tokens[0];
  174. auto resourceSize = tokens[1].getIntValue();
  175. auto originalFileName = cppFileLocation.getSiblingFile (tokens[2].unquoted()).getFullPathName();
  176. jassert (resourceName.isNotEmpty() && resourceSize > 0);
  177. if (resourceName.isNotEmpty() && resourceSize > 0)
  178. {
  179. auto firstLine = i;
  180. while (i < cpp.size())
  181. if (cpp [i++].contains ("}"))
  182. break;
  183. auto dataString = cpp.joinIntoString (" ", firstLine, i - firstLine)
  184. .fromFirstOccurrenceOf ("{", false, false);
  185. MemoryOutputStream out;
  186. String::CharPointerType t (dataString.getCharPointer());
  187. int n = 0;
  188. while (! t.isEmpty())
  189. {
  190. auto c = t.getAndAdvance();
  191. if (c >= '0' && c <= '9')
  192. {
  193. n = n * 10 + (int) (c - '0');
  194. }
  195. else if (c == ',')
  196. {
  197. out.writeByte ((char) n);
  198. n = 0;
  199. }
  200. else if (c == '}')
  201. {
  202. break;
  203. }
  204. }
  205. jassert (resourceSize < (int) out.getDataSize() && resourceSize > (int) out.getDataSize() - 2);
  206. MemoryBlock mb (out.getData(), out.getDataSize());
  207. mb.setSize ((size_t) resourceSize);
  208. add (resourceName, originalFileName, mb);
  209. }
  210. }
  211. }
  212. }
  213. //==============================================================================
  214. void BinaryResources::fillInGeneratedCode (GeneratedCode& code) const
  215. {
  216. if (resources.size() > 0)
  217. {
  218. code.publicMemberDeclarations << "// Binary resources:\n";
  219. MemoryOutputStream defs;
  220. defs << "//==============================================================================\n";
  221. defs << "// Binary resources - be careful not to edit any of these sections!\n\n";
  222. for (auto* r : resources)
  223. {
  224. code.publicMemberDeclarations
  225. << "static const char* "
  226. << r->name
  227. << ";\nstatic const int "
  228. << r->name
  229. << "Size;\n";
  230. auto name = r->name;
  231. auto& mb = r->data;
  232. defs << "// JUCER_RESOURCE: " << name << ", " << (int) mb.getSize()
  233. << ", \""
  234. << File (r->originalFilename)
  235. .getRelativePathFrom (code.document->getCppFile())
  236. .replaceCharacter ('\\', '/')
  237. << "\"\n";
  238. String line1;
  239. line1 << "static const unsigned char resource_"
  240. << code.className << "_" << name << "[] = { ";
  241. defs << line1;
  242. int charsOnLine = line1.length();
  243. for (size_t j = 0; j < mb.getSize(); ++j)
  244. {
  245. auto num = (int) (unsigned char) mb[j];
  246. defs << num << ',';
  247. charsOnLine += 2;
  248. if (num >= 10) ++charsOnLine;
  249. if (num >= 100) ++charsOnLine;
  250. if (charsOnLine >= 200)
  251. {
  252. charsOnLine = 0;
  253. defs << '\n';
  254. }
  255. }
  256. defs
  257. << "0,0};\n\n"
  258. "const char* " << code.className << "::" << name
  259. << " = (const char*) resource_" << code.className << "_" << name
  260. << ";\nconst int "
  261. << code.className << "::" << name << "Size = "
  262. << (int) mb.getSize()
  263. << ";\n\n";
  264. }
  265. code.staticMemberDefinitions << defs.toString();
  266. }
  267. }