Browse Source

EdgeTable: Avoid shifts of negative numbers

v6.1.6
reuk 3 years ago
parent
commit
1a4296e98b
No known key found for this signature in database GPG Key ID: 9ADCD339CFC98A11
2 changed files with 52 additions and 51 deletions
  1. +40
    -43
      modules/juce_graphics/geometry/juce_EdgeTable.cpp
  2. +12
    -8
      modules/juce_graphics/geometry/juce_EdgeTable.h

+ 40
- 43
modules/juce_graphics/geometry/juce_EdgeTable.cpp View File

@@ -28,15 +28,12 @@ namespace juce
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6255 6263 6386)
const int juce_edgeTableDefaultEdgesPerLine = 32;
//==============================================================================
EdgeTable::EdgeTable (Rectangle<int> area, const Path& path, const AffineTransform& transform)
: bounds (area),
// this is a very vague heuristic to make a rough guess at a good table size
// 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,
maxEdgesPerLine (jmax (defaultEdgesPerLine / 2,
4 * (int) std::sqrt (path.data.size()))),
lineStrideElements (maxEdgesPerLine * 2 + 1)
{
@@ -49,10 +46,10 @@ EdgeTable::EdgeTable (Rectangle<int> area, const Path& path, const AffineTransfo
t += lineStrideElements;
}
auto leftLimit = bounds.getX() * 256;
auto topLimit = bounds.getY() * 256;
auto rightLimit = bounds.getRight() * 256;
auto heightLimit = bounds.getHeight() * 256;
auto leftLimit = scale * bounds.getX();
auto topLimit = scale * bounds.getY();
auto rightLimit = scale * bounds.getRight();
auto heightLimit = scale * bounds.getHeight();
PathFlatteningIterator iter (path, transform);
@@ -97,7 +94,7 @@ EdgeTable::EdgeTable (Rectangle<int> area, const Path& path, const AffineTransfo
else if (x >= rightLimit)
x = rightLimit - 1;
addEdgePoint (x, y1 >> 8, direction * step);
addEdgePoint (x, y1 / scale, direction * step);
y1 += step;
}
while (y1 < y2);
@@ -110,14 +107,14 @@ EdgeTable::EdgeTable (Rectangle<int> area, const Path& path, const AffineTransfo
EdgeTable::EdgeTable (Rectangle<int> rectangleToAdd)
: bounds (rectangleToAdd),
maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine),
lineStrideElements (juce_edgeTableDefaultEdgesPerLine * 2 + 1)
maxEdgesPerLine (defaultEdgesPerLine),
lineStrideElements (defaultEdgesPerLine * 2 + 1)
{
allocate();
table[0] = 0;
auto x1 = rectangleToAdd.getX() << 8;
auto x2 = rectangleToAdd.getRight() << 8;
auto x1 = scale * rectangleToAdd.getX();
auto x2 = scale * rectangleToAdd.getRight();
int* t = table;
for (int i = rectangleToAdd.getHeight(); --i >= 0;)
@@ -133,8 +130,8 @@ EdgeTable::EdgeTable (Rectangle<int> rectangleToAdd)
EdgeTable::EdgeTable (const RectangleList<int>& rectanglesToAdd)
: bounds (rectanglesToAdd.getBounds()),
maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine),
lineStrideElements (juce_edgeTableDefaultEdgesPerLine * 2 + 1),
maxEdgesPerLine (defaultEdgesPerLine),
lineStrideElements (defaultEdgesPerLine * 2 + 1),
needToCheckEmptiness (true)
{
allocate();
@@ -142,8 +139,8 @@ EdgeTable::EdgeTable (const RectangleList<int>& rectanglesToAdd)
for (auto& r : rectanglesToAdd)
{
auto x1 = r.getX() << 8;
auto x2 = r.getRight() << 8;
auto x1 = scale * r.getX();
auto x2 = scale * r.getRight();
auto y = r.getY() - bounds.getY();
for (int j = r.getHeight(); --j >= 0;)
@@ -164,17 +161,17 @@ EdgeTable::EdgeTable (const RectangleList<float>& rectanglesToAdd)
for (auto& r : rectanglesToAdd)
{
auto x1 = roundToInt (r.getX() * 256.0f);
auto x2 = roundToInt (r.getRight() * 256.0f);
auto x1 = roundToInt ((float) scale * r.getX());
auto x2 = roundToInt ((float) scale * r.getRight());
auto y1 = roundToInt (r.getY() * 256.0f) - (bounds.getY() << 8);
auto y2 = roundToInt (r.getBottom() * 256.0f) - (bounds.getY() << 8);
auto y1 = roundToInt ((float) scale * r.getY()) - (bounds.getY() * scale);
auto y2 = roundToInt ((float) scale * r.getBottom()) - (bounds.getY() * scale);
if (x2 <= x1 || y2 <= y1)
continue;
auto y = y1 >> 8;
auto lastLine = y2 >> 8;
auto y = y1 / scale;
auto lastLine = y2 / scale;
if (y == lastLine)
{
@@ -197,20 +194,20 @@ EdgeTable::EdgeTable (const RectangleList<float>& rectanglesToAdd)
EdgeTable::EdgeTable (Rectangle<float> rectangleToAdd)
: bounds ((int) std::floor (rectangleToAdd.getX()),
roundToInt (rectangleToAdd.getY() * 256.0f) >> 8,
roundToInt (rectangleToAdd.getY() * 256.0f) / scale,
2 + (int) rectangleToAdd.getWidth(),
2 + (int) rectangleToAdd.getHeight()),
maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine),
lineStrideElements ((juce_edgeTableDefaultEdgesPerLine * 2) + 1)
maxEdgesPerLine (defaultEdgesPerLine),
lineStrideElements ((defaultEdgesPerLine * 2) + 1)
{
jassert (! rectangleToAdd.isEmpty());
allocate();
table[0] = 0;
auto x1 = roundToInt (rectangleToAdd.getX() * 256.0f);
auto x2 = roundToInt (rectangleToAdd.getRight() * 256.0f);
auto y1 = roundToInt (rectangleToAdd.getY() * 256.0f) - (bounds.getY() << 8);
auto y2 = roundToInt (rectangleToAdd.getBottom() * 256.0f) - (bounds.getY() << 8);
auto x1 = roundToInt ((float) scale * rectangleToAdd.getX());
auto x2 = roundToInt ((float) scale * rectangleToAdd.getRight());
auto y1 = roundToInt ((float) scale * rectangleToAdd.getY()) - (bounds.getY() * scale);
auto y2 = roundToInt ((float) scale * rectangleToAdd.getBottom()) - (bounds.getY() * scale);
jassert (y1 < 256);
if (x2 <= x1 || y2 <= y1)
@@ -222,7 +219,7 @@ EdgeTable::EdgeTable (Rectangle<float> rectangleToAdd)
int lineY = 0;
int* t = table;
if ((y1 >> 8) == (y2 >> 8))
if ((y1 / scale) == (y2 / scale))
{
t[0] = 2;
t[1] = x1;
@@ -242,7 +239,7 @@ EdgeTable::EdgeTable (Rectangle<float> rectangleToAdd)
++lineY;
t += lineStrideElements;
while (lineY < (y2 >> 8))
while (lineY < (y2 / scale))
{
t[0] = 2;
t[1] = x1;
@@ -361,7 +358,7 @@ void EdgeTable::sanitiseLevels (const bool useNonZeroWinding) noexcept
auto corrected = std::abs (level);
if (corrected >> 8)
if (corrected / scale)
{
if (useNonZeroWinding)
{
@@ -371,7 +368,7 @@ void EdgeTable::sanitiseLevels (const bool useNonZeroWinding) noexcept
{
corrected &= 511;
if (corrected >> 8)
if (corrected / scale)
corrected = 511 - corrected;
}
}
@@ -497,7 +494,7 @@ void EdgeTable::multiplyLevels (float amount)
while (--numPoints > 0)
{
item->level = jmin (255, (item->level * multiplier) >> 8);
item->level = jmin (255, (item->level * multiplier) / scale);
++item;
}
}
@@ -521,7 +518,7 @@ void EdgeTable::intersectWithEdgeTableLine (const int y, const int* const otherL
return;
}
auto right = bounds.getRight() << 8;
auto right = bounds.getRight() * scale;
// optimise for the common case where our line lies entirely within a
// single pair of points, as happens when clipping to a simple rect.
@@ -576,7 +573,7 @@ void EdgeTable::intersectWithEdgeTableLine (const int y, const int* const otherL
lastX = nextX;
auto nextLevel = (level1 * (level2 + 1)) >> 8;
auto nextLevel = (level1 * (level2 + 1)) / scale;
jassert (isPositiveAndBelow (nextLevel, 256));
if (nextLevel != lastLevel)
@@ -702,8 +699,8 @@ void EdgeTable::clipToRectangle (Rectangle<int> r)
if (clipped.getX() > bounds.getX() || clipped.getRight() < bounds.getRight())
{
auto x1 = clipped.getX() << 8;
auto x2 = jmin (bounds.getRight(), clipped.getRight()) << 8;
auto x1 = scale * clipped.getX();
auto x2 = scale * jmin (bounds.getRight(), clipped.getRight());
int* line = table + lineStrideElements * top;
for (int i = bottom - top; --i >= 0;)
@@ -729,8 +726,8 @@ void EdgeTable::excludeRectangle (Rectangle<int> r)
auto bottom = clipped.getBottom() - bounds.getY();
const int rectLine[] = { 4, std::numeric_limits<int>::min(), 255,
clipped.getX() << 8, 0,
clipped.getRight() << 8, 255,
scale * clipped.getX(), 0,
scale * clipped.getRight(), 255,
std::numeric_limits<int>::max(), 0 };
for (int i = top; i < bottom; ++i)
@@ -800,7 +797,7 @@ void EdgeTable::clipLineToMask (int x, int y, const uint8* mask, int maskStride,
if (alpha != lastLevel)
{
tempLine[++destIndex] = (x << 8);
tempLine[++destIndex] = (x * scale);
tempLine[++destIndex] = alpha;
lastLevel = alpha;
}
@@ -810,7 +807,7 @@ void EdgeTable::clipLineToMask (int x, int y, const uint8* mask, int maskStride,
if (lastLevel > 0)
{
tempLine[++destIndex] = (x << 8);
tempLine[++destIndex] = (x * scale);
tempLine[++destIndex] = 0;
}


+ 12
- 8
modules/juce_graphics/geometry/juce_EdgeTable.h View File

@@ -122,7 +122,7 @@ public:
if (--numPoints > 0)
{
int x = *++line;
jassert ((x >> 8) >= bounds.getX() && (x >> 8) < bounds.getRight());
jassert ((x / scale) >= bounds.getX() && (x / scale) < bounds.getRight());
int levelAccumulator = 0;
iterationCallback.setEdgeTableYPos (bounds.getY() + y);
@@ -130,12 +130,12 @@ public:
while (--numPoints >= 0)
{
const int level = *++line;
jassert (isPositiveAndBelow (level, 256));
jassert (isPositiveAndBelow (level, scale));
const int endX = *++line;
jassert (endX >= x);
const int endOfRun = (endX >> 8);
const int endOfRun = (endX / scale);
if (endOfRun == (x >> 8))
if (endOfRun == (x / scale))
{
// small segment within the same pixel, so just save it for the next
// time round..
@@ -146,8 +146,8 @@ public:
// plot the fist pixel of this segment, including any accumulated
// levels from smaller segments that haven't been drawn yet
levelAccumulator += (0x100 - (x & 0xff)) * level;
levelAccumulator >>= 8;
x >>= 8;
levelAccumulator /= scale;
x /= scale;
if (levelAccumulator > 0)
{
@@ -174,11 +174,11 @@ public:
x = endX;
}
levelAccumulator >>= 8;
levelAccumulator /= scale;
if (levelAccumulator > 0)
{
x >>= 8;
x /= scale;
jassert (x >= bounds.getX() && x < bounds.getRight());
if (levelAccumulator >= 255)
@@ -191,6 +191,10 @@ public:
}
private:
//==============================================================================
static constexpr auto defaultEdgesPerLine = 32;
static constexpr auto scale = 256;
//==============================================================================
// table line format: number of points; point0 x, point0 levelDelta, point1 x, point1 levelDelta, etc
struct LineItem


Loading…
Cancel
Save