Browse Source

Simplified the Path class by making it use an Array for starage.

tags/2021-05-28
jules 7 years ago
parent
commit
5e9267e5d8
5 changed files with 179 additions and 259 deletions
  1. +1
    -1
      modules/juce_graphics/geometry/juce_EdgeTable.cpp
  2. +153
    -232
      modules/juce_graphics/geometry/juce_Path.cpp
  3. +2
    -3
      modules/juce_graphics/geometry/juce_Path.h
  4. +21
    -21
      modules/juce_graphics/geometry/juce_PathIterator.cpp
  5. +2
    -2
      modules/juce_graphics/geometry/juce_PathIterator.h

+ 1
- 1
modules/juce_graphics/geometry/juce_EdgeTable.cpp View File

@@ -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();


+ 153
- 232
modules/juce_graphics/geometry/juce_Path.cpp View File

@@ -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 {};
auto* i = data.end() - 1;
if (i > 0 && isMarker (data.elements[i], closeSubPathMarker))
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))
{


+ 2
- 3
modules/juce_graphics/geometry/juce_Path.h View File

@@ -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
{


+ 21
- 21
modules/juce_graphics/geometry/juce_PathIterator.cpp View File

@@ -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;


+ 2
- 2
modules/juce_graphics/geometry/juce_PathIterator.h View File

@@ -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…
Cancel
Save