in wicket-extensions/src/main/java/org/apache/wicket/extensions/captcha/kittens/OpaqueRegion.java [181:284]
OpaqueRegion subtract(final OpaqueRegion removeRegion, final Point offset)
{
// Create new rectangle list
final List<Rectangle> newRectangles = new ArrayList<>();
// For each rectangle
for (final Rectangle rectangle : rectangles)
{
// Get y
final int y = rectangle.y;
// Work list starts with the current rectangle in this opaque region
final List<Rectangle> workList = new ArrayList<>();
workList.add(new Rectangle(rectangle));
// For each rectangle in the region to remove
for (final Rectangle remove : removeRegion.rectangles)
{
// Offset the rectangle
final Rectangle offsetRemove = new Rectangle(remove);
offsetRemove.translate(offset.x, offset.y);
// If we've gone past a possible match
if (offsetRemove.y > y)
{
// quit
break;
}
// If we're processing a rectangle on the right scan-line
if (offsetRemove.y == y)
{
// Get rectangle x1 and x2
int rx1 = offsetRemove.x;
int rx2 = offsetRemove.x + offsetRemove.width;
// Go through work list to remove the given rectangle
for (int i = 0; i < workList.size(); i++)
{
// Get rectangle from work list
final Rectangle work = workList.get(i);
// Get work x1, x2
int x1 = work.x;
int x2 = work.x + work.width;
// Compare left and right sides
if ((rx1 <= x1) && (rx2 >= x2))
{
// Whole rectangle is obscured
workList.remove(i);
i -= 1;
}
else
{
// Check which sides are in
boolean leftIn = (rx1 >= x1) && (rx1 < x2);
boolean rightIn = (rx2 > x1) && (rx2 <= x2);
if (leftIn)
{
if (rightIn)
{
// Split in two
if (rx1 - x1 > 0)
{
workList.set(i, new Rectangle(x1, y, rx1 - x1, 1));
}
if (x2 - rx2 > 0)
{
workList.add(i + 1, new Rectangle(rx2, y, x2 - rx2, 1));
}
}
else
{
// Chop off right side
if (rx1 - x1 > 0)
{
workList.set(i, new Rectangle(x1, y, rx1 - x1, 1));
}
}
}
else if (rightIn)
{
// Chop off left side
if (x2 - rx2 > 0)
{
workList.set(i, new Rectangle(rx2, y, x2 - rx2, 1));
}
}
}
}
}
}
// Add the rectangle(s) to the new list
newRectangles.addAll(workList);
}
// Return new opaque region
return new OpaqueRegion(newRectangles);
}