mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Simplified the Path class by making it use an Array for starage.
This commit is contained in:
parent
c0223ae2bc
commit
5e9267e5d8
5 changed files with 179 additions and 259 deletions
|
|
@ -36,7 +36,7 @@ EdgeTable::EdgeTable (Rectangle<int> area, const Path& path, const AffineTransfo
|
|||
// for a given path, such that it's big enough to mostly avoid remapping, but also
|
||||
// not so big that it's wasteful for simple paths.
|
||||
maxEdgesPerLine (jmax (juce_edgeTableDefaultEdgesPerLine / 2,
|
||||
4 * (int) std::sqrt (path.numElements))),
|
||||
4 * (int) std::sqrt (path.data.size()))),
|
||||
lineStrideElements (maxEdgesPerLine * 2 + 1)
|
||||
{
|
||||
allocate();
|
||||
|
|
|
|||
|
|
@ -137,37 +137,26 @@ Path::~Path()
|
|||
}
|
||||
|
||||
Path::Path (const Path& other)
|
||||
: numElements (other.numElements),
|
||||
: data (other.data),
|
||||
bounds (other.bounds),
|
||||
useNonZeroWinding (other.useNonZeroWinding)
|
||||
{
|
||||
if (numElements > 0)
|
||||
{
|
||||
data.setAllocatedSize ((int) numElements);
|
||||
memcpy (data.elements, other.data.elements, numElements * sizeof (float));
|
||||
}
|
||||
}
|
||||
|
||||
Path& Path::operator= (const Path& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
data.ensureAllocatedSize ((int) other.numElements);
|
||||
|
||||
numElements = other.numElements;
|
||||
data = other.data;
|
||||
bounds = other.bounds;
|
||||
useNonZeroWinding = other.useNonZeroWinding;
|
||||
|
||||
if (numElements > 0)
|
||||
memcpy (data.elements, other.data.elements, numElements * sizeof (float));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Path::Path (Path&& other) noexcept
|
||||
: data (static_cast<ArrayAllocationBase <float, DummyCriticalSection>&&> (other.data)),
|
||||
numElements (other.numElements),
|
||||
: data (static_cast<Array<float>&&> (other.data)),
|
||||
bounds (other.bounds),
|
||||
useNonZeroWinding (other.useNonZeroWinding)
|
||||
{
|
||||
|
|
@ -175,40 +164,24 @@ Path::Path (Path&& other) noexcept
|
|||
|
||||
Path& Path::operator= (Path&& other) noexcept
|
||||
{
|
||||
data = static_cast<ArrayAllocationBase <float, DummyCriticalSection>&&> (other.data);
|
||||
numElements = other.numElements;
|
||||
data = static_cast<Array<float>&&> (other.data);
|
||||
bounds = other.bounds;
|
||||
useNonZeroWinding = other.useNonZeroWinding;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Path::operator== (const Path& other) const noexcept
|
||||
{
|
||||
return ! operator!= (other);
|
||||
}
|
||||
|
||||
bool Path::operator!= (const Path& other) const noexcept
|
||||
{
|
||||
if (numElements != other.numElements || useNonZeroWinding != other.useNonZeroWinding)
|
||||
return true;
|
||||
|
||||
for (size_t i = 0; i < numElements; ++i)
|
||||
if (data.elements[i] != other.data.elements[i])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
bool Path::operator== (const Path& other) const noexcept { return useNonZeroWinding == other.useNonZeroWinding && data == other.data; }
|
||||
bool Path::operator!= (const Path& other) const noexcept { return ! operator== (other); }
|
||||
|
||||
void Path::clear() noexcept
|
||||
{
|
||||
numElements = 0;
|
||||
data.clearQuick();
|
||||
bounds.reset();
|
||||
}
|
||||
|
||||
void Path::swapWithPath (Path& other) noexcept
|
||||
{
|
||||
data.swapWith (other.data);
|
||||
std::swap (numElements, other.numElements);
|
||||
std::swap (bounds.pathXMin, other.bounds.pathXMin);
|
||||
std::swap (bounds.pathXMax, other.bounds.pathXMax);
|
||||
std::swap (bounds.pathYMin, other.bounds.pathYMin);
|
||||
|
|
@ -230,11 +203,9 @@ void Path::scaleToFit (float x, float y, float w, float h, bool preserveProporti
|
|||
//==============================================================================
|
||||
bool Path::isEmpty() const noexcept
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
while (i < numElements)
|
||||
for (auto i = data.begin(), e = data.end(); i != e; ++i)
|
||||
{
|
||||
auto type = data.elements[i++];
|
||||
auto type = *i;
|
||||
|
||||
if (isMarker (type, moveMarker))
|
||||
{
|
||||
|
|
@ -264,23 +235,19 @@ Rectangle<float> Path::getBoundsTransformed (const AffineTransform& transform) c
|
|||
//==============================================================================
|
||||
void Path::preallocateSpace (int numExtraCoordsToMakeSpaceFor)
|
||||
{
|
||||
data.ensureAllocatedSize ((int) numElements + numExtraCoordsToMakeSpaceFor);
|
||||
data.ensureStorageAllocated (data.size() + numExtraCoordsToMakeSpaceFor);
|
||||
}
|
||||
|
||||
void Path::startNewSubPath (const float x, const float y)
|
||||
{
|
||||
JUCE_CHECK_COORDS_ARE_VALID (x, y);
|
||||
|
||||
if (numElements == 0)
|
||||
if (data.isEmpty())
|
||||
bounds.reset (x, y);
|
||||
else
|
||||
bounds.extend (x, y);
|
||||
|
||||
preallocateSpace (3);
|
||||
|
||||
data.elements[numElements++] = moveMarker;
|
||||
data.elements[numElements++] = x;
|
||||
data.elements[numElements++] = y;
|
||||
data.add (moveMarker, x, y);
|
||||
}
|
||||
|
||||
void Path::startNewSubPath (Point<float> start)
|
||||
|
|
@ -292,15 +259,10 @@ void Path::lineTo (const float x, const float y)
|
|||
{
|
||||
JUCE_CHECK_COORDS_ARE_VALID (x, y);
|
||||
|
||||
if (numElements == 0)
|
||||
if (data.isEmpty())
|
||||
startNewSubPath (0, 0);
|
||||
|
||||
preallocateSpace (3);
|
||||
|
||||
data.elements[numElements++] = lineMarker;
|
||||
data.elements[numElements++] = x;
|
||||
data.elements[numElements++] = y;
|
||||
|
||||
data.add (lineMarker, x, y);
|
||||
bounds.extend (x, y);
|
||||
}
|
||||
|
||||
|
|
@ -315,17 +277,10 @@ void Path::quadraticTo (const float x1, const float y1,
|
|||
JUCE_CHECK_COORDS_ARE_VALID (x1, y1);
|
||||
JUCE_CHECK_COORDS_ARE_VALID (x2, y2);
|
||||
|
||||
if (numElements == 0)
|
||||
if (data.isEmpty())
|
||||
startNewSubPath (0, 0);
|
||||
|
||||
preallocateSpace (5);
|
||||
|
||||
data.elements[numElements++] = quadMarker;
|
||||
data.elements[numElements++] = x1;
|
||||
data.elements[numElements++] = y1;
|
||||
data.elements[numElements++] = x2;
|
||||
data.elements[numElements++] = y2;
|
||||
|
||||
data.add (quadMarker, x1, y1, x2, y2);
|
||||
bounds.extend (x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
|
|
@ -343,19 +298,10 @@ void Path::cubicTo (const float x1, const float y1,
|
|||
JUCE_CHECK_COORDS_ARE_VALID (x2, y2);
|
||||
JUCE_CHECK_COORDS_ARE_VALID (x3, y3);
|
||||
|
||||
if (numElements == 0)
|
||||
if (data.isEmpty())
|
||||
startNewSubPath (0, 0);
|
||||
|
||||
preallocateSpace (7);
|
||||
|
||||
data.elements[numElements++] = cubicMarker;
|
||||
data.elements[numElements++] = x1;
|
||||
data.elements[numElements++] = y1;
|
||||
data.elements[numElements++] = x2;
|
||||
data.elements[numElements++] = y2;
|
||||
data.elements[numElements++] = x3;
|
||||
data.elements[numElements++] = y3;
|
||||
|
||||
data.add (cubicMarker, x1, y1, x2, y2, x3, y3);
|
||||
bounds.extend (x1, y1, x2, y2);
|
||||
bounds.extend (x3, y3);
|
||||
}
|
||||
|
|
@ -371,48 +317,43 @@ void Path::cubicTo (Point<float> controlPoint1,
|
|||
|
||||
void Path::closeSubPath()
|
||||
{
|
||||
if (numElements > 0 && ! isMarker (data.elements[numElements - 1], closeSubPathMarker))
|
||||
{
|
||||
preallocateSpace (1);
|
||||
data.elements[numElements++] = closeSubPathMarker;
|
||||
}
|
||||
if (! (data.isEmpty() || isMarker (data.getLast(), closeSubPathMarker)))
|
||||
data.add (closeSubPathMarker);
|
||||
}
|
||||
|
||||
Point<float> Path::getCurrentPosition() const
|
||||
{
|
||||
int i = (int) numElements - 1;
|
||||
if (data.isEmpty())
|
||||
return {};
|
||||
|
||||
if (i > 0 && isMarker (data.elements[i], closeSubPathMarker))
|
||||
auto* i = data.end() - 1;
|
||||
|
||||
if (isMarker (*i, closeSubPathMarker))
|
||||
{
|
||||
while (i >= 0)
|
||||
while (i != data.begin())
|
||||
{
|
||||
if (isMarker (data.elements[i], moveMarker))
|
||||
if (isMarker (*--i, moveMarker))
|
||||
{
|
||||
i += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
return { data.elements[i - 1], data.elements[i] };
|
||||
if (i != data.begin())
|
||||
return { *(i - 1), *i };
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void Path::addRectangle (const float x, const float y,
|
||||
const float w, const float h)
|
||||
void Path::addRectangle (float x, float y, float w, float h)
|
||||
{
|
||||
float x1 = x, y1 = y, x2 = x + w, y2 = y + h;
|
||||
auto x1 = x, y1 = y, x2 = x + w, y2 = y + h;
|
||||
|
||||
if (w < 0) std::swap (x1, x2);
|
||||
if (h < 0) std::swap (y1, y2);
|
||||
|
||||
preallocateSpace (13);
|
||||
|
||||
if (numElements == 0)
|
||||
if (data.isEmpty())
|
||||
{
|
||||
bounds.pathXMin = x1;
|
||||
bounds.pathXMax = x2;
|
||||
|
|
@ -427,19 +368,11 @@ void Path::addRectangle (const float x, const float y,
|
|||
bounds.pathYMax = jmax (bounds.pathYMax, y2);
|
||||
}
|
||||
|
||||
data.elements[numElements++] = moveMarker;
|
||||
data.elements[numElements++] = x1;
|
||||
data.elements[numElements++] = y2;
|
||||
data.elements[numElements++] = lineMarker;
|
||||
data.elements[numElements++] = x1;
|
||||
data.elements[numElements++] = y1;
|
||||
data.elements[numElements++] = lineMarker;
|
||||
data.elements[numElements++] = x2;
|
||||
data.elements[numElements++] = y1;
|
||||
data.elements[numElements++] = lineMarker;
|
||||
data.elements[numElements++] = x2;
|
||||
data.elements[numElements++] = y2;
|
||||
data.elements[numElements++] = closeSubPathMarker;
|
||||
data.add (moveMarker, x1, y2,
|
||||
lineMarker, x1, y1,
|
||||
lineMarker, x2, y1,
|
||||
lineMarker, x2, y2,
|
||||
closeSubPathMarker);
|
||||
}
|
||||
|
||||
void Path::addRoundedRectangle (float x, float y, float w, float h, float csx, float csy)
|
||||
|
|
@ -511,9 +444,9 @@ void Path::addTriangle (float x1, float y1,
|
|||
float x2, float y2,
|
||||
float x3, float y3)
|
||||
{
|
||||
addTriangle (Point<float> (x1, y1),
|
||||
Point<float> (x2, y2),
|
||||
Point<float> (x3, y3));
|
||||
addTriangle ({ x1, y1 },
|
||||
{ x2, y2 },
|
||||
{ x3, y3 });
|
||||
}
|
||||
|
||||
void Path::addTriangle (Point<float> p1, Point<float> p2, Point<float> p3)
|
||||
|
|
@ -524,10 +457,10 @@ void Path::addTriangle (Point<float> p1, Point<float> p2, Point<float> p3)
|
|||
closeSubPath();
|
||||
}
|
||||
|
||||
void Path::addQuadrilateral (const float x1, const float y1,
|
||||
const float x2, const float y2,
|
||||
const float x3, const float y3,
|
||||
const float x4, const float y4)
|
||||
void Path::addQuadrilateral (float x1, float y1,
|
||||
float x2, float y2,
|
||||
float x3, float y3,
|
||||
float x4, float y4)
|
||||
{
|
||||
startNewSubPath (x1, y1);
|
||||
lineTo (x2, y2);
|
||||
|
|
@ -538,7 +471,7 @@ void Path::addQuadrilateral (const float x1, const float y1,
|
|||
|
||||
void Path::addEllipse (float x, float y, float w, float h)
|
||||
{
|
||||
addEllipse (Rectangle<float> (x, y, w, h));
|
||||
addEllipse ({ x, y, w, h });
|
||||
}
|
||||
|
||||
void Path::addEllipse (Rectangle<float> area)
|
||||
|
|
@ -558,11 +491,9 @@ void Path::addEllipse (Rectangle<float> area)
|
|||
closeSubPath();
|
||||
}
|
||||
|
||||
void Path::addArc (const float x, const float y,
|
||||
const float w, const float h,
|
||||
const float fromRadians,
|
||||
const float toRadians,
|
||||
const bool startAsNewSubPath)
|
||||
void Path::addArc (float x, float y, float w, float h,
|
||||
float fromRadians, float toRadians,
|
||||
bool startAsNewSubPath)
|
||||
{
|
||||
auto radiusX = w / 2.0f;
|
||||
auto radiusY = h / 2.0f;
|
||||
|
|
@ -575,16 +506,15 @@ void Path::addArc (const float x, const float y,
|
|||
startAsNewSubPath);
|
||||
}
|
||||
|
||||
void Path::addCentredArc (const float centreX, const float centreY,
|
||||
const float radiusX, const float radiusY,
|
||||
const float rotationOfEllipse,
|
||||
const float fromRadians,
|
||||
float toRadians,
|
||||
const bool startAsNewSubPath)
|
||||
void Path::addCentredArc (float centreX, float centreY,
|
||||
float radiusX, float radiusY,
|
||||
float rotationOfEllipse,
|
||||
float fromRadians, float toRadians,
|
||||
bool startAsNewSubPath)
|
||||
{
|
||||
if (radiusX > 0.0f && radiusY > 0.0f)
|
||||
{
|
||||
const Point<float> centre (centreX, centreY);
|
||||
Point<float> centre (centreX, centreY);
|
||||
auto rotation = AffineTransform::rotation (rotationOfEllipse, centreX, centreY);
|
||||
auto angle = fromRadians;
|
||||
|
||||
|
|
@ -618,15 +548,13 @@ void Path::addCentredArc (const float centreX, const float centreY,
|
|||
}
|
||||
}
|
||||
|
||||
void Path::addPieSegment (const float x, const float y,
|
||||
const float width, const float height,
|
||||
const float fromRadians,
|
||||
const float toRadians,
|
||||
const float innerCircleProportionalSize)
|
||||
void Path::addPieSegment (float x, float y, float width, float height,
|
||||
float fromRadians, float toRadians,
|
||||
float innerCircleProportionalSize)
|
||||
{
|
||||
float radiusX = width * 0.5f;
|
||||
float radiusY = height * 0.5f;
|
||||
const Point<float> centre (x + radiusX, y + radiusY);
|
||||
auto radiusX = width * 0.5f;
|
||||
auto radiusY = height * 0.5f;
|
||||
Point<float> centre (x + radiusX, y + radiusY);
|
||||
|
||||
startNewSubPath (centre.getPointOnCircumference (radiusX, radiusY, fromRadians));
|
||||
addArc (x, y, width, height, fromRadians, toRadians);
|
||||
|
|
@ -663,9 +591,8 @@ void Path::addPieSegment (const float x, const float y,
|
|||
}
|
||||
|
||||
void Path::addPieSegment (Rectangle<float> segmentBounds,
|
||||
const float fromRadians,
|
||||
const float toRadians,
|
||||
const float innerCircleProportionalSize)
|
||||
float fromRadians, float toRadians,
|
||||
float innerCircleProportionalSize)
|
||||
{
|
||||
addPieSegment (segmentBounds.getX(),
|
||||
segmentBounds.getY(),
|
||||
|
|
@ -760,8 +687,8 @@ void Path::addStar (Point<float> centre, int numberOfPoints, float innerRadius,
|
|||
void Path::addBubble (Rectangle<float> bodyArea,
|
||||
Rectangle<float> maximumArea,
|
||||
Point<float> arrowTip,
|
||||
const float cornerSize,
|
||||
const float arrowBaseWidth)
|
||||
float cornerSize,
|
||||
float arrowBaseWidth)
|
||||
{
|
||||
auto halfW = bodyArea.getWidth() / 2.0f;
|
||||
auto halfH = bodyArea.getHeight() / 2.0f;
|
||||
|
|
@ -824,10 +751,9 @@ void Path::addBubble (Rectangle<float> bodyArea,
|
|||
|
||||
void Path::addPath (const Path& other)
|
||||
{
|
||||
size_t i = 0;
|
||||
const float* d = other.data.elements;
|
||||
const auto* d = other.data.begin();
|
||||
|
||||
while (i < other.numElements)
|
||||
for (int i = 0; i < other.data.size();)
|
||||
{
|
||||
auto type = d[i++];
|
||||
|
||||
|
|
@ -866,10 +792,9 @@ void Path::addPath (const Path& other)
|
|||
void Path::addPath (const Path& other,
|
||||
const AffineTransform& transformToApply)
|
||||
{
|
||||
size_t i = 0;
|
||||
const float* d = other.data.elements;
|
||||
const auto* d = other.data.begin();
|
||||
|
||||
while (i < other.numElements)
|
||||
for (int i = 0; i < other.data.size();)
|
||||
{
|
||||
auto type = d[i++];
|
||||
|
||||
|
|
@ -923,8 +848,8 @@ void Path::applyTransform (const AffineTransform& transform) noexcept
|
|||
{
|
||||
bounds.reset();
|
||||
bool firstPoint = true;
|
||||
float* d = data.elements;
|
||||
auto* end = d + numElements;
|
||||
float* d = data.begin();
|
||||
auto* end = data.end();
|
||||
|
||||
while (d < end)
|
||||
{
|
||||
|
|
@ -977,9 +902,8 @@ AffineTransform Path::getTransformToScaleToFit (Rectangle<float> area, bool pres
|
|||
preserveProportions, justification);
|
||||
}
|
||||
|
||||
AffineTransform Path::getTransformToScaleToFit (const float x, const float y,
|
||||
const float w, const float h,
|
||||
const bool preserveProportions,
|
||||
AffineTransform Path::getTransformToScaleToFit (float x, float y, float w, float h,
|
||||
bool preserveProportions,
|
||||
Justification justification) const
|
||||
{
|
||||
auto boundsRect = getBounds();
|
||||
|
|
@ -1030,7 +954,7 @@ AffineTransform Path::getTransformToScaleToFit (const float x, const float y,
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
bool Path::contains (const float x, const float y, const float tolerance) const
|
||||
bool Path::contains (float x, float y, float tolerance) const
|
||||
{
|
||||
if (x <= bounds.pathXMin || x >= bounds.pathXMax
|
||||
|| y <= bounds.pathYMin || y >= bounds.pathYMax)
|
||||
|
|
@ -1061,12 +985,12 @@ bool Path::contains (const float x, const float y, const float tolerance) const
|
|||
: ((negativeCrossings + positiveCrossings) & 1) != 0;
|
||||
}
|
||||
|
||||
bool Path::contains (Point<float> point, const float tolerance) const
|
||||
bool Path::contains (Point<float> point, float tolerance) const
|
||||
{
|
||||
return contains (point.x, point.y, tolerance);
|
||||
}
|
||||
|
||||
bool Path::intersectsLine (Line<float> line, const float tolerance)
|
||||
bool Path::intersectsLine (Line<float> line, float tolerance)
|
||||
{
|
||||
PathFlatteningIterator i (*this, AffineTransform(), tolerance);
|
||||
Point<float> intersection;
|
||||
|
|
@ -1078,7 +1002,7 @@ bool Path::intersectsLine (Line<float> line, const float tolerance)
|
|||
return false;
|
||||
}
|
||||
|
||||
Line<float> Path::getClippedLine (Line<float> line, const bool keepSectionOutsidePath) const
|
||||
Line<float> Path::getClippedLine (Line<float> line, bool keepSectionOutsidePath) const
|
||||
{
|
||||
Line<float> result (line);
|
||||
const bool startInside = contains (line.getStart());
|
||||
|
|
@ -1174,23 +1098,23 @@ Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
|||
return *this;
|
||||
|
||||
Path p;
|
||||
size_t indexOfPathStart = 0, indexOfPathStartThis = 0;
|
||||
size_t n = 0;
|
||||
int n = 0, indexOfPathStart = 0, indexOfPathStartThis = 0;
|
||||
auto* elements = data.begin();
|
||||
bool lastWasLine = false, firstWasLine = false;
|
||||
|
||||
while (n < numElements)
|
||||
while (n < data.size())
|
||||
{
|
||||
auto type = data.elements[n++];
|
||||
auto type = elements[n++];
|
||||
|
||||
if (isMarker (type, moveMarker))
|
||||
{
|
||||
indexOfPathStart = p.numElements;
|
||||
indexOfPathStart = p.data.size();
|
||||
indexOfPathStartThis = n - 1;
|
||||
auto x = data.elements[n++];
|
||||
auto y = data.elements[n++];
|
||||
auto x = elements[n++];
|
||||
auto y = elements[n++];
|
||||
p.startNewSubPath (x, y);
|
||||
lastWasLine = false;
|
||||
firstWasLine = (isMarker (data.elements[n], lineMarker));
|
||||
firstWasLine = (isMarker (elements[n], lineMarker));
|
||||
}
|
||||
else if (isMarker (type, lineMarker) || isMarker (type, closeSubPathMarker))
|
||||
{
|
||||
|
|
@ -1198,28 +1122,28 @@ Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
|||
|
||||
if (isMarker (type, lineMarker))
|
||||
{
|
||||
endX = data.elements[n++];
|
||||
endY = data.elements[n++];
|
||||
endX = elements[n++];
|
||||
endY = elements[n++];
|
||||
|
||||
if (n > 8)
|
||||
{
|
||||
startX = data.elements[n - 8];
|
||||
startY = data.elements[n - 7];
|
||||
joinX = data.elements[n - 5];
|
||||
joinY = data.elements[n - 4];
|
||||
startX = elements[n - 8];
|
||||
startY = elements[n - 7];
|
||||
joinX = elements[n - 5];
|
||||
joinY = elements[n - 4];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
endX = data.elements[indexOfPathStartThis + 1];
|
||||
endY = data.elements[indexOfPathStartThis + 2];
|
||||
endX = elements[indexOfPathStartThis + 1];
|
||||
endY = elements[indexOfPathStartThis + 2];
|
||||
|
||||
if (n > 6)
|
||||
{
|
||||
startX = data.elements[n - 6];
|
||||
startY = data.elements[n - 5];
|
||||
joinX = data.elements[n - 3];
|
||||
joinY = data.elements[n - 2];
|
||||
startX = elements[n - 6];
|
||||
startY = elements[n - 5];
|
||||
joinX = elements[n - 3];
|
||||
joinY = elements[n - 2];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1231,8 +1155,8 @@ Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
|||
{
|
||||
auto propNeeded = jmin (0.5, cornerRadius / len1);
|
||||
|
||||
p.data.elements[p.numElements - 2] = (float) (joinX - (joinX - startX) * propNeeded);
|
||||
p.data.elements[p.numElements - 1] = (float) (joinY - (joinY - startY) * propNeeded);
|
||||
*(p.data.end() - 2) = (float) (joinX - (joinX - startX) * propNeeded);
|
||||
*(p.data.end() - 1) = (float) (joinY - (joinY - startY) * propNeeded);
|
||||
}
|
||||
|
||||
auto len2 = PathHelpers::lengthOf (endX, endY, joinX, joinY);
|
||||
|
|
@ -1258,12 +1182,12 @@ Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
|||
{
|
||||
if (firstWasLine)
|
||||
{
|
||||
startX = data.elements[n - 3];
|
||||
startY = data.elements[n - 2];
|
||||
startX = elements[n - 3];
|
||||
startY = elements[n - 2];
|
||||
joinX = endX;
|
||||
joinY = endY;
|
||||
endX = data.elements[indexOfPathStartThis + 4];
|
||||
endY = data.elements[indexOfPathStartThis + 5];
|
||||
endX = elements[indexOfPathStartThis + 4];
|
||||
endY = elements[indexOfPathStartThis + 5];
|
||||
|
||||
auto len1 = PathHelpers::lengthOf (startX, startY, joinX, joinY);
|
||||
|
||||
|
|
@ -1271,8 +1195,8 @@ Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
|||
{
|
||||
auto propNeeded = jmin (0.5, cornerRadius / len1);
|
||||
|
||||
p.data.elements[p.numElements - 2] = (float) (joinX - (joinX - startX) * propNeeded);
|
||||
p.data.elements[p.numElements - 1] = (float) (joinY - (joinY - startY) * propNeeded);
|
||||
*(p.data.end() - 2) = (float) (joinX - (joinX - startX) * propNeeded);
|
||||
*(p.data.end() - 1) = (float) (joinY - (joinY - startY) * propNeeded);
|
||||
}
|
||||
|
||||
auto len2 = PathHelpers::lengthOf (endX, endY, joinX, joinY);
|
||||
|
|
@ -1286,8 +1210,8 @@ Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
|||
|
||||
p.quadraticTo (joinX, joinY, endX, endY);
|
||||
|
||||
p.data.elements[indexOfPathStart + 1] = endX;
|
||||
p.data.elements[indexOfPathStart + 2] = endY;
|
||||
p.data.begin()[indexOfPathStart + 1] = endX;
|
||||
p.data.begin()[indexOfPathStart + 2] = endY;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1297,21 +1221,21 @@ Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
|||
else if (isMarker (type, quadMarker))
|
||||
{
|
||||
lastWasLine = false;
|
||||
auto x1 = data.elements[n++];
|
||||
auto y1 = data.elements[n++];
|
||||
auto x2 = data.elements[n++];
|
||||
auto y2 = data.elements[n++];
|
||||
auto x1 = elements[n++];
|
||||
auto y1 = elements[n++];
|
||||
auto x2 = elements[n++];
|
||||
auto y2 = elements[n++];
|
||||
p.quadraticTo (x1, y1, x2, y2);
|
||||
}
|
||||
else if (isMarker (type, cubicMarker))
|
||||
{
|
||||
lastWasLine = false;
|
||||
auto x1 = data.elements[n++];
|
||||
auto y1 = data.elements[n++];
|
||||
auto x2 = data.elements[n++];
|
||||
auto y2 = data.elements[n++];
|
||||
auto x3 = data.elements[n++];
|
||||
auto y3 = data.elements[n++];
|
||||
auto x1 = elements[n++];
|
||||
auto y1 = elements[n++];
|
||||
auto x2 = elements[n++];
|
||||
auto y2 = elements[n++];
|
||||
auto x3 = elements[n++];
|
||||
auto y3 = elements[n++];
|
||||
p.cubicTo (x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
}
|
||||
|
|
@ -1396,39 +1320,39 @@ void Path::writePathToStream (OutputStream& dest) const
|
|||
{
|
||||
dest.writeByte (useNonZeroWinding ? 'n' : 'z');
|
||||
|
||||
for (size_t i = 0; i < numElements;)
|
||||
for (auto* i = data.begin(); i != data.end();)
|
||||
{
|
||||
auto type = data.elements[i++];
|
||||
auto type = *i++;
|
||||
|
||||
if (isMarker (type, moveMarker))
|
||||
{
|
||||
dest.writeByte ('m');
|
||||
dest.writeFloat (data.elements[i++]);
|
||||
dest.writeFloat (data.elements[i++]);
|
||||
dest.writeFloat (*i++);
|
||||
dest.writeFloat (*i++);
|
||||
}
|
||||
else if (isMarker (type, lineMarker))
|
||||
{
|
||||
dest.writeByte ('l');
|
||||
dest.writeFloat (data.elements[i++]);
|
||||
dest.writeFloat (data.elements[i++]);
|
||||
dest.writeFloat (*i++);
|
||||
dest.writeFloat (*i++);
|
||||
}
|
||||
else if (isMarker (type, quadMarker))
|
||||
{
|
||||
dest.writeByte ('q');
|
||||
dest.writeFloat (data.elements[i++]);
|
||||
dest.writeFloat (data.elements[i++]);
|
||||
dest.writeFloat (data.elements[i++]);
|
||||
dest.writeFloat (data.elements[i++]);
|
||||
dest.writeFloat (*i++);
|
||||
dest.writeFloat (*i++);
|
||||
dest.writeFloat (*i++);
|
||||
dest.writeFloat (*i++);
|
||||
}
|
||||
else if (isMarker (type, cubicMarker))
|
||||
{
|
||||
dest.writeByte ('b');
|
||||
dest.writeFloat (data.elements[i++]);
|
||||
dest.writeFloat (data.elements[i++]);
|
||||
dest.writeFloat (data.elements[i++]);
|
||||
dest.writeFloat (data.elements[i++]);
|
||||
dest.writeFloat (data.elements[i++]);
|
||||
dest.writeFloat (data.elements[i++]);
|
||||
dest.writeFloat (*i++);
|
||||
dest.writeFloat (*i++);
|
||||
dest.writeFloat (*i++);
|
||||
dest.writeFloat (*i++);
|
||||
dest.writeFloat (*i++);
|
||||
dest.writeFloat (*i++);
|
||||
}
|
||||
else if (isMarker (type, closeSubPathMarker))
|
||||
{
|
||||
|
|
@ -1445,12 +1369,11 @@ String Path::toString() const
|
|||
if (! useNonZeroWinding)
|
||||
s << 'a';
|
||||
|
||||
size_t i = 0;
|
||||
float lastMarker = 0.0f;
|
||||
|
||||
while (i < numElements)
|
||||
for (int i = 0; i < data.size();)
|
||||
{
|
||||
auto type = data.elements[i++];
|
||||
auto type = data.begin()[i++];
|
||||
char markerChar = 0;
|
||||
int numCoords = 0;
|
||||
|
||||
|
|
@ -1489,9 +1412,9 @@ String Path::toString() const
|
|||
lastMarker = type;
|
||||
}
|
||||
|
||||
while (--numCoords >= 0 && i < numElements)
|
||||
while (--numCoords >= 0 && i < data.size())
|
||||
{
|
||||
String coord (data.elements[i++], 3);
|
||||
String coord (data.begin()[i++], 3);
|
||||
|
||||
while (coord.endsWithChar ('0') && coord != "0")
|
||||
coord = coord.dropLastCharacters (1);
|
||||
|
|
@ -1576,7 +1499,7 @@ void Path::restoreFromString (StringRef stringVersion)
|
|||
|
||||
//==============================================================================
|
||||
Path::Iterator::Iterator (const Path& p) noexcept
|
||||
: elementType (startNewSubPath), path (p)
|
||||
: elementType (startNewSubPath), path (p), index (path.data.begin())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -1586,41 +1509,39 @@ Path::Iterator::~Iterator() noexcept
|
|||
|
||||
bool Path::Iterator::next() noexcept
|
||||
{
|
||||
const float* elements = path.data.elements;
|
||||
|
||||
if (index < path.numElements)
|
||||
if (index != path.data.end())
|
||||
{
|
||||
auto type = elements[index++];
|
||||
auto type = *index++;
|
||||
|
||||
if (isMarker (type, moveMarker))
|
||||
{
|
||||
elementType = startNewSubPath;
|
||||
x1 = elements[index++];
|
||||
y1 = elements[index++];
|
||||
x1 = *index++;
|
||||
y1 = *index++;
|
||||
}
|
||||
else if (isMarker (type, lineMarker))
|
||||
{
|
||||
elementType = lineTo;
|
||||
x1 = elements[index++];
|
||||
y1 = elements[index++];
|
||||
x1 = *index++;
|
||||
y1 = *index++;
|
||||
}
|
||||
else if (isMarker (type, quadMarker))
|
||||
{
|
||||
elementType = quadraticTo;
|
||||
x1 = elements[index++];
|
||||
y1 = elements[index++];
|
||||
x2 = elements[index++];
|
||||
y2 = elements[index++];
|
||||
x1 = *index++;
|
||||
y1 = *index++;
|
||||
x2 = *index++;
|
||||
y2 = *index++;
|
||||
}
|
||||
else if (isMarker (type, cubicMarker))
|
||||
{
|
||||
elementType = cubicTo;
|
||||
x1 = elements[index++];
|
||||
y1 = elements[index++];
|
||||
x2 = elements[index++];
|
||||
y2 = elements[index++];
|
||||
x3 = elements[index++];
|
||||
y3 = elements[index++];
|
||||
x1 = *index++;
|
||||
y1 = *index++;
|
||||
x2 = *index++;
|
||||
y2 = *index++;
|
||||
x3 = *index++;
|
||||
y3 = *index++;
|
||||
}
|
||||
else if (isMarker (type, closeSubPathMarker))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -753,7 +753,7 @@ public:
|
|||
//==============================================================================
|
||||
private:
|
||||
const Path& path;
|
||||
size_t index = 0;
|
||||
const float* index;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (Iterator)
|
||||
};
|
||||
|
|
@ -803,8 +803,7 @@ private:
|
|||
friend class Path::Iterator;
|
||||
friend class EdgeTable;
|
||||
|
||||
ArrayAllocationBase<float, DummyCriticalSection> data;
|
||||
size_t numElements = 0;
|
||||
Array<float> data;
|
||||
|
||||
struct PathBounds
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,18 +32,18 @@ namespace juce
|
|||
#endif
|
||||
|
||||
//==============================================================================
|
||||
PathFlatteningIterator::PathFlatteningIterator (const Path& path_,
|
||||
const AffineTransform& transform_,
|
||||
const float tolerance)
|
||||
PathFlatteningIterator::PathFlatteningIterator (const Path& pathToUse,
|
||||
const AffineTransform& t,
|
||||
float tolerance)
|
||||
: x2 (0),
|
||||
y2 (0),
|
||||
closesSubPath (false),
|
||||
subPathIndex (-1),
|
||||
path (path_),
|
||||
transform (transform_),
|
||||
points (path_.data.elements),
|
||||
path (pathToUse),
|
||||
transform (t),
|
||||
source (path.data.begin()),
|
||||
toleranceSquared (tolerance * tolerance),
|
||||
isIdentityTransform (transform_.isIdentity())
|
||||
isIdentityTransform (t.isIdentity())
|
||||
{
|
||||
stackPos = stackBase;
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ PathFlatteningIterator::~PathFlatteningIterator()
|
|||
bool PathFlatteningIterator::isLastInSubpath() const noexcept
|
||||
{
|
||||
return stackPos == stackBase.get()
|
||||
&& (index >= path.numElements || isMarker (points[index], Path::moveMarker));
|
||||
&& (source == path.data.end() || isMarker (*source, Path::moveMarker));
|
||||
}
|
||||
|
||||
bool PathFlatteningIterator::next()
|
||||
|
|
@ -74,30 +74,30 @@ bool PathFlatteningIterator::next()
|
|||
|
||||
if (stackPos == stackBase)
|
||||
{
|
||||
if (index >= path.numElements)
|
||||
if (source == path.data.end())
|
||||
return false;
|
||||
|
||||
type = points [index++];
|
||||
type = *source++;
|
||||
|
||||
if (! isMarker (type, Path::closeSubPathMarker))
|
||||
{
|
||||
x2 = points [index++];
|
||||
y2 = points [index++];
|
||||
x2 = *source++;
|
||||
y2 = *source++;
|
||||
|
||||
if (isMarker (type, Path::quadMarker))
|
||||
{
|
||||
x3 = points [index++];
|
||||
y3 = points [index++];
|
||||
x3 = *source++;
|
||||
y3 = *source++;
|
||||
|
||||
if (! isIdentityTransform)
|
||||
transform.transformPoints (x2, y2, x3, y3);
|
||||
}
|
||||
else if (isMarker (type, Path::cubicMarker))
|
||||
{
|
||||
x3 = points [index++];
|
||||
y3 = points [index++];
|
||||
x4 = points [index++];
|
||||
y4 = points [index++];
|
||||
x3 = *source++;
|
||||
y3 = *source++;
|
||||
x4 = *source++;
|
||||
y4 = *source++;
|
||||
|
||||
if (! isIdentityTransform)
|
||||
transform.transformPoints (x2, y2, x3, y3, x4, y4);
|
||||
|
|
@ -137,9 +137,9 @@ bool PathFlatteningIterator::next()
|
|||
{
|
||||
++subPathIndex;
|
||||
|
||||
closesSubPath = (stackPos == stackBase)
|
||||
&& (index < path.numElements)
|
||||
&& (points [index] == Path::closeSubPathMarker)
|
||||
closesSubPath = stackPos == stackBase
|
||||
&& source != path.data.end()
|
||||
&& *source == Path::closeSubPathMarker
|
||||
&& x2 == subPathCloseX
|
||||
&& y2 == subPathCloseY;
|
||||
|
||||
|
|
|
|||
|
|
@ -95,14 +95,14 @@ private:
|
|||
//==============================================================================
|
||||
const Path& path;
|
||||
const AffineTransform transform;
|
||||
float* points;
|
||||
const float* source;
|
||||
const float toleranceSquared;
|
||||
float subPathCloseX = 0, subPathCloseY = 0;
|
||||
const bool isIdentityTransform;
|
||||
|
||||
HeapBlock<float> stackBase { 32 };
|
||||
float* stackPos;
|
||||
size_t index = 0, stackSize = 32;
|
||||
size_t stackSize = 32;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PathFlatteningIterator)
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue