29JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6255 6263 6386)
36 maxEdgesPerLine (
jmax (defaultEdgesPerLine / 2,
37 4 * (
int)
std::sqrt (path.data.size()))),
38 lineStrideElements (maxEdgesPerLine * 2 + 1)
43 for (
int i = bounds.getHeight(); --i >= 0;)
46 t += lineStrideElements;
60 return static_cast<int64_t> (y * 256.0f + (y >= 0 ? 0.5f : -0.5f));
88 const double startX = 256.0f * iter.x1;
89 const double multiplier = (iter.x2 - iter.x1) / (iter.y2 - iter.y1);
94 auto step =
jmin (stepSize, y2 -
y1, 256 - (
y1 & 255));
98 addEdgePoint (
clampedX,
static_cast<int> (
y1 / scale),
static_cast<int> (direction * step));
106 sanitiseLevels (path.isUsingNonZeroWinding());
111 maxEdgesPerLine (defaultEdgesPerLine),
112 lineStrideElements (defaultEdgesPerLine * 2 + 1)
128 t += lineStrideElements;
134 maxEdgesPerLine (defaultEdgesPerLine),
135 lineStrideElements (defaultEdgesPerLine * 2 + 1),
136 needToCheckEmptiness (
true)
143 auto x1 = scale * r.getX();
144 auto x2 = scale * r.getRight();
145 auto y = r.getY() - bounds.
getY();
147 for (
int j = r.getHeight(); --
j >= 0;)
148 addEdgePointPair (x1, x2, y++, 255);
151 sanitiseLevels (
true);
165 auto x1 =
roundToInt ((
float) scale * r.getX());
166 auto x2 =
roundToInt ((
float) scale * r.getRight());
169 auto y2 =
roundToInt ((
float) scale * r.getBottom()) - (bounds.
getY() * scale);
171 if (x2 <= x1 || y2 <=
y1)
179 addEdgePointPair (x1, x2, y, y2 -
y1);
183 addEdgePointPair (x1, x2, y++, 255 - (
y1 & 255));
186 addEdgePointPair (x1, x2, y++, 255);
189 addEdgePointPair (x1, x2, y, y2 & 255);
193 sanitiseLevels (
true);
201 maxEdgesPerLine (defaultEdgesPerLine),
202 lineStrideElements ((defaultEdgesPerLine * 2) + 1)
214 if (x2 <= x1 || y2 <=
y1)
223 if ((
y1 / scale) == (y2 / scale))
231 t += lineStrideElements;
237 t[2] = 255 - (
y1 & 255);
241 t += lineStrideElements;
243 while (lineY < (y2 / scale))
251 t += lineStrideElements;
261 t += lineStrideElements;
267 t += lineStrideElements;
279 bounds =
other.bounds;
280 maxEdgesPerLine =
other.maxEdgesPerLine;
281 lineStrideElements =
other.lineStrideElements;
282 needToCheckEmptiness =
other.needToCheckEmptiness;
285 copyEdgeTableData (table, lineStrideElements,
other.table, lineStrideElements, bounds.
getHeight());
294static size_t getEdgeTableAllocationSize (
int lineStride,
int height)
noexcept
297 return (
size_t) (lineStride * (2 +
jmax (0, height)));
300void EdgeTable::allocate()
302 table.
malloc (getEdgeTableAllocationSize (lineStrideElements, bounds.
getHeight()));
305void EdgeTable::clearLineSizes() noexcept
309 for (
int i = bounds.
getHeight(); --i >= 0;)
312 t += lineStrideElements;
320 memcpy (dest, src, (
size_t) (src[0] * 2 + 1) *
sizeof (
int));
326void EdgeTable::sanitiseLevels (
const bool useNonZeroWinding)
noexcept
331 for (
int y = bounds.getHeight(); --y >= 0;)
337 auto* items =
reinterpret_cast<LineItem*
> (
lineStart + 1);
364 if (useNonZeroWinding)
383 (items - 1)->level = 0;
408inline void EdgeTable::remapWithExtraSpace (
int numPoints)
418 for (
int i = bounds.
getHeight(); --i >= 0;)
424void EdgeTable::addEdgePoint (
const int x,
const int y,
const int winding)
428 auto* line = table + lineStrideElements * y;
434 line = table + lineStrideElements * y;
443void EdgeTable::addEdgePointPair (
int x1,
int x2,
int y,
int winding)
447 auto* line = table + lineStrideElements * y;
453 line = table + lineStrideElements * y;
464void EdgeTable::translate (
float dx,
int dy)
noexcept
471 for (
int i = bounds.getHeight(); --i >= 0;)
490 for (
int y = 0; y < bounds.
getHeight(); ++y)
493 auto* item =
reinterpret_cast<LineItem*
> (
lineStart + 1);
504void EdgeTable::intersectWithEdgeTableLine (
const int y,
const int*
const otherLine)
508 auto*
srcLine = table + lineStrideElements * y;
522 auto right = bounds.
getRight() * scale;
593 srcLine = table + lineStrideElements * y;
602 srcLine = table + lineStrideElements * y;
612 auto* temp = table + lineStrideElements * bounds.
getHeight();
629 srcLine = table + lineStrideElements * y;
640void EdgeTable::clipEdgeTableLineToRange (
int* dest,
const int x1,
const int x2)
noexcept
642 int* lastItem = dest + (dest[0] * 2 - 1);
644 if (x2 < lastItem[0])
652 while (x2 < lastItem[-2])
664 while (lastItem[0] > x1)
672 memmove (dest + 1, lastItem, (
size_t) dest[0] * (
sizeof (
int) * 2));
681void EdgeTable::clipToRectangle (Rectangle<int> r)
683 auto clipped = r.getIntersection (bounds);
687 needToCheckEmptiness =
false;
698 for (
int i = 0; i < top; ++i)
699 table[lineStrideElements * i] = 0;
703 auto x1 = scale *
clipped.getX();
705 int* line = table + lineStrideElements * top;
707 for (
int i = bottom - top; --i >= 0;)
710 clipEdgeTableLineToRange (line, x1, x2);
712 line += lineStrideElements;
716 needToCheckEmptiness =
true;
720void EdgeTable::excludeRectangle (Rectangle<int> r)
722 auto clipped = r.getIntersection (bounds);
731 scale *
clipped.getRight(), 255,
734 for (
int i = top; i < bottom; ++i)
735 intersectWithEdgeTableLine (i,
rectLine);
737 needToCheckEmptiness =
true;
741void EdgeTable::clipToEdgeTable (
const EdgeTable&
other)
747 needToCheckEmptiness =
false;
761 for (
int i = 0; i < top; ++i)
762 table[lineStrideElements * i] = 0;
766 for (
int i = top; i < bottom; ++i)
768 intersectWithEdgeTableLine (i,
otherLine);
772 needToCheckEmptiness =
true;
783 needToCheckEmptiness =
true;
787 table[lineStrideElements * y] = 0;
817 intersectWithEdgeTableLine (y,
tempLine);
820bool EdgeTable::isEmpty() noexcept
822 if (needToCheckEmptiness)
824 needToCheckEmptiness =
false;
827 for (
int i = bounds.
getHeight(); --i >= 0;)
832 t += lineStrideElements;
841JUCE_END_IGNORE_WARNINGS_MSVC
A table of horizontal scan-line segments - used for rasterising Paths.
EdgeTable(Rectangle< int > clipLimits, const Path &pathToAdd, const AffineTransform &transform)
Creates an edge table containing a path.
void optimiseTable()
Reduces the amount of space the table has allocated.
EdgeTable & operator=(const EdgeTable &)
Copies from another edge table.
void multiplyLevels(float factor)
Scales all the alpha-levels in the table by the given multiplier.
void swapWith(HeapBlock< ElementType, otherBlockThrows > &other) noexcept
Swaps this object's data with the data of another HeapBlock.
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
Allocates a specified amount of memory.
Flattens a Path object into a series of straight-line sections.
A path is a sequence of lines and curves that may either form a closed shape or be open-ended.
Maintains a set of rectangles as a complex region.
Manages a rectangle and allows geometric operations to be performed on it.
ValueType getRight() const noexcept
Returns the x coordinate of the rectangle's right-hand-side.
ValueType getX() const noexcept
Returns the x coordinate of the rectangle's left-hand-side.
void setRight(ValueType newRight) noexcept
Adjusts the width so that the right-hand edge of the rectangle has this new value.
void setHeight(ValueType newHeight) noexcept
Changes the rectangle's height.
ValueType getY() const noexcept
Returns the y coordinate of the rectangle's top edge.
ValueType getHeight() const noexcept
Returns the height of the rectangle.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Constrains a value to keep it within a given range.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Returns true if a value is at least zero, and also below a specified upper limit.
unsigned char uint8
A platform-independent 8-bit unsigned integer type.
int roundToInt(const FloatType value) noexcept
Fast floating-point-to-integer conversion.