/*
* Copyright 2015 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;
/**
* The simplest dabs strategy: it places the dabs along the lines
* connecting the mouse events with an uniform spacing between them
*/
public class LinearDabsStrategy implements DabsStrategy {
private final DabsBrush brush;
private double distanceFromLastDab = 0;
private SpacingStrategy spacingStrategy;
private AngleSettings angleSettings;
private final boolean refreshBrushForEachDab;
private double prevX = 0;
private double prevY = 0;
public LinearDabsStrategy(DabsBrush brush, SpacingStrategy spacingStrategy, AngleSettings angleSettings, boolean refreshBrushForEachDab) {
this.brush = brush;
this.spacingStrategy = spacingStrategy;
this.angleSettings = angleSettings;
this.refreshBrushForEachDab = refreshBrushForEachDab;
}
@Override
public void onDragStart(double x, double y) {
brush.setupBrushStamp(x, y);
distanceFromLastDab = 0; // moved from reset()
prevX = x;
prevY = y;
if (angleSettings.isAngleAware()) {
// For angle-aware brushes we don't draw a dab in this
// method because we have no angle information.
// However, we manipulate the distance from the last dab
// so that a dab is drawn soon
distanceFromLastDab = spacingStrategy.getSpacing(brush.getRadius()) * 0.8;
} else {
brush.putDab(x, y, 0);
}
}
@Override
public void onNewMousePoint(double endX, double endY) {
double dx = endX - prevX;
double dy = endY - prevY;
double lineDistance = Math.sqrt(dx * dx + dy * dy);
double spacing = spacingStrategy.getSpacing(brush.getRadius());
double relativeSpacingDistance = spacing / lineDistance;
double initialRelativeSpacingDistance = (spacing - distanceFromLastDab) / lineDistance;
double theta = 0;
if (angleSettings.isAngleAware()) {
theta = Math.atan2(dy, dx);
}
double x = prevX, y = prevY;
boolean drew = false;
for(double t = initialRelativeSpacingDistance; t < 1.0; t += relativeSpacingDistance) {
x = prevX + t * dx;
y = prevY + t * dy;
if(refreshBrushForEachDab) {
brush.setupBrushStamp(x, y);
}
if (angleSettings.shouldJitterAngle()) {
theta = angleSettings.calculatePerturbedAngle(theta);
}
brush.putDab(x, y, theta);
drew = true;
}
if(drew) {
double remainingDx = (endX - x);
double remainingDy = (endY - y);
distanceFromLastDab = Math.sqrt(remainingDx * remainingDx + remainingDy * remainingDy);
} else {
distanceFromLastDab += lineDistance;
}
prevX = endX;
prevY = endY;
}
@Override
public void settingsChanged() {
DabsBrushSettings settings = brush.getSettings();
angleSettings = settings.getAngleSettings();
spacingStrategy = settings.getSpacingStrategy();
// assert spacingStrategy.isValid();
}
}