diff --git a/modules/juce_graphics/geometry/juce_EdgeTable.cpp b/modules/juce_graphics/geometry/juce_EdgeTable.cpp index 268fd88fc2..f9f1688c81 100644 --- a/modules/juce_graphics/geometry/juce_EdgeTable.cpp +++ b/modules/juce_graphics/geometry/juce_EdgeTable.cpp @@ -28,15 +28,12 @@ namespace juce JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6255 6263 6386) -const int juce_edgeTableDefaultEdgesPerLine = 32; - -//============================================================================== EdgeTable::EdgeTable (Rectangle 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 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 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 area, const Path& path, const AffineTransfo EdgeTable::EdgeTable (Rectangle 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 rectangleToAdd) EdgeTable::EdgeTable (const RectangleList& 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& 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& 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& rectanglesToAdd) EdgeTable::EdgeTable (Rectangle 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 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 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 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 r) auto bottom = clipped.getBottom() - bounds.getY(); const int rectLine[] = { 4, std::numeric_limits::min(), 255, - clipped.getX() << 8, 0, - clipped.getRight() << 8, 255, + scale * clipped.getX(), 0, + scale * clipped.getRight(), 255, std::numeric_limits::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; } diff --git a/modules/juce_graphics/geometry/juce_EdgeTable.h b/modules/juce_graphics/geometry/juce_EdgeTable.h index 8f474a53e9..ca7a5270e1 100644 --- a/modules/juce_graphics/geometry/juce_EdgeTable.h +++ b/modules/juce_graphics/geometry/juce_EdgeTable.h @@ -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