|
70 | 70 | import java.util.Optional; |
71 | 71 | import java.util.concurrent.CompletableFuture; |
72 | 72 | import java.util.function.Consumer; |
| 73 | +import java.util.function.Predicate; |
73 | 74 |
|
74 | 75 | import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE; |
75 | 76 | import static java.lang.String.format; |
| 77 | +import static java.util.stream.Collectors.toList; |
76 | 78 | import static pixelitor.Composition.ImageChangeActions.FULL; |
77 | 79 | import static pixelitor.Composition.LayerAdder.Position.ABOVE_ACTIVE; |
78 | 80 | import static pixelitor.Composition.LayerAdder.Position.BELLOW_ACTIVE; |
@@ -384,21 +386,17 @@ public void mergeDown(Layer layer, boolean updateGUI) { |
384 | 386 | BufferedImage bellowImage = bellowLayer.getImage(); |
385 | 387 | Graphics2D g = bellowImage.createGraphics(); |
386 | 388 | g.translate(-bellowLayer.getTX(), -bellowLayer.getTY()); |
387 | | - BufferedImage result = activeLayer.applyLayer(g, bellowImage, false); |
| 389 | + BufferedImage result = layer.applyLayer(g, bellowImage, false); |
388 | 390 | if (result != null) { // this was an adjustment |
389 | 391 | bellowLayer.setImage(result); |
390 | 392 | } |
391 | 393 | g.dispose(); |
392 | 394 |
|
393 | 395 | bellowLayer.updateIconImage(); |
394 | 396 |
|
395 | | - // keep the reference because after deleting the |
396 | | - // active merged layer, another layer will become active |
397 | | - Layer mergedLayer = activeLayer; |
| 397 | + deleteLayer(layer, false, updateGUI); |
398 | 398 |
|
399 | | - deleteActiveLayer(updateGUI, false); |
400 | | - |
401 | | - History.addEdit(new MergeDownEdit(this, mergedLayer, |
| 399 | + History.addEdit(new MergeDownEdit(this, layer, |
402 | 400 | bellowLayer, imageBefore, maskViewModeBefore, layerIndex)); |
403 | 401 | } |
404 | 402 |
|
@@ -471,9 +469,10 @@ public void setActiveLayer(Layer newActiveLayer, boolean updateGUI, boolean addT |
471 | 469 | if (addToHistory) { |
472 | 470 | History.addEdit(new LayerSelectionChangeEdit( |
473 | 471 | editName, this, oldLayer, newActiveLayer)); |
| 472 | + } |
474 | 473 |
|
475 | | - // shouldn't run in initialization code |
476 | | - Tools.imageChanged(activeLayer); |
| 474 | + if(view != null) { // shouldn't run while loading the composition |
| 475 | + Tools.editedObjectChanged(activeLayer); |
477 | 476 | } |
478 | 477 |
|
479 | 478 | assert checkInvariant(); |
@@ -507,6 +506,20 @@ public int getNumLayers() { |
507 | 506 | return layerList.size(); |
508 | 507 | } |
509 | 508 |
|
| 509 | + public int getNumLayers(Predicate<Layer> condition) { |
| 510 | + return (int) layerList.stream() |
| 511 | + .filter(condition) |
| 512 | + .count(); |
| 513 | + } |
| 514 | + |
| 515 | + public int getNumImageLayers() { |
| 516 | + return getNumLayers(layer -> layer instanceof ImageLayer); |
| 517 | + } |
| 518 | + |
| 519 | + public int getNumTextLayers() { |
| 520 | + return getNumLayers(layer -> layer instanceof TextLayer); |
| 521 | + } |
| 522 | + |
510 | 523 | public void forEachLayer(Consumer<Layer> action) { |
511 | 524 | layerList.forEach(action); |
512 | 525 | } |
@@ -535,6 +548,21 @@ public void updateAllIconImages() { |
535 | 548 | forEachDrawable(Drawable::updateIconImage); |
536 | 549 | } |
537 | 550 |
|
| 551 | + public void rasterizeAllTextLayers() { |
| 552 | + assert view == null; |
| 553 | + |
| 554 | + // create a separate copy to avoid modification |
| 555 | + // of the original list while iterating |
| 556 | + List<TextLayer> textLayers = layerList.stream() |
| 557 | + .filter(layer -> layer instanceof TextLayer) |
| 558 | + .map(layer -> (TextLayer) layer) |
| 559 | + .collect(toList()); |
| 560 | + |
| 561 | + for (TextLayer textLayer : textLayers) { |
| 562 | + textLayer.replaceWithRasterized(false, false); |
| 563 | + } |
| 564 | + } |
| 565 | + |
538 | 566 | public boolean activeIsDrawable() { |
539 | 567 | if (activeLayer instanceof ImageLayer) { |
540 | 568 | return true; |
@@ -1071,9 +1099,14 @@ public void invertSelection() { |
1071 | 1099 | if (selection != null) { |
1072 | 1100 | Shape backupShape = selection.getShape(); |
1073 | 1101 | Shape inverted = canvas.invertShape(backupShape); |
1074 | | - selection.setShape(inverted); |
1075 | | - History.addEdit(new SelectionShapeChangeEdit( |
1076 | | - "Invert Selection", this, backupShape)); |
| 1102 | + if(inverted.getBounds2D().isEmpty()) { |
| 1103 | + // presumably everything was selected, and now nothing is |
| 1104 | + deselect(true); |
| 1105 | + } else { |
| 1106 | + selection.setShape(inverted); |
| 1107 | + History.addEdit(new SelectionShapeChangeEdit( |
| 1108 | + "Invert Selection", this, backupShape)); |
| 1109 | + } |
1077 | 1110 | } |
1078 | 1111 | } |
1079 | 1112 |
|
@@ -1266,16 +1299,6 @@ public boolean checkInvariant() { |
1266 | 1299 | return true; |
1267 | 1300 | } |
1268 | 1301 |
|
1269 | | - public int getNumImageLayers() { |
1270 | | - int count = 0; |
1271 | | - for (Layer layer : layerList) { |
1272 | | - if (layer instanceof ImageLayer) { |
1273 | | - count++; |
1274 | | - } |
1275 | | - } |
1276 | | - return count; |
1277 | | - } |
1278 | | - |
1279 | 1302 | public int calcNumImages() { |
1280 | 1303 | int count = 0; |
1281 | 1304 | for (Layer layer : layerList) { |
|
0 commit comments