/* * Copyright 2017 Laszlo Balazs-Csiki * * This file is part of Pixelitor. Pixelitor is free software: you * can redistribute it and/or modify it under the terms of the GNU * General Public License, version 3 as published by the Free * Software Foundation. * * Pixelitor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Pixelitor. If not, see <http://www.gnu.org/licenses/>. */ package pixelitor.tools.brushes; import pixelitor.Composition; import pixelitor.utils.debug.DebugNode; import java.awt.Graphics2D; import java.awt.Rectangle; /** * Tracks the area affected by a brush for the undo * Can be used as a decorator to other brushes */ public class BrushAffectedArea implements Brush { // affected area coordinates private double minX = 0; private double minY = 0; private double maxX = 0; private double maxY = 0; private Brush delegate; public BrushAffectedArea(Brush delegate) { this.delegate = delegate; } // this constructor is used when this object is not used as a brush delegate public BrushAffectedArea() { } public void updateAffectedCoordinates(double x, double y) { if(x > maxX) { maxX = x; } else if(x < minX) { minX = x; } if(y > maxY) { maxY = y; } else if(y < minY) { minY = y; } } public void initAffectedCoordinates(double x, double y) { minX = x; minY = y; maxX = x; maxY = y; } /** * Calculates the rectangle affected by a brush stroke for the undo mechanism */ public Rectangle getRectangleAffectedByBrush(int radius) { // To be on the safe side, save a little more than necessary - some brushes have randomness int radius2 = 2 * radius; int radius4 = 4 * radius; double saveX = minX - radius2; double saveY = minY - radius2; double saveWidth = maxX - minX + radius4; double saveHeight = maxY - minY + radius4; return new Rectangle((int) saveX, (int) saveY, (int) saveWidth, (int) saveHeight); } @Override public void setTarget(Composition comp, Graphics2D g) { delegate.setTarget(comp, g); } @Override public void setRadius(int radius) { delegate.setRadius(radius); } @Override public void onDragStart(double x, double y) { updateAffectedCoordinates(x, y); delegate.onDragStart(x, y); } @Override public void onNewMousePoint(double x, double y) { updateAffectedCoordinates(x, y); delegate.onNewMousePoint(x, y); } @Override public DebugNode getDebugNode() { DebugNode node = new DebugNode("Brush Affected Area", this); node.addDoubleChild("minX", minX); node.addDoubleChild("minY", minY); node.addDoubleChild("maxX", maxX); node.addDoubleChild("maxY", maxY); if (delegate != null) { node.add(delegate.getDebugNode()); } else { node.addStringChild("delegate", "null"); } return node; } }