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.

286 lines
9.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-10 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "../../../core/juce_StandardHeader.h"
  19. BEGIN_JUCE_NAMESPACE
  20. #include "juce_Drawable.h"
  21. #include "juce_DrawableComposite.h"
  22. #include "juce_DrawablePath.h"
  23. #include "juce_DrawableImage.h"
  24. #include "juce_DrawableText.h"
  25. #include "../imaging/juce_ImageFileFormat.h"
  26. #include "../../../text/juce_XmlDocument.h"
  27. #include "../../../io/files/juce_FileInputStream.h"
  28. //==============================================================================
  29. Drawable::RenderingContext::RenderingContext (Graphics& g_,
  30. const AffineTransform& transform_,
  31. const float opacity_) throw()
  32. : g (g_),
  33. transform (transform_),
  34. opacity (opacity_)
  35. {
  36. }
  37. //==============================================================================
  38. Drawable::Drawable()
  39. : parent (0)
  40. {
  41. }
  42. Drawable::~Drawable()
  43. {
  44. }
  45. void Drawable::draw (Graphics& g, const float opacity, const AffineTransform& transform) const
  46. {
  47. render (RenderingContext (g, transform, opacity));
  48. }
  49. void Drawable::drawAt (Graphics& g, const float x, const float y, const float opacity) const
  50. {
  51. draw (g, opacity, AffineTransform::translation (x, y));
  52. }
  53. void Drawable::drawWithin (Graphics& g,
  54. const int destX,
  55. const int destY,
  56. const int destW,
  57. const int destH,
  58. const RectanglePlacement& placement,
  59. const float opacity) const
  60. {
  61. if (destW > 0 && destH > 0)
  62. {
  63. Rectangle<float> bounds (getBounds());
  64. draw (g, opacity,
  65. placement.getTransformToFit (bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(),
  66. (float) destX, (float) destY,
  67. (float) destW, (float) destH));
  68. }
  69. }
  70. //==============================================================================
  71. Drawable* Drawable::createFromImageData (const void* data, const size_t numBytes)
  72. {
  73. Drawable* result = 0;
  74. Image* const image = ImageFileFormat::loadFrom (data, (int) numBytes);
  75. if (image != 0)
  76. {
  77. DrawableImage* const di = new DrawableImage();
  78. di->setImage (image, true);
  79. result = di;
  80. }
  81. else
  82. {
  83. const String asString (String::createStringFromData (data, (int) numBytes));
  84. XmlDocument doc (asString);
  85. ScopedPointer <XmlElement> outer (doc.getDocumentElement (true));
  86. if (outer != 0 && outer->hasTagName ("svg"))
  87. {
  88. ScopedPointer <XmlElement> svg (doc.getDocumentElement());
  89. if (svg != 0)
  90. result = Drawable::createFromSVG (*svg);
  91. }
  92. }
  93. return result;
  94. }
  95. Drawable* Drawable::createFromImageDataStream (InputStream& dataSource)
  96. {
  97. MemoryBlock mb;
  98. dataSource.readIntoMemoryBlock (mb);
  99. return createFromImageData (mb.getData(), mb.getSize());
  100. }
  101. Drawable* Drawable::createFromImageFile (const File& file)
  102. {
  103. const ScopedPointer <FileInputStream> fin (file.createInputStream());
  104. return fin != 0 ? createFromImageDataStream (*fin) : 0;
  105. }
  106. //==============================================================================
  107. Drawable* Drawable::createFromValueTree (const ValueTree& tree, ImageProvider* imageProvider)
  108. {
  109. const Identifier type (tree.getType());
  110. Drawable* d = 0;
  111. if (type == DrawablePath::valueTreeType)
  112. d = new DrawablePath();
  113. else if (type == DrawableComposite::valueTreeType)
  114. d = new DrawableComposite();
  115. else if (type == DrawableImage::valueTreeType)
  116. d = new DrawableImage();
  117. else if (type == DrawableText::valueTreeType)
  118. d = new DrawableText();
  119. if (d != 0)
  120. d->refreshFromValueTree (tree, imageProvider);
  121. return d;
  122. }
  123. //==============================================================================
  124. const Identifier Drawable::ValueTreeWrapperBase::idProperty ("id");
  125. const Identifier Drawable::ValueTreeWrapperBase::type ("type");
  126. const Identifier Drawable::ValueTreeWrapperBase::x1 ("x1");
  127. const Identifier Drawable::ValueTreeWrapperBase::x2 ("x2");
  128. const Identifier Drawable::ValueTreeWrapperBase::y1 ("y1");
  129. const Identifier Drawable::ValueTreeWrapperBase::y2 ("y2");
  130. const Identifier Drawable::ValueTreeWrapperBase::colour ("colour");
  131. const Identifier Drawable::ValueTreeWrapperBase::radial ("radial");
  132. const Identifier Drawable::ValueTreeWrapperBase::colours ("colours");
  133. Drawable::ValueTreeWrapperBase::ValueTreeWrapperBase (const ValueTree& state_)
  134. : state (state_)
  135. {
  136. }
  137. Drawable::ValueTreeWrapperBase::~ValueTreeWrapperBase()
  138. {
  139. }
  140. const String Drawable::ValueTreeWrapperBase::getID() const
  141. {
  142. return state [idProperty];
  143. }
  144. void Drawable::ValueTreeWrapperBase::setID (const String& newID, UndoManager* undoManager)
  145. {
  146. if (newID.isEmpty())
  147. state.removeProperty (idProperty, undoManager);
  148. else
  149. state.setProperty (idProperty, newID, undoManager);
  150. }
  151. const FillType Drawable::ValueTreeWrapperBase::readFillType (const ValueTree& v)
  152. {
  153. const String newType (v[type].toString());
  154. if (newType == "solid")
  155. {
  156. const String colourString (v [colour].toString());
  157. return FillType (Colour (colourString.isEmpty() ? (uint32) 0xff000000
  158. : (uint32) colourString.getHexValue32()));
  159. }
  160. else if (newType == "gradient")
  161. {
  162. ColourGradient g;
  163. g.point1.setXY (v[x1], v[y1]);
  164. g.point2.setXY (v[x2], v[y2]);
  165. g.isRadial = v[radial];
  166. StringArray colourSteps;
  167. colourSteps.addTokens (v[colours].toString(), false);
  168. for (int i = 0; i < colourSteps.size() / 2; ++i)
  169. g.addColour (colourSteps[i * 2].getDoubleValue(),
  170. Colour ((uint32) colourSteps[i * 2 + 1].getHexValue32()));
  171. return FillType (g);
  172. }
  173. else if (newType == "image")
  174. {
  175. jassertfalse; //xxx todo
  176. }
  177. jassertfalse;
  178. return FillType();
  179. }
  180. void Drawable::ValueTreeWrapperBase::replaceFillType (const Identifier& tag, const FillType& fillType, UndoManager* undoManager)
  181. {
  182. ValueTree v (state.getChildWithName (tag));
  183. if (! v.isValid())
  184. {
  185. state.addChild (ValueTree (tag), -1, undoManager);
  186. v = state.getChildWithName (tag);
  187. }
  188. if (fillType.isColour())
  189. {
  190. v.setProperty (type, "solid", undoManager);
  191. v.setProperty (colour, String::toHexString ((int) fillType.colour.getARGB()), undoManager);
  192. v.removeProperty (x1, undoManager);
  193. v.removeProperty (x2, undoManager);
  194. v.removeProperty (y1, undoManager);
  195. v.removeProperty (y2, undoManager);
  196. v.removeProperty (radial, undoManager);
  197. v.removeProperty (colours, undoManager);
  198. }
  199. else if (fillType.isGradient())
  200. {
  201. v.setProperty (type, "gradient", undoManager);
  202. v.setProperty (x1, fillType.gradient->point1.getX(), undoManager);
  203. v.setProperty (y1, fillType.gradient->point1.getY(), undoManager);
  204. v.setProperty (x2, fillType.gradient->point2.getX(), undoManager);
  205. v.setProperty (y2, fillType.gradient->point2.getY(), undoManager);
  206. v.setProperty (radial, fillType.gradient->isRadial, undoManager);
  207. String s;
  208. for (int i = 0; i < fillType.gradient->getNumColours(); ++i)
  209. s << " " << fillType.gradient->getColourPosition (i)
  210. << " " << String::toHexString ((int) fillType.gradient->getColour(i).getARGB());
  211. v.setProperty (colours, s.trimStart(), undoManager);
  212. v.removeProperty (colour, undoManager);
  213. }
  214. else if (fillType.isTiledImage())
  215. {
  216. v.setProperty (type, "image", undoManager);
  217. jassertfalse; //xxx todo
  218. v.removeProperty (x1, undoManager);
  219. v.removeProperty (x2, undoManager);
  220. v.removeProperty (y1, undoManager);
  221. v.removeProperty (y2, undoManager);
  222. v.removeProperty (radial, undoManager);
  223. v.removeProperty (colours, undoManager);
  224. v.removeProperty (colour, undoManager);
  225. }
  226. else
  227. {
  228. jassertfalse;
  229. }
  230. }
  231. END_JUCE_NAMESPACE