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.

356 lines
10KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. #include "../jucer_Headers.h"
  18. #include "jucer_JucerDocument.h"
  19. //==============================================================================
  20. BinaryResources::BinaryResources()
  21. {
  22. }
  23. BinaryResources::~BinaryResources()
  24. {
  25. }
  26. BinaryResources& BinaryResources::operator= (const BinaryResources& other)
  27. {
  28. for (int i = 0; i < other.resources.size(); ++i)
  29. add (other.resources[i]->name,
  30. other.resources[i]->originalFilename,
  31. other.resources[i]->data);
  32. return *this;
  33. }
  34. void BinaryResources::changed()
  35. {
  36. if (document != nullptr)
  37. {
  38. document->changed();
  39. document->refreshAllPropertyComps();
  40. }
  41. }
  42. //==============================================================================
  43. void BinaryResources::clear()
  44. {
  45. if (resources.size() > 0)
  46. {
  47. resources.clear();
  48. changed();
  49. }
  50. }
  51. StringArray BinaryResources::getResourceNames() const
  52. {
  53. StringArray s;
  54. for (int i = 0; i < resources.size(); ++i)
  55. s.add (resources.getUnchecked(i)->name);
  56. return s;
  57. }
  58. BinaryResources::BinaryResource* BinaryResources::findResource (const String& name) const noexcept
  59. {
  60. for (int i = resources.size(); --i >= 0;)
  61. if (resources.getUnchecked(i)->name == name)
  62. return resources.getUnchecked(i);
  63. return 0;
  64. }
  65. const BinaryResources::BinaryResource* BinaryResources::getResource (const String& name) const
  66. {
  67. return findResource (name);
  68. }
  69. const BinaryResources::BinaryResource* BinaryResources::getResourceForFile (const File& file) const
  70. {
  71. for (int i = resources.size(); --i >= 0;)
  72. if (resources.getUnchecked(i)->originalFilename == file.getFullPathName())
  73. return resources.getUnchecked(i);
  74. return 0;
  75. }
  76. bool BinaryResources::add (const String& name, const File& file)
  77. {
  78. MemoryBlock mb;
  79. if (! file.loadFileAsData (mb))
  80. return false;
  81. add (name, file.getFullPathName(), mb);
  82. return true;
  83. }
  84. void BinaryResources::add (const String& name, const String& originalFileName, const MemoryBlock& data)
  85. {
  86. BinaryResource* r = findResource (name);
  87. if (r == 0)
  88. {
  89. resources.add (r = new BinaryResource());
  90. r->name = name;
  91. }
  92. r->originalFilename = originalFileName;
  93. r->data = data;
  94. deleteAndZero (r->drawable);
  95. changed();
  96. }
  97. bool BinaryResources::reload (const int index)
  98. {
  99. return resources[index] != 0
  100. && add (resources [index]->name,
  101. File (resources [index]->originalFilename));
  102. }
  103. String BinaryResources::browseForResource (const String& title,
  104. const String& wildcard,
  105. const File& fileToStartFrom,
  106. const String& resourceToReplace)
  107. {
  108. FileChooser fc (title, fileToStartFrom, wildcard);
  109. if (fc.browseForFileToOpen())
  110. {
  111. String name (resourceToReplace);
  112. if (name.isEmpty())
  113. name = findUniqueName (fc.getResult().getFileName());
  114. if (! add (name, fc.getResult()))
  115. {
  116. AlertWindow::showMessageBox (AlertWindow::WarningIcon,
  117. TRANS("Adding Resource"),
  118. TRANS("Failed to load the file!"));
  119. name = String::empty;
  120. }
  121. return name;
  122. }
  123. return String::empty;
  124. }
  125. String BinaryResources::findUniqueName (const String& rootName) const
  126. {
  127. String nameRoot (CodeHelpers::makeValidIdentifier (rootName, true, true, false));
  128. String name (nameRoot);
  129. const StringArray names (getResourceNames());
  130. int suffix = 1;
  131. while (names.contains (name))
  132. name = nameRoot + String (++suffix);
  133. return name;
  134. }
  135. void BinaryResources::remove (const int i)
  136. {
  137. if (resources[i] != 0)
  138. {
  139. resources.remove (i);
  140. changed();
  141. }
  142. }
  143. const Drawable* BinaryResources::getDrawable (const String& name) const
  144. {
  145. BinaryResources::BinaryResource* const res = const_cast <BinaryResources::BinaryResource*> (getResource (name));
  146. if (res == 0)
  147. return 0;
  148. if (res->drawable == 0 && res->data.getSize() > 0)
  149. res->drawable = Drawable::createFromImageData (res->data.getData(), res->data.getSize());
  150. return res->drawable;
  151. }
  152. Image BinaryResources::getImageFromCache (const String& name) const
  153. {
  154. if (const BinaryResources::BinaryResource* const res = getResource (name))
  155. if (res->data.getSize() > 0)
  156. return ImageCache::getFromMemory (res->data.getData(), (int) res->data.getSize());
  157. return Image();
  158. }
  159. void BinaryResources::loadFromCpp (const File& cppFileLocation, const String& cppFile)
  160. {
  161. StringArray cpp;
  162. cpp.addLines (cppFile);
  163. clear();
  164. for (int i = 0; i < cpp.size(); ++i)
  165. {
  166. if (cpp[i].contains ("JUCER_RESOURCE:"))
  167. {
  168. StringArray tokens;
  169. tokens.addTokens (cpp[i].fromFirstOccurrenceOf (":", false, false), ",", "\"'");
  170. tokens.trim();
  171. tokens.removeEmptyStrings();
  172. const String resourceName (tokens[0]);
  173. const int size = tokens[1].getIntValue();
  174. const String originalFileName (cppFileLocation.getSiblingFile (tokens[2].unquoted()).getFullPathName());
  175. jassert (resourceName.isNotEmpty() && size > 0);
  176. if (resourceName.isNotEmpty() && size > 0)
  177. {
  178. const int firstLine = i;
  179. while (i < cpp.size())
  180. if (cpp [i++].contains ("}"))
  181. break;
  182. const String dataString (cpp.joinIntoString (" ", firstLine, i - firstLine)
  183. .fromFirstOccurrenceOf ("{", false, false));
  184. MemoryOutputStream out;
  185. String::CharPointerType t (dataString.getCharPointer());
  186. int n = 0;
  187. while (! t.isEmpty())
  188. {
  189. const juce_wchar c = t.getAndAdvance();
  190. if (c >= '0' && c <= '9')
  191. n = n * 10 + (c - '0');
  192. else if (c == ',')
  193. {
  194. out.writeByte ((char) n);
  195. n = 0;
  196. }
  197. else if (c == '}')
  198. break;
  199. }
  200. jassert (size < (int) out.getDataSize() && size > (int) out.getDataSize() - 2);
  201. MemoryBlock mb (out.getData(), out.getDataSize());
  202. mb.setSize (size);
  203. add (resourceName, originalFileName, mb);
  204. }
  205. }
  206. }
  207. }
  208. //==============================================================================
  209. void BinaryResources::fillInGeneratedCode (GeneratedCode& code) const
  210. {
  211. if (resources.size() > 0)
  212. {
  213. code.publicMemberDeclarations << "// Binary resources:\n";
  214. String defs;
  215. defs << "//==============================================================================\n";
  216. defs << "// Binary resources - be careful not to edit any of these sections!\n\n";
  217. for (int i = 0; i < resources.size(); ++i)
  218. {
  219. code.publicMemberDeclarations
  220. << "static const char* "
  221. << resources[i]->name
  222. << ";\nstatic const int "
  223. << resources[i]->name
  224. << "Size;\n";
  225. const String name (resources[i]->name);
  226. const MemoryBlock& mb = resources[i]->data;
  227. defs << "// JUCER_RESOURCE: " << name << ", " << (int) mb.getSize()
  228. << ", \""
  229. << File (resources[i]->originalFilename)
  230. .getRelativePathFrom (code.document->getCppFile())
  231. .replaceCharacter ('\\', '/')
  232. << "\"\n";
  233. String line1;
  234. line1 << "static const unsigned char resource_"
  235. << code.className << "_" << name << "[] = { ";
  236. defs += line1;
  237. MemoryOutputStream out (65536);
  238. int charsOnLine = line1.length();
  239. for (size_t j = 0; j < mb.getSize(); ++j)
  240. {
  241. const int num = ((int) (unsigned char) mb[j]);
  242. out << num << ',';
  243. charsOnLine += 2;
  244. if (num >= 10)
  245. ++charsOnLine;
  246. if (num >= 100)
  247. ++charsOnLine;
  248. if (charsOnLine >= 200)
  249. {
  250. charsOnLine = 0;
  251. out << '\n';
  252. }
  253. }
  254. out << (char) 0;
  255. defs
  256. << (const char*) out.getData()
  257. << "0,0};\n\nconst char* "
  258. << 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;
  266. }
  267. }
  268. BinaryResources::BinaryResource::BinaryResource()
  269. : drawable (0)
  270. {
  271. }
  272. BinaryResources::BinaryResource::~BinaryResource()
  273. {
  274. deleteAndZero (drawable);
  275. }