mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
EdgeTable: Avoid integer truncation when rendering paths with large coordinates
Previously, if the PathFlatteningIterator returned a line segment with
very large x or y positions, the result of
roundToInt (iter.y1 * 256.0f)
could be incorrect, if the result was too large to fit in an int.
Using int64_t to store intermediate results, converting to int when
updating the edge table itself produces accurate results for a wider
range of inputs.
This commit is contained in:
parent
059d98507c
commit
4f67a18a3f
1 changed files with 10 additions and 14 deletions
|
|
@ -46,17 +46,17 @@ EdgeTable::EdgeTable (Rectangle<int> area, const Path& path, const AffineTransfo
|
||||||
t += lineStrideElements;
|
t += lineStrideElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto leftLimit = scale * bounds.getX();
|
auto leftLimit = scale * static_cast<int64_t> (bounds.getX());
|
||||||
auto topLimit = scale * bounds.getY();
|
auto topLimit = scale * static_cast<int64_t> (bounds.getY());
|
||||||
auto rightLimit = scale * bounds.getRight();
|
auto rightLimit = scale * static_cast<int64_t> (bounds.getRight());
|
||||||
auto heightLimit = scale * bounds.getHeight();
|
auto heightLimit = scale * static_cast<int64_t> (bounds.getHeight());
|
||||||
|
|
||||||
PathFlatteningIterator iter (path, transform);
|
PathFlatteningIterator iter (path, transform);
|
||||||
|
|
||||||
while (iter.next())
|
while (iter.next())
|
||||||
{
|
{
|
||||||
auto y1 = roundToInt (iter.y1 * 256.0f);
|
auto y1 = static_cast<int64_t> (iter.y1 * 256.0f);
|
||||||
auto y2 = roundToInt (iter.y2 * 256.0f);
|
auto y2 = static_cast<int64_t> (iter.y2 * 256.0f);
|
||||||
|
|
||||||
if (y1 != y2)
|
if (y1 != y2)
|
||||||
{
|
{
|
||||||
|
|
@ -82,19 +82,15 @@ EdgeTable::EdgeTable (Rectangle<int> area, const Path& path, const AffineTransfo
|
||||||
{
|
{
|
||||||
const double startX = 256.0f * iter.x1;
|
const double startX = 256.0f * iter.x1;
|
||||||
const double multiplier = (iter.x2 - iter.x1) / (iter.y2 - iter.y1);
|
const double multiplier = (iter.x2 - iter.x1) / (iter.y2 - iter.y1);
|
||||||
auto stepSize = jlimit (1, 256, 256 / (1 + (int) std::abs (multiplier)));
|
auto stepSize = static_cast<int64_t> (jlimit (1, 256, 256 / (1 + (int) std::abs (multiplier))));
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
auto step = jmin (stepSize, y2 - y1, 256 - (y1 & 255));
|
auto step = jmin (stepSize, y2 - y1, 256 - (y1 & 255));
|
||||||
auto x = roundToInt (startX + multiplier * ((y1 + (step >> 1)) - startY));
|
auto x = static_cast<int64_t> (startX + multiplier * static_cast<double> ((y1 + (step >> 1)) - startY));
|
||||||
|
auto clampedX = static_cast<int> (jlimit (leftLimit, rightLimit - 1, x));
|
||||||
|
|
||||||
if (x < leftLimit)
|
addEdgePoint (clampedX, static_cast<int> (y1 / scale), static_cast<int> (direction * step));
|
||||||
x = leftLimit;
|
|
||||||
else if (x >= rightLimit)
|
|
||||||
x = rightLimit - 1;
|
|
||||||
|
|
||||||
addEdgePoint (x, y1 / scale, direction * step);
|
|
||||||
y1 += step;
|
y1 += step;
|
||||||
}
|
}
|
||||||
while (y1 < y2);
|
while (y1 < y2);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue