mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-11 23:54:18 +00:00
269 lines
8.9 KiB
C++
269 lines
8.9 KiB
C++
/*
|
|
==============================================================================
|
|
|
|
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
|
Copyright 2004-10 by Raw Material Software Ltd.
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
JUCE can be redistributed and/or modified under the terms of the GNU General
|
|
Public License (Version 2), as published by the Free Software Foundation.
|
|
A copy of the license is included in the JUCE distribution, or can be found
|
|
online at www.gnu.org/licenses.
|
|
|
|
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
To release a closed-source product which uses JUCE, commercial licenses are
|
|
available: visit www.rawmaterialsoftware.com/juce for more information.
|
|
|
|
==============================================================================
|
|
*/
|
|
|
|
#include "../../../core/juce_StandardHeader.h"
|
|
|
|
BEGIN_JUCE_NAMESPACE
|
|
|
|
#include "juce_Drawable.h"
|
|
#include "juce_DrawableComposite.h"
|
|
#include "juce_DrawablePath.h"
|
|
#include "juce_DrawableImage.h"
|
|
#include "juce_DrawableText.h"
|
|
#include "../imaging/juce_ImageFileFormat.h"
|
|
#include "../../../text/juce_XmlDocument.h"
|
|
#include "../../../io/files/juce_FileInputStream.h"
|
|
|
|
|
|
//==============================================================================
|
|
Drawable::RenderingContext::RenderingContext (Graphics& g_,
|
|
const AffineTransform& transform_,
|
|
const float opacity_) throw()
|
|
: g (g_),
|
|
transform (transform_),
|
|
opacity (opacity_)
|
|
{
|
|
}
|
|
|
|
//==============================================================================
|
|
Drawable::Drawable()
|
|
: parent (0)
|
|
{
|
|
}
|
|
|
|
Drawable::~Drawable()
|
|
{
|
|
}
|
|
|
|
void Drawable::draw (Graphics& g, const float opacity, const AffineTransform& transform) const
|
|
{
|
|
render (RenderingContext (g, transform, opacity));
|
|
}
|
|
|
|
void Drawable::drawAt (Graphics& g, const float x, const float y, const float opacity) const
|
|
{
|
|
draw (g, opacity, AffineTransform::translation (x, y));
|
|
}
|
|
|
|
void Drawable::drawWithin (Graphics& g,
|
|
const int destX,
|
|
const int destY,
|
|
const int destW,
|
|
const int destH,
|
|
const RectanglePlacement& placement,
|
|
const float opacity) const
|
|
{
|
|
if (destW > 0 && destH > 0)
|
|
{
|
|
Rectangle<float> bounds (getBounds());
|
|
|
|
draw (g, opacity,
|
|
placement.getTransformToFit (bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(),
|
|
(float) destX, (float) destY,
|
|
(float) destW, (float) destH));
|
|
}
|
|
}
|
|
|
|
//==============================================================================
|
|
Drawable* Drawable::createFromImageData (const void* data, const size_t numBytes)
|
|
{
|
|
Drawable* result = 0;
|
|
|
|
Image image (ImageFileFormat::loadFrom (data, (int) numBytes));
|
|
|
|
if (image.isValid())
|
|
{
|
|
DrawableImage* const di = new DrawableImage();
|
|
di->setImage (image);
|
|
result = di;
|
|
}
|
|
else
|
|
{
|
|
const String asString (String::createStringFromData (data, (int) numBytes));
|
|
|
|
XmlDocument doc (asString);
|
|
ScopedPointer <XmlElement> outer (doc.getDocumentElement (true));
|
|
|
|
if (outer != 0 && outer->hasTagName ("svg"))
|
|
{
|
|
ScopedPointer <XmlElement> svg (doc.getDocumentElement());
|
|
|
|
if (svg != 0)
|
|
result = Drawable::createFromSVG (*svg);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
Drawable* Drawable::createFromImageDataStream (InputStream& dataSource)
|
|
{
|
|
MemoryBlock mb;
|
|
dataSource.readIntoMemoryBlock (mb);
|
|
|
|
return createFromImageData (mb.getData(), mb.getSize());
|
|
}
|
|
|
|
Drawable* Drawable::createFromImageFile (const File& file)
|
|
{
|
|
const ScopedPointer <FileInputStream> fin (file.createInputStream());
|
|
|
|
return fin != 0 ? createFromImageDataStream (*fin) : 0;
|
|
}
|
|
|
|
//==============================================================================
|
|
Drawable* Drawable::createFromValueTree (const ValueTree& tree, ImageProvider* imageProvider)
|
|
{
|
|
const Identifier type (tree.getType());
|
|
|
|
Drawable* d = 0;
|
|
if (type == DrawablePath::valueTreeType)
|
|
d = new DrawablePath();
|
|
else if (type == DrawableComposite::valueTreeType)
|
|
d = new DrawableComposite();
|
|
else if (type == DrawableImage::valueTreeType)
|
|
d = new DrawableImage();
|
|
else if (type == DrawableText::valueTreeType)
|
|
d = new DrawableText();
|
|
|
|
if (d != 0)
|
|
d->refreshFromValueTree (tree, imageProvider);
|
|
|
|
return d;
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
const Identifier Drawable::ValueTreeWrapperBase::idProperty ("id");
|
|
const Identifier Drawable::ValueTreeWrapperBase::type ("type");
|
|
const Identifier Drawable::ValueTreeWrapperBase::gradientPoint1 ("point1");
|
|
const Identifier Drawable::ValueTreeWrapperBase::gradientPoint2 ("point2");
|
|
const Identifier Drawable::ValueTreeWrapperBase::colour ("colour");
|
|
const Identifier Drawable::ValueTreeWrapperBase::radial ("radial");
|
|
const Identifier Drawable::ValueTreeWrapperBase::colours ("colours");
|
|
|
|
Drawable::ValueTreeWrapperBase::ValueTreeWrapperBase (const ValueTree& state_)
|
|
: state (state_)
|
|
{
|
|
}
|
|
|
|
Drawable::ValueTreeWrapperBase::~ValueTreeWrapperBase()
|
|
{
|
|
}
|
|
|
|
const String Drawable::ValueTreeWrapperBase::getID() const
|
|
{
|
|
return state [idProperty];
|
|
}
|
|
|
|
void Drawable::ValueTreeWrapperBase::setID (const String& newID, UndoManager* undoManager)
|
|
{
|
|
if (newID.isEmpty())
|
|
state.removeProperty (idProperty, undoManager);
|
|
else
|
|
state.setProperty (idProperty, newID, undoManager);
|
|
}
|
|
|
|
const FillType Drawable::ValueTreeWrapperBase::readFillType (const ValueTree& v, RelativePoint* gp1, RelativePoint* gp2,
|
|
RelativeCoordinate::NamedCoordinateFinder* nameFinder)
|
|
{
|
|
const String newType (v[type].toString());
|
|
|
|
if (newType == "solid")
|
|
{
|
|
const String colourString (v [colour].toString());
|
|
return FillType (Colour (colourString.isEmpty() ? (uint32) 0xff000000
|
|
: (uint32) colourString.getHexValue32()));
|
|
}
|
|
else if (newType == "gradient")
|
|
{
|
|
RelativePoint p1 (v [gradientPoint1]), p2 (v [gradientPoint2]);
|
|
|
|
ColourGradient g;
|
|
|
|
if (gp1 != 0)
|
|
*gp1 = p1;
|
|
if (gp2 != 0)
|
|
*gp2 = p2;
|
|
|
|
g.point1 = p1.resolve (nameFinder);
|
|
g.point2 = p2.resolve (nameFinder);
|
|
g.isRadial = v[radial];
|
|
|
|
StringArray colourSteps;
|
|
colourSteps.addTokens (v[colours].toString(), false);
|
|
|
|
for (int i = 0; i < colourSteps.size() / 2; ++i)
|
|
g.addColour (colourSteps[i * 2].getDoubleValue(),
|
|
Colour ((uint32) colourSteps[i * 2 + 1].getHexValue32()));
|
|
|
|
return FillType (g);
|
|
}
|
|
else if (newType == "image")
|
|
{
|
|
jassertfalse; //xxx todo
|
|
}
|
|
|
|
jassertfalse;
|
|
return FillType();
|
|
}
|
|
|
|
void Drawable::ValueTreeWrapperBase::writeFillType (ValueTree& v, const FillType& fillType,
|
|
const RelativePoint* gp1, const RelativePoint* gp2,
|
|
UndoManager* const undoManager)
|
|
{
|
|
if (fillType.isColour())
|
|
{
|
|
v.setProperty (type, "solid", undoManager);
|
|
v.setProperty (colour, String::toHexString ((int) fillType.colour.getARGB()), undoManager);
|
|
}
|
|
else if (fillType.isGradient())
|
|
{
|
|
v.setProperty (type, "gradient", undoManager);
|
|
v.setProperty (gradientPoint1, gp1 != 0 ? gp1->toString() : fillType.gradient->point1.toString(), undoManager);
|
|
v.setProperty (gradientPoint2, gp2 != 0 ? gp2->toString() : fillType.gradient->point2.toString(), undoManager);
|
|
v.setProperty (radial, fillType.gradient->isRadial, undoManager);
|
|
|
|
String s;
|
|
for (int i = 0; i < fillType.gradient->getNumColours(); ++i)
|
|
s << " " << fillType.gradient->getColourPosition (i)
|
|
<< " " << String::toHexString ((int) fillType.gradient->getColour(i).getARGB());
|
|
|
|
v.setProperty (colours, s.trimStart(), undoManager);
|
|
}
|
|
else if (fillType.isTiledImage())
|
|
{
|
|
v.setProperty (type, "image", undoManager);
|
|
|
|
jassertfalse; //xxx todo
|
|
}
|
|
else
|
|
{
|
|
jassertfalse;
|
|
}
|
|
}
|
|
|
|
|
|
END_JUCE_NAMESPACE
|