263 lines
8.0 KiB
C++
263 lines
8.0 KiB
C++
|
/*
|
||
|
==============================================================================
|
||
|
|
||
|
This file is part of the JUCE library.
|
||
|
Copyright (c) 2020 - Raw Material Software Limited
|
||
|
|
||
|
JUCE is an open source library subject to commercial or open-source
|
||
|
licensing.
|
||
|
|
||
|
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||
|
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||
|
|
||
|
End User License Agreement: www.juce.com/juce-6-licence
|
||
|
Privacy Policy: www.juce.com/juce-privacy-policy
|
||
|
|
||
|
Or: You may also use this code under the terms of the GPL v3 (see
|
||
|
www.gnu.org/licenses).
|
||
|
|
||
|
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||
|
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||
|
DISCLAIMED.
|
||
|
|
||
|
==============================================================================
|
||
|
*/
|
||
|
|
||
|
namespace juce
|
||
|
{
|
||
|
|
||
|
RelativePointPath::RelativePointPath()
|
||
|
: usesNonZeroWinding (true),
|
||
|
containsDynamicPoints (false)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
RelativePointPath::RelativePointPath (const RelativePointPath& other)
|
||
|
: usesNonZeroWinding (true),
|
||
|
containsDynamicPoints (false)
|
||
|
{
|
||
|
for (int i = 0; i < other.elements.size(); ++i)
|
||
|
elements.add (other.elements.getUnchecked(i)->clone());
|
||
|
}
|
||
|
|
||
|
RelativePointPath::RelativePointPath (const Path& path)
|
||
|
: usesNonZeroWinding (path.isUsingNonZeroWinding()),
|
||
|
containsDynamicPoints (false)
|
||
|
{
|
||
|
for (Path::Iterator i (path); i.next();)
|
||
|
{
|
||
|
switch (i.elementType)
|
||
|
{
|
||
|
case Path::Iterator::startNewSubPath: elements.add (new StartSubPath (RelativePoint (i.x1, i.y1))); break;
|
||
|
case Path::Iterator::lineTo: elements.add (new LineTo (RelativePoint (i.x1, i.y1))); break;
|
||
|
case Path::Iterator::quadraticTo: elements.add (new QuadraticTo (RelativePoint (i.x1, i.y1), RelativePoint (i.x2, i.y2))); break;
|
||
|
case Path::Iterator::cubicTo: elements.add (new CubicTo (RelativePoint (i.x1, i.y1), RelativePoint (i.x2, i.y2), RelativePoint (i.x3, i.y3))); break;
|
||
|
case Path::Iterator::closePath: elements.add (new CloseSubPath()); break;
|
||
|
default: jassertfalse; break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RelativePointPath::~RelativePointPath()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
bool RelativePointPath::operator== (const RelativePointPath& other) const noexcept
|
||
|
{
|
||
|
if (elements.size() != other.elements.size()
|
||
|
|| usesNonZeroWinding != other.usesNonZeroWinding
|
||
|
|| containsDynamicPoints != other.containsDynamicPoints)
|
||
|
return false;
|
||
|
|
||
|
for (int i = 0; i < elements.size(); ++i)
|
||
|
{
|
||
|
ElementBase* const e1 = elements.getUnchecked(i);
|
||
|
ElementBase* const e2 = other.elements.getUnchecked(i);
|
||
|
|
||
|
if (e1->type != e2->type)
|
||
|
return false;
|
||
|
|
||
|
int numPoints1, numPoints2;
|
||
|
const RelativePoint* const points1 = e1->getControlPoints (numPoints1);
|
||
|
const RelativePoint* const points2 = e2->getControlPoints (numPoints2);
|
||
|
|
||
|
jassert (numPoints1 == numPoints2);
|
||
|
|
||
|
for (int j = numPoints1; --j >= 0;)
|
||
|
if (points1[j] != points2[j])
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool RelativePointPath::operator!= (const RelativePointPath& other) const noexcept
|
||
|
{
|
||
|
return ! operator== (other);
|
||
|
}
|
||
|
|
||
|
void RelativePointPath::swapWith (RelativePointPath& other) noexcept
|
||
|
{
|
||
|
elements.swapWith (other.elements);
|
||
|
std::swap (usesNonZeroWinding, other.usesNonZeroWinding);
|
||
|
std::swap (containsDynamicPoints, other.containsDynamicPoints);
|
||
|
}
|
||
|
|
||
|
void RelativePointPath::createPath (Path& path, Expression::Scope* scope) const
|
||
|
{
|
||
|
for (int i = 0; i < elements.size(); ++i)
|
||
|
elements.getUnchecked(i)->addToPath (path, scope);
|
||
|
}
|
||
|
|
||
|
bool RelativePointPath::containsAnyDynamicPoints() const
|
||
|
{
|
||
|
return containsDynamicPoints;
|
||
|
}
|
||
|
|
||
|
void RelativePointPath::addElement (ElementBase* newElement)
|
||
|
{
|
||
|
if (newElement != nullptr)
|
||
|
{
|
||
|
elements.add (newElement);
|
||
|
containsDynamicPoints = containsDynamicPoints || newElement->isDynamic();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
RelativePointPath::ElementBase::ElementBase (const ElementType type_) : type (type_)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
bool RelativePointPath::ElementBase::isDynamic()
|
||
|
{
|
||
|
int numPoints;
|
||
|
const RelativePoint* const points = getControlPoints (numPoints);
|
||
|
|
||
|
for (int i = numPoints; --i >= 0;)
|
||
|
if (points[i].isDynamic())
|
||
|
return true;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
RelativePointPath::StartSubPath::StartSubPath (const RelativePoint& pos)
|
||
|
: ElementBase (startSubPathElement), startPos (pos)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void RelativePointPath::StartSubPath::addToPath (Path& path, Expression::Scope* scope) const
|
||
|
{
|
||
|
path.startNewSubPath (startPos.resolve (scope));
|
||
|
}
|
||
|
|
||
|
RelativePoint* RelativePointPath::StartSubPath::getControlPoints (int& numPoints)
|
||
|
{
|
||
|
numPoints = 1;
|
||
|
return &startPos;
|
||
|
}
|
||
|
|
||
|
RelativePointPath::ElementBase* RelativePointPath::StartSubPath::clone() const
|
||
|
{
|
||
|
return new StartSubPath (startPos);
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
RelativePointPath::CloseSubPath::CloseSubPath()
|
||
|
: ElementBase (closeSubPathElement)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void RelativePointPath::CloseSubPath::addToPath (Path& path, Expression::Scope*) const
|
||
|
{
|
||
|
path.closeSubPath();
|
||
|
}
|
||
|
|
||
|
RelativePoint* RelativePointPath::CloseSubPath::getControlPoints (int& numPoints)
|
||
|
{
|
||
|
numPoints = 0;
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
RelativePointPath::ElementBase* RelativePointPath::CloseSubPath::clone() const
|
||
|
{
|
||
|
return new CloseSubPath();
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
RelativePointPath::LineTo::LineTo (const RelativePoint& endPoint_)
|
||
|
: ElementBase (lineToElement), endPoint (endPoint_)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void RelativePointPath::LineTo::addToPath (Path& path, Expression::Scope* scope) const
|
||
|
{
|
||
|
path.lineTo (endPoint.resolve (scope));
|
||
|
}
|
||
|
|
||
|
RelativePoint* RelativePointPath::LineTo::getControlPoints (int& numPoints)
|
||
|
{
|
||
|
numPoints = 1;
|
||
|
return &endPoint;
|
||
|
}
|
||
|
|
||
|
RelativePointPath::ElementBase* RelativePointPath::LineTo::clone() const
|
||
|
{
|
||
|
return new LineTo (endPoint);
|
||
|
}
|
||
|
|
||
|
//==============================================================================
|
||
|
RelativePointPath::QuadraticTo::QuadraticTo (const RelativePoint& controlPoint, const RelativePoint& endPoint)
|
||
|
: ElementBase (quadraticToElement)
|
||
|
{
|
||
|
controlPoints[0] = controlPoint;
|
||
|
controlPoints[1] = endPoint;
|
||
|
}
|
||
|
|
||
|
void RelativePointPath::QuadraticTo::addToPath (Path& path, Expression::Scope* scope) const
|
||
|
{
|
||
|
path.quadraticTo (controlPoints[0].resolve (scope),
|
||
|
controlPoints[1].resolve (scope));
|
||
|
}
|
||
|
|
||
|
RelativePoint* RelativePointPath::QuadraticTo::getControlPoints (int& numPoints)
|
||
|
{
|
||
|
numPoints = 2;
|
||
|
return controlPoints;
|
||
|
}
|
||
|
|
||
|
RelativePointPath::ElementBase* RelativePointPath::QuadraticTo::clone() const
|
||
|
{
|
||
|
return new QuadraticTo (controlPoints[0], controlPoints[1]);
|
||
|
}
|
||
|
|
||
|
|
||
|
//==============================================================================
|
||
|
RelativePointPath::CubicTo::CubicTo (const RelativePoint& controlPoint1, const RelativePoint& controlPoint2, const RelativePoint& endPoint)
|
||
|
: ElementBase (cubicToElement)
|
||
|
{
|
||
|
controlPoints[0] = controlPoint1;
|
||
|
controlPoints[1] = controlPoint2;
|
||
|
controlPoints[2] = endPoint;
|
||
|
}
|
||
|
|
||
|
void RelativePointPath::CubicTo::addToPath (Path& path, Expression::Scope* scope) const
|
||
|
{
|
||
|
path.cubicTo (controlPoints[0].resolve (scope),
|
||
|
controlPoints[1].resolve (scope),
|
||
|
controlPoints[2].resolve (scope));
|
||
|
}
|
||
|
|
||
|
RelativePoint* RelativePointPath::CubicTo::getControlPoints (int& numPoints)
|
||
|
{
|
||
|
numPoints = 3;
|
||
|
return controlPoints;
|
||
|
}
|
||
|
|
||
|
RelativePointPath::ElementBase* RelativePointPath::CubicTo::clone() const
|
||
|
{
|
||
|
return new CubicTo (controlPoints[0], controlPoints[1], controlPoints[2]);
|
||
|
}
|
||
|
|
||
|
} // namespace juce
|