|
- /*
- ==============================================================================
-
- 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_DrawableShape.h"
- #include "juce_DrawableComposite.h"
-
-
- //==============================================================================
- DrawableShape::DrawableShape()
- : strokeType (0.0f),
- mainFill (Colours::black),
- strokeFill (Colours::black)
- {
- }
-
- DrawableShape::DrawableShape (const DrawableShape& other)
- : strokeType (other.strokeType),
- mainFill (other.mainFill),
- strokeFill (other.strokeFill)
- {
- }
-
- DrawableShape::~DrawableShape()
- {
- }
-
- void DrawableShape::setFill (const FillType& newFill)
- {
- mainFill = newFill;
- }
-
- void DrawableShape::setStrokeFill (const FillType& newFill)
- {
- strokeFill = newFill;
- }
-
- void DrawableShape::setStrokeType (const PathStrokeType& newStrokeType)
- {
- strokeType = newStrokeType;
- strokeChanged();
- }
-
- void DrawableShape::setStrokeThickness (const float newThickness)
- {
- setStrokeType (PathStrokeType (newThickness, strokeType.getJointStyle(), strokeType.getEndStyle()));
- }
-
- bool DrawableShape::isStrokeVisible() const throw()
- {
- return strokeType.getStrokeThickness() > 0.0f && ! strokeFill.isInvisible();
- }
-
- bool DrawableShape::refreshFillTypes (const FillAndStrokeState& newState,
- Expression::EvaluationContext* /*nameFinder*/,
- ComponentBuilder::ImageProvider* imageProvider)
- {
- bool hasChanged = false;
-
- {
- const FillType f (newState.getMainFill (getParent(), imageProvider));
-
- if (mainFill != f)
- {
- hasChanged = true;
- mainFill = f;
- }
- }
-
- {
- const FillType f (newState.getStrokeFill (getParent(), imageProvider));
-
- if (strokeFill != f)
- {
- hasChanged = true;
- strokeFill = f;
- }
- }
-
- return hasChanged;
- }
-
- void DrawableShape::writeTo (FillAndStrokeState& state, ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager) const
- {
- state.setMainFill (mainFill, 0, 0, 0, imageProvider, undoManager);
- state.setStrokeFill (strokeFill, 0, 0, 0, imageProvider, undoManager);
- state.setStrokeType (strokeType, undoManager);
- }
-
- //==============================================================================
- void DrawableShape::paint (Graphics& g)
- {
- transformContextToCorrectOrigin (g);
-
- g.setFillType (mainFill);
- g.fillPath (path);
-
- if (isStrokeVisible())
- {
- g.setFillType (strokeFill);
- g.fillPath (strokePath);
- }
- }
-
- void DrawableShape::pathChanged()
- {
- rebuildPath (path);
- strokeChanged();
- }
-
- void DrawableShape::strokeChanged()
- {
- strokePath.clear();
- strokeType.createStrokedPath (strokePath, path, AffineTransform::identity, 4.0f);
-
- setBoundsToEnclose (getDrawableBounds());
- repaint();
- }
-
- const Rectangle<float> DrawableShape::getDrawableBounds() const
- {
- if (isStrokeVisible())
- return strokePath.getBounds();
- else
- return path.getBounds();
- }
-
- bool DrawableShape::hitTest (int x, int y) const
- {
- const float globalX = (float) (x - originRelativeToComponent.getX());
- const float globalY = (float) (y - originRelativeToComponent.getY());
-
- return path.contains (globalX, globalY)
- || (isStrokeVisible() && strokePath.contains (globalX, globalY));
- }
-
- //==============================================================================
- const Identifier DrawableShape::FillAndStrokeState::type ("type");
- const Identifier DrawableShape::FillAndStrokeState::colour ("colour");
- const Identifier DrawableShape::FillAndStrokeState::colours ("colours");
- const Identifier DrawableShape::FillAndStrokeState::fill ("Fill");
- const Identifier DrawableShape::FillAndStrokeState::stroke ("Stroke");
- const Identifier DrawableShape::FillAndStrokeState::path ("Path");
- const Identifier DrawableShape::FillAndStrokeState::jointStyle ("jointStyle");
- const Identifier DrawableShape::FillAndStrokeState::capStyle ("capStyle");
- const Identifier DrawableShape::FillAndStrokeState::strokeWidth ("strokeWidth");
- const Identifier DrawableShape::FillAndStrokeState::gradientPoint1 ("point1");
- const Identifier DrawableShape::FillAndStrokeState::gradientPoint2 ("point2");
- const Identifier DrawableShape::FillAndStrokeState::gradientPoint3 ("point3");
- const Identifier DrawableShape::FillAndStrokeState::radial ("radial");
- const Identifier DrawableShape::FillAndStrokeState::imageId ("imageId");
- const Identifier DrawableShape::FillAndStrokeState::imageOpacity ("imageOpacity");
-
- DrawableShape::FillAndStrokeState::FillAndStrokeState (const ValueTree& state_)
- : Drawable::ValueTreeWrapperBase (state_)
- {
- }
-
- const FillType DrawableShape::FillAndStrokeState::getMainFill (Expression::EvaluationContext* nameFinder,
- ComponentBuilder::ImageProvider* imageProvider) const
- {
- return readFillType (state.getChildWithName (fill), 0, 0, 0, nameFinder, imageProvider);
- }
-
- ValueTree DrawableShape::FillAndStrokeState::getMainFillState()
- {
- ValueTree v (state.getChildWithName (fill));
- if (v.isValid())
- return v;
-
- setMainFill (Colours::black, 0, 0, 0, 0, 0);
- return getMainFillState();
- }
-
- void DrawableShape::FillAndStrokeState::setMainFill (const FillType& newFill, const RelativePoint* gp1, const RelativePoint* gp2,
- const RelativePoint* gp3, ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager)
- {
- ValueTree v (state.getOrCreateChildWithName (fill, undoManager));
- writeFillType (v, newFill, gp1, gp2, gp3, imageProvider, undoManager);
- }
-
- const FillType DrawableShape::FillAndStrokeState::getStrokeFill (Expression::EvaluationContext* nameFinder,
- ComponentBuilder::ImageProvider* imageProvider) const
- {
- return readFillType (state.getChildWithName (stroke), 0, 0, 0, nameFinder, imageProvider);
- }
-
- ValueTree DrawableShape::FillAndStrokeState::getStrokeFillState()
- {
- ValueTree v (state.getChildWithName (stroke));
- if (v.isValid())
- return v;
-
- setStrokeFill (Colours::black, 0, 0, 0, 0, 0);
- return getStrokeFillState();
- }
-
- void DrawableShape::FillAndStrokeState::setStrokeFill (const FillType& newFill, const RelativePoint* gp1, const RelativePoint* gp2,
- const RelativePoint* gp3, ComponentBuilder::ImageProvider* imageProvider, UndoManager* undoManager)
- {
- ValueTree v (state.getOrCreateChildWithName (stroke, undoManager));
- writeFillType (v, newFill, gp1, gp2, gp3, imageProvider, undoManager);
- }
-
- const PathStrokeType DrawableShape::FillAndStrokeState::getStrokeType() const
- {
- const String jointStyleString (state [jointStyle].toString());
- const String capStyleString (state [capStyle].toString());
-
- return PathStrokeType (state [strokeWidth],
- jointStyleString == "curved" ? PathStrokeType::curved
- : (jointStyleString == "bevel" ? PathStrokeType::beveled
- : PathStrokeType::mitered),
- capStyleString == "square" ? PathStrokeType::square
- : (capStyleString == "round" ? PathStrokeType::rounded
- : PathStrokeType::butt));
- }
-
- void DrawableShape::FillAndStrokeState::setStrokeType (const PathStrokeType& newStrokeType, UndoManager* undoManager)
- {
- state.setProperty (strokeWidth, (double) newStrokeType.getStrokeThickness(), undoManager);
- state.setProperty (jointStyle, newStrokeType.getJointStyle() == PathStrokeType::mitered
- ? "miter" : (newStrokeType.getJointStyle() == PathStrokeType::curved ? "curved" : "bevel"), undoManager);
- state.setProperty (capStyle, newStrokeType.getEndStyle() == PathStrokeType::butt
- ? "butt" : (newStrokeType.getEndStyle() == PathStrokeType::square ? "square" : "round"), undoManager);
- }
-
- const FillType DrawableShape::FillAndStrokeState::readFillType (const ValueTree& v, RelativePoint* const gp1, RelativePoint* const gp2, RelativePoint* const gp3,
- Expression::EvaluationContext* const nameFinder, ComponentBuilder::ImageProvider* imageProvider)
- {
- 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]), p3 (v [gradientPoint3]);
-
- ColourGradient g;
-
- if (gp1 != 0) *gp1 = p1;
- if (gp2 != 0) *gp2 = p2;
- if (gp3 != 0) *gp3 = p3;
-
- 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()));
-
- FillType fillType (g);
-
- if (g.isRadial)
- {
- const Point<float> point3 (p3.resolve (nameFinder));
- const Point<float> point3Source (g.point1.getX() + g.point2.getY() - g.point1.getY(),
- g.point1.getY() + g.point1.getX() - g.point2.getX());
-
- fillType.transform = AffineTransform::fromTargetPoints (g.point1.getX(), g.point1.getY(), g.point1.getX(), g.point1.getY(),
- g.point2.getX(), g.point2.getY(), g.point2.getX(), g.point2.getY(),
- point3Source.getX(), point3Source.getY(), point3.getX(), point3.getY());
- }
-
- return fillType;
- }
- else if (newType == "image")
- {
- Image im;
- if (imageProvider != 0)
- im = imageProvider->getImageForIdentifier (v[imageId]);
-
- FillType f (im, AffineTransform::identity);
- f.setOpacity ((float) v.getProperty (imageOpacity, 1.0f));
- return f;
- }
-
- jassert (! v.isValid());
- return FillType();
- }
-
- namespace DrawableShapeHelpers
- {
- const Point<float> calcThirdGradientPoint (const FillType& fillType)
- {
- const ColourGradient& g = *fillType.gradient;
- const Point<float> point3Source (g.point1.getX() + g.point2.getY() - g.point1.getY(),
- g.point1.getY() + g.point1.getX() - g.point2.getX());
-
- return point3Source.transformedBy (fillType.transform);
- }
- }
-
- void DrawableShape::FillAndStrokeState::writeFillType (ValueTree& v, const FillType& fillType,
- const RelativePoint* const gp1, const RelativePoint* const gp2, const RelativePoint* gp3,
- ComponentBuilder::ImageProvider* imageProvider, 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 (gradientPoint3, gp3 != 0 ? gp3->toString() : DrawableShapeHelpers::calcThirdGradientPoint (fillType).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);
-
- if (imageProvider != 0)
- v.setProperty (imageId, imageProvider->getIdentifierForImage (fillType.image), undoManager);
-
- if (fillType.getOpacity() < 1.0f)
- v.setProperty (imageOpacity, fillType.getOpacity(), undoManager);
- else
- v.removeProperty (imageOpacity, undoManager);
- }
- else
- {
- jassertfalse;
- }
- }
-
- END_JUCE_NAMESPACE
|