📄 cpartwork.java
字号:
public CPLayer getLayer(int i) {
if (i < 0 || i >= layers.size()) {
return null;
}
return layers.get(i);
}
//
// Undo / Redo
//
public void undo() {
if (!canUndo()) {
return;
}
CPUndo undo = undoList.removeFirst();
undo.undo();
redoList.addFirst(undo);
}
public void redo() {
if (!canRedo()) {
return;
}
CPUndo redo = redoList.removeFirst();
redo.redo();
undoList.addFirst(redo);
}
public boolean canUndo() {
return !undoList.isEmpty();
}
public boolean canRedo() {
return !redoList.isEmpty();
}
private void addUndo(CPUndo undo) {
if (undoList.isEmpty() || !(undoList.getFirst()).merge(undo)) {
if (undoList.size() >= maxUndo) {
undoList.removeLast();
}
undoList.addFirst(undo);
} else {
// Two merged changes can mean no change at all
// don't leave a useless undo in the list
if ((undoList.getFirst()).noChange()) {
undoList.removeFirst();
}
}
if (!redoList.isEmpty()) {
redoList = new LinkedList();
}
}
public void clearHistory() {
undoList = new LinkedList();
redoList = new LinkedList();
Runtime r = Runtime.getRuntime();
r.gc();
}
//
//
//
public int colorPicker(float x, float y) {
// not really necessary and could potentially the repaint
// of the canvas to miss that area
// fusionLayers();
return fusion.getPixel((int) x, (int) y) & 0xffffff;
}
public boolean isPointWithin(float x, float y) {
return x >= 0 && y >= 0 && (int) x < width && (int) y < height;
}
// FIXME: 2007-01-13 I'm moving this to the CPRect class
// find where this version is used and change the
// code to use the CPRect version
public void clipSourceDest(CPRect srcRect, CPRect dstRect) {
// FIXME:
// /!\ dstRect bottom and right are ignored and instead we clip
// against the width, height of the layer. :/
//
// this version would be enough in most cases (when we don't need
// srcRect bottom and right to be clipped)
// it's left here in case it's needed to make a faster version
// of this function
// dstRect.right = Math.min(width, dstRect.left + srcRect.getWidth());
// dstRect.bottom = Math.min(height, dstRect.top + srcRect.getHeight());
// new dest bottom/right
dstRect.right = dstRect.left + srcRect.getWidth();
if (dstRect.right > width) {
srcRect.right -= dstRect.right - width;
dstRect.right = width;
}
dstRect.bottom = dstRect.top + srcRect.getHeight();
if (dstRect.bottom > height) {
srcRect.bottom -= dstRect.bottom - height;
dstRect.bottom = height;
}
// new src top/left
if (dstRect.left < 0) {
srcRect.left -= dstRect.left;
dstRect.left = 0;
}
if (dstRect.top < 0) {
srcRect.top -= dstRect.top;
dstRect.top = 0;
}
}
public Object[] getLayers() {
return layers.toArray();
}
public int getLayersNb() {
return layers.size();
}
public CPRect getSize() {
return new CPRect(width, height);
}
//
// Selection methods
//
// Gets the current selection rect or a rectangle covering the whole canvas if there are no selections
public CPRect getSelectionAutoSelect() {
CPRect r;
if (!curSelection.isEmpty()) {
r = (CPRect) curSelection.clone();
} else {
r = getSize();
}
return r;
}
// Gets the current selection rect
public CPRect getSelection() {
return (CPRect) curSelection.clone();
}
void setSelection(CPRect r) {
curSelection.set(r);
curSelection.clip(getSize());
}
void emptySelection() {
curSelection.makeEmpty();
}
//
//
//
public void invalidateFusion(CPRect r) {
fusionArea.union(r);
callListenersUpdateRegion(r);
}
public void invalidateFusion() {
invalidateFusion(new CPRect(0, 0, width, height));
}
public void setLayerVisibility(int layer, boolean visible) {
addUndo(new CPUndoLayerVisible(layer, getLayer(layer).visible, visible));
getLayer(layer).visible = visible;
invalidateFusion();
callListenersLayerChange();
}
public void addLayer() {
addUndo(new CPUndoAddLayer(activeLayer));
CPLayer newLayer = new CPLayer(width, height);
newLayer.name = getDefaultLayerName();
layers.add(activeLayer + 1, newLayer);
setActiveLayer(activeLayer + 1);
invalidateFusion();
callListenersLayerChange();
}
public void removeLayer() {
if (layers.size() > 1) {
addUndo(new CPUndoRemoveLayer(activeLayer, curLayer));
layers.remove(activeLayer);
setActiveLayer(activeLayer < layers.size() ? activeLayer : activeLayer - 1);
invalidateFusion();
callListenersLayerChange();
}
}
public void duplicateLayer() {
String copySuffix = " Copy";
addUndo(new CPUndoDuplicateLayer(activeLayer));
CPLayer newLayer = new CPLayer(width, height);
newLayer.copyFrom(layers.elementAt(activeLayer));
if (!newLayer.name.endsWith(copySuffix)) {
newLayer.name += copySuffix;
}
layers.add(activeLayer + 1, newLayer);
setActiveLayer(activeLayer + 1);
invalidateFusion();
callListenersLayerChange();
}
public void mergeDown(boolean createUndo) {
if (layers.size() > 0 && activeLayer > 0) {
if (createUndo) {
addUndo(new CPUndoMergeDownLayer(activeLayer));
}
layers.elementAt(activeLayer).fusionWithFullAlpha(layers.elementAt(activeLayer - 1),
new CPRect(width, height));
layers.remove(activeLayer);
setActiveLayer(activeLayer - 1);
invalidateFusion();
callListenersLayerChange();
}
}
public void mergeAllLayers(boolean createUndo) {
if (layers.size() > 1) {
if (createUndo) {
addUndo(new CPUndoMergeAllLayers());
}
fusionLayers();
layers.clear();
CPLayer layer = new CPLayer(width, height);
layer.name = getDefaultLayerName();
layer.copyDataFrom(fusion);
layers.add(layer);
setActiveLayer(0);
invalidateFusion();
callListenersLayerChange();
}
}
public void moveLayer(int from, int to) {
if (from < 0 || from >= getLayersNb() || to < 0 || to > getLayersNb() || from == to) {
return;
}
addUndo(new CPUndoMoveLayer(from, to));
moveLayerReal(from, to);
}
private void moveLayerReal(int from, int to) {
CPLayer layer = layers.remove(from);
if (to <= from) {
layers.add(to, layer);
setActiveLayer(to);
} else {
layers.add(to - 1, layer);
setActiveLayer(to - 1);
}
invalidateFusion();
callListenersLayerChange();
}
public void setLayerAlpha(int layer, int alpha) {
if (getLayer(layer).getAlpha() != alpha) {
addUndo(new CPUndoLayerAlpha(layer, alpha));
getLayer(layer).setAlpha(alpha);
invalidateFusion();
callListenersLayerChange();
}
}
public void setBlendMode(int layer, int blendMode) {
if (getLayer(layer).getBlendMode() != blendMode) {
addUndo(new CPUndoLayerMode(layer, blendMode));
getLayer(layer).setBlendMode(blendMode);
invalidateFusion();
callListenersLayerChange();
}
}
public void setLayerName(int layer, String name) {
if (getLayer(layer).name != name) {
addUndo(new CPUndoLayerRename(layer, name));
getLayer(layer).name = name;
callListenersLayerChange();
}
}
public void floodFill(float x, float y) {
undoBuffer.copyFrom(curLayer);
undoArea = new CPRect(width, height);
curLayer.floodFill((int) x, (int) y, curColor | 0xff000000);
addUndo(new CPUndoPaint());
invalidateFusion();
}
public void fill(int color) {
CPRect r = getSelectionAutoSelect();
undoBuffer.copyFrom(curLayer);
undoArea = r;
curLayer.clear(r, color);
addUndo(new CPUndoPaint());
invalidateFusion();
}
public void clear() {
fill(0xffffff);
}
public void hFlip() {
CPRect r = getSelectionAutoSelect();
undoBuffer.copyFrom(curLayer);
undoArea = r;
curLayer.copyRegionHFlip(r, undoBuffer);
addUndo(new CPUndoPaint());
invalidateFusion();
}
public void vFlip() {
CPRect r = getSelectionAutoSelect();
undoBuffer.copyFrom(curLayer);
undoArea = r;
curLayer.copyRegionVFlip(r, undoBuffer);
addUndo(new CPUndoPaint());
invalidateFusion();
}
public void monochromaticNoise() {
CPRect r = getSelectionAutoSelect();
undoBuffer.copyFrom(curLayer);
undoArea = r;
curLayer.fillWithNoise(r);
addUndo(new CPUndoPaint());
invalidateFusion();
}
public void colorNoise() {
CPRect r = getSelectionAutoSelect();
undoBuffer.copyFrom(curLayer);
undoArea = r;
curLayer.fillWithColorNoise(r);
addUndo(new CPUndoPaint());
invalidateFusion();
}
public void boxBlur(int radiusX, int radiusY, int iterations) {
CPRect r = getSelectionAutoSelect();
undoBuffer.copyFrom(curLayer);
undoArea = r;
for (int c = 0; c < iterations; c++) {
curLayer.boxBlur(r, radiusX, radiusY);
}
addUndo(new CPUndoPaint());
invalidateFusion();
}
public void invert() {
CPRect r = getSelectionAutoSelect();
undoBuffer.copyFrom(curLayer);
undoArea = r;
curLayer.invert(r);
addUndo(new CPUndoPaint());
invalidateFusion();
}
public void rectangleSelection(CPRect r) {
CPRect newSelection = (CPRect) r.clone();
newSelection.clip(getSize());
addUndo(new CPUndoRectangleSelection(getSelection(), newSelection));
setSelection(newSelection);
}
public void beginPreviewMode(boolean copy) {
// !!!! awful awful hack !!! will break as soon as CPMultiUndo is used for other things
// FIXME: ASAP!
if (!copy && !undoList.isEmpty() && redoList.isEmpty() && (undoList.getFirst() instanceof CPMultiUndo)
&& (((CPMultiUndo) undoList.getFirst()).undoes[0] instanceof CPUndoPaint)
&& ((CPUndoPaint) ((CPMultiUndo) undoList.getFirst()).undoes[0]).layer == getActiveLayerNb()) {
undo();
copy = prevModeCopy;
} else {
movePrevX = 0;
movePrevY = 0;
undoBuffer.copyFrom(curLayer);
undoArea.makeEmpty();
opacityBuffer.clear();
opacityArea.makeEmpty();
}
moveInitSelect = null;
moveModeCopy = copy;
}
public void endPreviewMode() {
CPUndo undo = new CPUndoPaint();
if (moveInitSelect != null) {
CPUndo[] undoArray = { undo, new CPUndoRectangleSelection(moveInitSelect, getSelection()) };
undo = new CPMultiUndo(undoArray);
} else {
// !!!!!!
// FIXME: this is required just to make the awful move hack work
CPUndo[] undoArray = { undo };
undo = new CPMultiUndo(undoArray);
}
addUndo(undo);
moveInitSelect = null;
movePrevX = movePrevX2;
movePrevY = movePrevY2;
prevModeCopy = moveModeCopy;
}
// temp awful hack
CPRect moveInitSelect = null;
int movePrevX, movePrevY, movePrevX2, movePrevY2;
boolean moveModeCopy, prevModeCopy;
public void move(int offsetX, int offsetY) {
CPRect srcRect;
offsetX += movePrevX;
offsetY += movePrevY;
if (moveInitSelect == null) {
srcRect = getSelectionAutoSelect();
if (!getSelection().isEmpty()) {
moveInitSelect = getSelection();
}
} else {
srcRect = (CPRect) moveInitSelect.clone();
}
curLayer.copyFrom(undoBuffer);
if (!moveModeCopy) {
curLayer.clear(srcRect, 0);
}
curLayer.pasteAlphaRect(undoBuffer, srcRect, srcRect.left + offsetX, srcRect.top + offsetY);
undoArea = new CPRect();
if (!moveModeCopy) {
undoArea.union(srcRect);
}
srcRect.translate(offsetX, offsetY);
undoArea.union(srcRect);
invalidateFusion();
if (moveInitSelect != null) {
CPRect sel = (CPRect) moveInitSelect.clone();
sel.translate(offsetX, offsetY);
setSelection(sel);
}
// this is a really bad idea :D
movePrevX2 = offsetX;
movePrevY2 = offsetY;
}
// ////
// Copy/Paste
public void cutSelection(boolean createUndo) {
CPRect sel = getSelection();
if (sel.isEmpty()) {
return;
}
clipboard = new CPClip(new CPColorBmp(curLayer, sel), sel.left, sel.top);
if (createUndo) {
addUndo(new CPUndoCut(clipboard.bmp, sel.left, sel.top, getActiveLayerNb(), sel));
}
curLayer.clear(sel, 0);
invalidateFusion();
}
public void copySelection() {
CPRect sel = getSelection();
if (sel.isEmpty()) {
return;
}
clipboard = new CPClip(new CPColorBmp(curLayer, sel), sel.left, sel.top);
}
public void copySelectionMerged() {
CPRect sel = getSelection();
if (sel.isEmpty()) {
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -