GClip.java
/*
* ..::jDrawingLib::..
*
* Copyright (C) Federico Vera 2012 - 2023 <[email protected]>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or any later
* version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.dkt.graphics.extras;
import com.dkt.graphics.elements.GFillableE;
import com.dkt.graphics.elements.GraphicE;
import java.awt.Graphics2D;
import java.awt.geom.Area;
import java.util.ArrayList;
/**
* This class wraps an {@link Area} in a {@link GraphicE}, in order to create
* a clipping area from {@link GFillableE}.
*
* @author Federico Vera {@literal<[email protected]>}
*/
public class GClip extends GraphicE {
private final ArrayList<Action> elements = new ArrayList<>();
private Area clip;
/**
* Copy constructor
*
* @param e {@code GClip} to copy
* @throws IllegalArgumentException if {@code e} is {@code null}
*/
public GClip(GClip e){
super(e);
elements.ensureCapacity(e.elements.size());
for (Action a : e.elements){
elements.add(new Action(a.e.clone(), a.a));
}
updateClip();
}
/**
* Basic {@code GClip} constructor
*/
public GClip() {
}
/**
* Constructs a {@code GClip} from a given area. Please note that when this
* constructor is used, then {@link GClip#traslate(int, int)} won't work.
* <br>If you really need to traslate a {@code GClip}, then you should
* previously add a {@link GTransform} to the graphic
*
* @param area {@link Area} object to be used as clip
* @throws IllegalArgumentException if {@code area} is {@code null}
*/
public GClip(Area area) {
if (area == null) {
throw new IllegalArgumentException("The area can't be null");
}
clip = area;
}
@Override
public void traslate(int x, int y) {
for (Action action : elements) {
action.e.traslate(x, y);
}
updateClip();
}
/**
* Adds the given element to the clipping area
*
* @param e element to add
*/
public void add(GFillableE e) {
elements.add(new Action(e, 0));
updateClip();
}
/**
* Subtracts the given element from the clipping area
*
* @param e element to subtract
*/
public void subtract(GFillableE e) {
elements.add(new Action(e, 1));
updateClip();
}
private void updateClip() {
if (elements.isEmpty()) {
return;
}
clip = new Area();
for (Action action : elements) {
if (action.a == 0) {
clip.add(action.e.getShape());
} else if (action.a == 1) {
clip.subtract(action.e.getShape());
}
}
}
@Override
public void draw(Graphics2D g) {
g.setClip(clip);
}
@Override
public GraphicE clone() {
return new GClip(this);
}
private record Action(GFillableE e, int a) {
}
}