App
Image.java
Go to the documentation of this file.
1 package mhr.appcore.image;
2 
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.InvocationTargetException;
5 import java.util.ArrayList;
6 import java.util.LinkedList;
7 
8 import org.w3c.dom.Document;
9 import org.w3c.dom.Element;
10 import org.w3c.dom.NodeList;
11 
12 import mhr.appcore.bitmap.BitmapInfo;
13 import mhr.appcore.bitmap.ChannelCount;
14 import mhr.appcore.bitmap.ColorMode;
15 import mhr.appcore.bitmap.Depth;
16 import mhr.appcore.bitmap.NBitmap;
17 import mhr.appcore.bitmap.exceptions.BitmapAllocationException;
18 import mhr.appcore.bitmap.exceptions.UnsupportedBitmapException;
19 import mhr.appcore.blending.BlendMode;
20 import mhr.appcore.blending.Blender;
21 import mhr.appcore.exceptions.AllocationException;
22 import mhr.appcore.tools.Tool;
23 import mhr.appcore.image.exceptions.ImageException;
24 import mhr.appcore.image.exceptions.ImageLoadingException;
25 import mhr.appcore.image.exceptions.ImageSavingException;
26 import mhr.appcore.image.exceptions.ImageStateException;
27 import mhr.appcore.image.exceptions.LayerCreationException;
28 import mhr.appcore.image.exceptions.LayerNotFoundException;
29 import mhr.appcore.image.layers.ColorLayer;
30 import mhr.appcore.image.layers.Layer;
31 import mhr.appcore.image.layers.LayerPDInfo;
32 import mhr.appcore.image.layers.LayerType;
33 import mhr.appcore.image.layers.RasterLayer;
34 import mhr.appcore.image.layers.filter.DifferenceOfGaussianSharpenFilterLayer;
35 import mhr.appcore.image.layers.filter.GaussianBlurFilterLayer;
36 import mhr.appcore.image.layers.filter.GaussianSharpenFilterLayer;
37 import mhr.appcore.image.layers.filter.LaplaceSharpenFilterLayer;
38 import mhr.appcore.image.layers.filter.LaplacianOfGaussianSharpenFilterLayer;
39 import mhr.appcore.image.layers.lut.BrightnessLUTLayer;
40 import mhr.appcore.image.layers.lut.ContrastLUTLayer;
41 import mhr.appcore.image.layers.lut.CurvesLUTLayer;
42 import mhr.appcore.image.layers.lut.GammaLUTLayer;
43 import mhr.appcore.interfaces.ImageFile;
44 import mhr.appcore.interfaces.PDBitmap;
45 import mhr.appcore.interfaces.PDImageDataPresentation;
46 import mhr.appcore.interpolators.Interpolator;
47 import mhr.appcore.interpolators.InterpolatorType;
48 import mhr.appcore.utils.Rect;
49 
54 public class Image {
55 
56  //===== INTERFACES, CLASSES, ENUMS ==========================================================================================================//
57  //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
61  protected class FileConstants {
62  public static final String ROOT_NODE = "Image";
63  public static final String INFO_NODE = "ImageInfo";
64  public static final String WIDTH_NODE = "Width";
65  public static final String HEIGHT_NODE = "Height";
66  public static final String DEPTH_NODE = "Depth";
67  public static final String NEXT_ID_NODE = "NextId";
68  public static final String SELECTED_STATE_NODE = "SelectedState";
69  public static final String SELECTED_LAYER_ID_NODE = "SelectedLayerId";
70  public static final String MASTER_MASK_ACTIVE_NODE = "MasterMaskActive";
71  public static final String IMAGE_LAYERS_NODE = "ImageLayers";
72  public static final String LAYER_NODE = "Layer";
73  public static final String LAYER_TYPE_NODE = "LayerType";
74 
75  public static final String MASTER_MASK_FILE_NAME = "master_mask";
76  }
77 
81  protected class UndoPatch {
83  protected int id;
84  protected Rect area;
85  protected NBitmap patch = null;
86 
91  public Rect getArea() {
92  return new Rect(area);
93  }
94 
99  public int getId() {
100  return id;
101  }
102 
108  return state;
109  }
110 
118  public UndoPatch(NBitmap from) {
120  id = selectedLayerId;
121  if (canvasChangedArea.getWidth() > 0 && canvasChangedArea.getHeight() > 0) { // Jinak se nealokuje bitmapa
122  area = new Rect(canvasChangedArea);
123  BitmapInfo i = from.getInfo();
125  from.copyTo(patch, area, 0, 0);
126  }
127  }
128 
136  public UndoPatch(NBitmap from, Rect fromArea, ImageSelectedState state, int id) {
137  this.state = state;
138  this.id = id;
139  if (fromArea.getWidth() > 0 && fromArea.getHeight() > 0) { // Jinak se nealokuje bitmapa
140  area = new Rect(fromArea);
141  BitmapInfo i = from.getInfo();
143  from.copyTo(patch, area, 0, 0);
144  }
145  }
146 
151  public boolean apply() {
152  if (patch == null || canvasOwner != null) {
153  return false;
154  }
155  NBitmap target = null;
156  switch (state) {
157  case SELECTED_LAYER:
158  try {
159  Layer l = getLayer(id);
160  target = ((RasterLayer)l).getBitmap();
161  } catch (LayerNotFoundException e) {
162  return false;
163  } catch (ClassCastException e) {
164  throw new ImageException("Bad undo action - not RasterLayer");
165  }
166  break;
167 
168  case SELECTED_MASK:
169  try {
170  Layer l = getLayer(id);
171  target = l.getMask(false);
172  } catch (LayerNotFoundException e) {
173  return false;
174  }
175 
176  break;
177 
178  case SELECTED_MASTER_MASK:
179  target = masterMask;
180  break;
181 
182  case SELECTED_NONE:
183  return false;
184  }
185 
186  if (target == null ) {
187  return false;
188  }
189 
190  NBitmap tmp = new NBitmap(patch.getInfo());
191  target.copyTo(tmp, area, 0, 0);
192  patch.copyTo(target, patch.getRect(), area.tlx, area.tly);
193  patch.dispose();
194  patch = tmp;
195  return true;
196  }
200  public void dispose() {
201  if (patch != null) {
202  patch.dispose();
203  patch = null;
204  }
205  }
206  }
207 
208  //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
209 
210 
211 
212  //===== FIELDS ==============================================================================================================================//
213  //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
214  protected int width;
215  protected int height;
216  protected Depth depth;
217  protected ArrayList<Layer> layers = new ArrayList<Layer>();
218  protected int nextId = 0;
219  protected NBitmap canvas;
220  protected RasterLayer tmpLayer;
221  protected NBitmap masterMask;
223  protected int selectedLayerId;
224  protected boolean masterMaskActive;
225  protected Tool canvasOwner = null;
226 
232  protected LinkedList<Rect> toBeRendered = new LinkedList<Rect>();
235 
239  protected int extraMargins;
240  protected UndoPatch patch = null;
241  protected NBitmap clipBoard = null;
242 
243  //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
244 
245 
246  //===== CONSTRUCTORS, DESTRUCTORS, RELATED METHODS ==========================================================================================//
247  //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
248  @Override
249  protected void finalize() throws Throwable {
250  dispose();
251  super.finalize();
252  }
253 
254  //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
262  BitmapInfo i = from.getInfo();
264  throw new UnsupportedBitmapException("Could not create image from supplied bitmap");
265  }
266  this.width = i.width;
267  this.height = i.height;
268  this.depth = i.depth;
269 
271  NBitmap tmp = new NBitmap(from);
272  tmp.copyTo(l.getBitmap(), tmp.getRect(), 0, 0);
273  tmp.dispose();
274 
275  layers.add(l);
278 
282 
284  }
285 
292  try {
293 
294  FileConstants c = new FileConstants();
295  Document d = null;
296  Element r = null;
297  Element ii = null;
298  Element il = null;
299 
300  try {
301  d = f.getDocument();
302  r = (Element) d.getElementsByTagName(c.ROOT_NODE).item(0);
303  ii = (Element) r.getElementsByTagName(c.INFO_NODE).item(0);
304  il = (Element) r.getElementsByTagName(c.IMAGE_LAYERS_NODE).item(0);
305  width = Integer.parseInt(ii.getElementsByTagName(c.WIDTH_NODE).item(0).getTextContent());
306  height = Integer.parseInt(ii.getElementsByTagName(c.HEIGHT_NODE).item(0).getTextContent());
307  depth = Depth.valueOf(ii.getElementsByTagName(c.DEPTH_NODE).item(0).getTextContent());
308  nextId = Integer.parseInt(ii.getElementsByTagName(c.NEXT_ID_NODE).item(0).getTextContent());
309  selectedState = ImageSelectedState.valueOf(ii.getElementsByTagName(c.SELECTED_STATE_NODE).item(0).getTextContent());
310  selectedLayerId = Integer.parseInt(ii.getElementsByTagName(c.SELECTED_LAYER_ID_NODE).item(0).getTextContent());
311  masterMaskActive = Boolean.parseBoolean(ii.getElementsByTagName(c.MASTER_MASK_ACTIVE_NODE).item(0).getTextContent());
312  } catch (ClassCastException e) {
313  throw new ImageLoadingException("Supplied xml doesn't describe image");
314  } catch (NullPointerException e) {
315  throw new ImageLoadingException("Supplied xml doesn't describe image");
316  }
317 
318  try {
320 
321  PDBitmap tmpMask = null;
322  NBitmap tmp = null;
323  try {
324  tmpMask = f.loadBitmap(c.MASTER_MASK_FILE_NAME);
325  tmp = new NBitmap(tmpMask);
326  masterMask = tmp.getChannel(3);
327  tmp.dispose();
328  tmpMask.dispose();
329  } catch (Exception e) {
330  if (tmp != null) {
331  tmp.dispose();
332  }
333  if (tmpMask != null) {
334  tmpMask.dispose();
335  }
336  throw new ImageLoadingException(e);
337  }
339  } catch (AllocationException e){
340  throw new ImageLoadingException(e);
341  } catch (UnsupportedBitmapException e) {
342  throw new ImageLoadingException(e);
343  }
344 
345  NodeList ll = il.getElementsByTagName(c.LAYER_NODE);
346 
347  int iMax = ll.getLength();
348 
349  if (iMax < 1) {
350  throw new ImageLoadingException("Supplied image file doesn't have layers.");
351  }
352 
353  Element li = null;
354  Layer l = null;
355  try {
356  for (int i = 0; i < iMax; i++) {
357  li = (Element) ll.item(i);
358  l = createLayer(getClassFor(LayerType.valueOf(li.getElementsByTagName(c.LAYER_TYPE_NODE).item(0).getTextContent())), li, f);
359  layers.add(l);
360  }
361  } catch (AllocationException e) {
362  throw new ImageLoadingException(e);
363  } catch (LayerCreationException e) {
364  throw new ImageLoadingException(e);
365  }
367  } catch (ImageLoadingException e) {
368  dispose();
369  throw new ImageLoadingException("Could not load image.", e);
370  }
371  }
372 
377  public int dispose() {
378  for (Layer l : layers) {
379  l.dispose();
380  }
381  layers.clear();
383  canvas.dispose();
384  tmpLayer.dispose();
385  if (patch != null) {
386  patch.dispose();
387  }
388  if (clipBoard != null) {
389  clipBoard.dispose();
390  }
391  return 0;
392  }
393 
394 
395  //===== METHODS =============================================================================================================================//
396  //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
401  protected int assignId() {
402  return nextId++;
403  }
404 
409  protected int getLastAssignedId() {
410  return nextId - 1;
411  }
412 
417  protected void addChangedArea(Rect area) {
418  synchronized (toBeRendered) {
419  toBeRendered.add(area);
420  toBeRendered.notifyAll();
421  }
422  }
423 
430  protected int getLayerPosition(int id) throws LayerNotFoundException {
431  Layer l = getLayer(id);
432  return layers.indexOf(l);
433  }
434 
440  protected Class<? extends Layer> getClassFor(LayerType type) {
441  switch (type) {
442  case LAYER_RASTER:
443  return RasterLayer.class;
444  case LAYER_COLOR:
445  return ColorLayer.class;
446  case LAYER_BRIGHTNESS:
447  return BrightnessLUTLayer.class;
448  case LAYER_CONTRAST:
449  return ContrastLUTLayer.class;
450  case LAYER_GAMMA:
451  return GammaLUTLayer.class;
452  case LAYER_CURVES:
453  return CurvesLUTLayer.class;
454  case LAYER_GAUSSIAN_BLUR:
455  return GaussianBlurFilterLayer.class;
456  case LAYER_LAPLACE_SHARPEN:
457  return LaplaceSharpenFilterLayer.class;
458  case LAYER_GAUSSIAN_SHARPEN:
459  return GaussianSharpenFilterLayer.class;
460  case LAYER_LAPLACIAN_OF_GAUSSIAN_SHARPEN:
462  case LAYER_DIFFERENCE_OF_GAUSSIAN_SHARPEN:
464  default:
465  return null;
466  }
467  }
468 
479  protected Layer createLayer(Class<? extends Layer> cls) throws ImageException {
480  try {
481  Constructor<? extends Layer> ctor = cls.getConstructor(new Class[] { Image.class, int.class });
482  return ctor.newInstance(new Object[] { this, assignId() });
483  } catch (NoSuchMethodException exc) {
484  throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
485  } catch (IllegalAccessException exc) {
486  throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
487  } catch (IllegalArgumentException exc) {
488  throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
489  } catch (InstantiationException exc) {
490  throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
491  } catch (InvocationTargetException exc) {
492  throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
493  } catch (ExceptionInInitializerError exc) {
494  throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
495  }
496  }
497 
506  protected Layer createLayer(Class<? extends Layer> cls, Element info, ImageFile file) throws ImageException {
507  try {
508  Constructor<? extends Layer> ctor = cls.getConstructor(new Class[] { Image.class, Element.class, ImageFile.class });
509  return ctor.newInstance(new Object[] { this, info, file});
510  } catch (NoSuchMethodException exc) {
511  throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
512  } catch (IllegalAccessException exc) {
513  throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
514  } catch (IllegalArgumentException exc) {
515  throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
516  } catch (InstantiationException exc) {
517  throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
518  } catch (InvocationTargetException exc) {
519  throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
520  } catch (ExceptionInInitializerError exc) {
521  throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
522  }
523  }
524 
532  protected void appendLeafElement(Document d, Element parent, String eName, String eContetnt) {
533  Element e = d.createElement(eName);
534  e.setTextContent(eContetnt);
535  parent.appendChild(e);
536  }
537 
538  //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
539 
543  public void mergeAll() {
544  if (canvasOwner != null) {
545  return;
546  }
547  RasterLayer merged = new RasterLayer(this, assignId());
548  NBitmap dst = merged.getBitmap();
549  for (Layer l : layers) {
550  l.applyTo(dst, getRect(), 0, 0);
551  l.dispose();
552  }
553  layers = new ArrayList<Layer>();
554  layers.add(merged);
555 
556  selectedLayerId = merged.getId();
557 
559 
560  if (pres != null) {
561  pres.hasChanged();
562  }
563 
564  }
565 
571  public void clear(ImageSelectedState item, int itemId) {
572  if (canvasOwner != null) {
573  return;
574  }
575 
576  NBitmap target = null;
577  switch (item) {
578  case SELECTED_LAYER:
579  try {
580  Layer l = getLayer(itemId);
581  target = ((RasterLayer)l).getBitmap();
582  } catch (LayerNotFoundException e) {
583  return;
584  } catch (ClassCastException e) {
585  return;
586  }
587  break;
588 
589  case SELECTED_MASK:
590  try {
591  Layer l = getLayer(itemId);
592  target = l.getMask(true);
593  } catch (LayerNotFoundException e) {
594  return;
595  }
596 
597  break;
598 
599  case SELECTED_MASTER_MASK:
600  target = masterMask;
601  break;
602 
603  case SELECTED_NONE:
604  return;
605  }
606 
607  if (target == null ) {
608  return; // maska neexistuje, jiny problem
609  }
610 
611  UndoPatch tmpPatch = new UndoPatch(target, target.getRect(), selectedState, itemId);
612 
613  try {
614  if (masterMaskActive) {
615  if (item == ImageSelectedState.SELECTED_LAYER) {
616  Blender.removeFrom4ch(target, masterMask, target.getRect(), 0, 0);
617  } else {
618  Blender.removeFrom(target, masterMask, target.getRect(), 0, 0);
619  }
620  } else {
621  target.fill(target.getRect(), 0x00);
622  }
623  } catch (IllegalArgumentException e) {
624  tmpPatch.dispose();
625  return;
626  }
627 
628  if (patch != null) {
629  patch.dispose();
630  patch = tmpPatch;
631  }
632 
634 
635  if (pres != null) {
636  synchronized (pres) {
638  getLayer(itemId).updateInfo(pres.getLayerInfo(itemId));
639  pres.hasChanged();
640  } else {
641  NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
642  Interpolator.resampleTo(masterMask, mskThumbWrap);
643  mskThumbWrap.dispose();
644  }
645  }
646  }
647  return;
648  }
649 
655  public void fill(ImageSelectedState item, int itemId) {
656  if (canvasOwner != null) {
657  return;
658  }
659 
660  NBitmap target = null;
661  switch (item) {
662  case SELECTED_LAYER:
663  return;
664 
665  case SELECTED_MASK:
666  try {
667  Layer l = getLayer(itemId);
668  target = l.getMask(true);
669  } catch (LayerNotFoundException e) {
670  return;
671  }
672 
673  break;
674 
675  case SELECTED_MASTER_MASK:
676  target = masterMask;
677  break;
678 
679  case SELECTED_NONE:
680  return;
681  }
682 
683  if (target == null ) {
684  return; // maska neexistuje, jiny problem
685  }
686 
687  UndoPatch tmpPatch = new UndoPatch(target, target.getRect(), selectedState, itemId);
688 
689  try {
690  if (masterMaskActive) {
691  Blender.addTo(target, masterMask, target.getRect(), 0, 0);
692  } else {
693  target.fill(target.getRect(), 0xFFFFFFFF);
694  }
695  } catch (IllegalArgumentException e) {
696  tmpPatch.dispose();
697  return;
698  }
699 
700  if (patch != null) {
701  patch.dispose();
702  patch = tmpPatch;
703  }
704 
706 
707  if (pres != null) {
708  synchronized (pres) {
710  getLayer(itemId).updateInfo(pres.getLayerInfo(itemId));
711  pres.hasChanged();
712  } else {
713  NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
714  Interpolator.resampleTo(masterMask, mskThumbWrap);
715  mskThumbWrap.dispose();
716  }
717  }
718  }
719  return;
720  }
721 
727  public void invertMask(ImageSelectedState item, int itemId) {
728  if (canvasOwner != null) {
729  return;
730  }
731 
732  NBitmap target = null;
733  switch (item) {
734  case SELECTED_LAYER:
735  return;
736 
737  case SELECTED_MASK:
738  try {
739  Layer l = getLayer(itemId);
740  target = l.getMask(true);
741  } catch (LayerNotFoundException e) {
742  return;
743  }
744 
745  break;
746 
747  case SELECTED_MASTER_MASK:
748  target = masterMask;
749  break;
750 
751  case SELECTED_NONE:
752  return;
753  }
754 
755  if (target == null ) {
756  return; // maska neexistuje, jiny problem
757  }
758 
759  UndoPatch tmpPatch = new UndoPatch(target, target.getRect(), selectedState, itemId);
760 
761  try {
762  if (masterMaskActive) {
763  NBitmap tmp = null;
764  try {
765  tmp = new NBitmap(target);
766  Blender.addTo(target, masterMask, target.getRect(), 0, 0);
767  Blender.removeFrom(target, masterMask, tmp, target.getRect(), 0, 0, 0, 0);
768  } finally {
769  if (tmp != null) {
770  tmp.dispose();
771  }
772  }
773  } else {
774  NBitmap tmp = null;
775  try {
776  tmp = new NBitmap(target);
777  target.fill(target.getRect(), 0xFFFFFFFF);
778  Blender.removeFrom(target, tmp, target.getRect(), 0, 0);
779  } finally {
780  if (tmp != null) {
781  tmp.dispose();
782  }
783  }
784  }
785  } catch (IllegalArgumentException e) {
786  tmpPatch.dispose();
787  return;
788  }
789 
790  if (patch != null) {
791  patch.dispose();
792  patch = tmpPatch;
793  }
794 
796 
797  if (pres != null) {
798  synchronized (pres) {
800  getLayer(itemId).updateInfo(pres.getLayerInfo(itemId));
801  pres.hasChanged();
802  } else {
803  NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
804  Interpolator.resampleTo(masterMask, mskThumbWrap);
805  mskThumbWrap.dispose();
806  }
807  }
808  }
809  return;
810  }
811 
817  public void toClipBoard(ImageSelectedState item, int itemId) {
818  if (clipBoard != null) {
819  clipBoard.dispose();
820  clipBoard = null;
821  }
822 
823  NBitmap source = null;
824  switch (item) {
825  case SELECTED_LAYER:
826  try {
827  Layer l = getLayer(itemId);
828  source = ((RasterLayer)l).getBitmap();
829  } catch (LayerNotFoundException e) {
830  return;
831  } catch (ClassCastException e) {
832  return;
833  }
834  break;
835 
836  case SELECTED_MASK:
837  try {
838  Layer l = getLayer(itemId);
839  source = l.getMask(false);
840  } catch (LayerNotFoundException e) {
841  return;
842  }
843 
844  break;
845 
846  case SELECTED_MASTER_MASK:
847  source = masterMask;
848  break;
849 
850  case SELECTED_NONE:
851  return;
852  }
853 
854  if (source == null ) {
855  return;
856  }
857 
858  if (masterMaskActive) {
859  BitmapInfo i = source.getInfo();
860  clipBoard = new NBitmap(i);
863  Blender.addTo(clipBoard, masterMask, source, masterMask.getRect(), 0, 0, 0, 0);
864  } else if (i.channelCount == ChannelCount.FOUR_CHANNEL) {
866  }
867  } else {
868  clipBoard = new NBitmap(source);
869  }
870  return;
871  }
872 
878  public void fromClipBoard(ImageSelectedState item, int itemId) {
879  if (clipBoard == null || canvasOwner != null) {
880  return;
881  }
882 
883  NBitmap target = null;
884  switch (item) {
885  case SELECTED_LAYER:
886  try {
887  Layer l = getLayer(itemId);
888  target = ((RasterLayer)l).getBitmap();
889  } catch (LayerNotFoundException e) {
890  return;
891  } catch (ClassCastException e) {
892  return;
893  }
894  break;
895 
896  case SELECTED_MASK:
897  try {
898  Layer l = getLayer(itemId);
899  target = l.getMask(true);
900  } catch (LayerNotFoundException e) {
901  return;
902  }
903 
904  break;
905 
906  case SELECTED_MASTER_MASK:
907  target = masterMask;
908  break;
909 
910  case SELECTED_NONE:
911  return;
912  }
913 
914  if (target == null ) {
915  return; // maska neexistuje, jiny problem
916  }
917 
918  UndoPatch tmpPatch = new UndoPatch(target, target.getRect(), selectedState, itemId);
919 
920  try {
921  if (masterMaskActive) {
922  if (item == ImageSelectedState.SELECTED_LAYER) {
924  tmpPatch.dispose();
925  return;
926  }
927  Blender.removeFrom4ch(target, masterMask, target.getRect(), 0, 0);
928  Blender.drawTo(BlendMode.BLEND_MODE_NORMAL, target, masterMask, clipBoard, target.getRect(), 0, 0, 0, 0);
929  } else {
931  tmpPatch.dispose();
932  return;
933  }
934  Blender.removeFrom(target, masterMask, target.getRect(), 0, 0);
935  Blender.addTo(target, masterMask, clipBoard, target.getRect(), 0, 0, 0, 0);
936  }
937  } else {
938  clipBoard.copyTo(target, getRect(), 0, 0);
939  }
940  } catch (IllegalArgumentException e) {
941  tmpPatch.dispose();
942  return;
943  }
944 
945  if (patch != null) {
946  patch.dispose();
947  patch = tmpPatch;
948  }
949 
951 
952  if (pres != null) {
953  synchronized (pres) {
955  getLayer(itemId).updateInfo(pres.getLayerInfo(itemId));
956  pres.hasChanged();
957  } else {
958  NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
959  Interpolator.resampleTo(masterMask, mskThumbWrap);
960  mskThumbWrap.dispose();
961  }
962  }
963  }
964  return;
965  }
966 
972  public void addClipBoard(ImageSelectedState item, int itemId) {
973  if (clipBoard == null || canvasOwner != null) {
974  return;
975  }
976 
977  NBitmap target = null;
978  switch (item) {
979  case SELECTED_LAYER:
980  try {
981  Layer l = getLayer(itemId);
982  target = ((RasterLayer)l).getBitmap();
983  } catch (LayerNotFoundException e) {
984  return;
985  } catch (ClassCastException e) {
986  return;
987  }
988  break;
989 
990  case SELECTED_MASK:
991  try {
992  Layer l = getLayer(itemId);
993  target = l.getMask(true);
994  } catch (LayerNotFoundException e) {
995  return;
996  }
997 
998  break;
999 
1000  case SELECTED_MASTER_MASK:
1001  target = masterMask;
1002  break;
1003 
1004  case SELECTED_NONE:
1005  return;
1006  }
1007 
1008  if (target == null ) {
1009  return; // maska neexistuje, jiny problem
1010  }
1011 
1012  UndoPatch tmpPatch = new UndoPatch(target, target.getRect(), selectedState, itemId);
1013 
1014  try {
1015  if (masterMaskActive) {
1016  if (item == ImageSelectedState.SELECTED_LAYER) {
1017  Blender.addTo4ch(target, masterMask, clipBoard, target.getRect(), 0, 0, 0, 0);
1018  } else {
1019  Blender.addTo(target, masterMask, clipBoard, target.getRect(), 0, 0, 0, 0);
1020  }
1021  } else {
1022  if (item == ImageSelectedState.SELECTED_LAYER) {
1023  Blender.addTo4ch(target, clipBoard, target.getRect(), 0, 0);
1024  } else {
1025  Blender.addTo(target, clipBoard, target.getRect(), 0, 0);
1026  }
1027  }
1028  } catch (IllegalArgumentException e) {
1029  tmpPatch.dispose();
1030  return;
1031  }
1032 
1033  if (patch != null) {
1034  patch.dispose();
1035  patch = tmpPatch;
1036  }
1037 
1039 
1040  if (pres != null) {
1041  synchronized (pres) {
1043  getLayer(itemId).updateInfo(pres.getLayerInfo(itemId));
1044  pres.hasChanged();
1045  } else {
1046  NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1047  Interpolator.resampleTo(masterMask, mskThumbWrap);
1048  mskThumbWrap.dispose();
1049  }
1050  }
1051  }
1052  return;
1053  }
1054 
1060  public void removeClipBoard(ImageSelectedState item, int itemId) {
1061  if (clipBoard == null || canvasOwner != null) {
1062  return;
1063  }
1064 
1065  NBitmap target = null;
1066  switch (item) {
1067  case SELECTED_LAYER:
1068  try {
1069  Layer l = getLayer(itemId);
1070  target = ((RasterLayer)l).getBitmap();
1071  } catch (LayerNotFoundException e) {
1072  return;
1073  } catch (ClassCastException e) {
1074  return;
1075  }
1076  break;
1077 
1078  case SELECTED_MASK:
1079  try {
1080  Layer l = getLayer(itemId);
1081  target = l.getMask(true);
1082  } catch (LayerNotFoundException e) {
1083  return;
1084  }
1085 
1086  break;
1087 
1088  case SELECTED_MASTER_MASK:
1089  target = masterMask;
1090  break;
1091 
1092  case SELECTED_NONE:
1093  return;
1094  }
1095 
1096  if (target == null ) {
1097  return; // maska neexistuje, jiny problem
1098  }
1099 
1100  UndoPatch tmpPatch = new UndoPatch(target, target.getRect(), selectedState, itemId);
1101 
1102  try {
1103  if (masterMaskActive) {
1104  if (item == ImageSelectedState.SELECTED_LAYER) {
1105  Blender.removeFrom4ch(target, masterMask, clipBoard, target.getRect(), 0, 0, 0, 0);
1106  } else {
1107  Blender.removeFrom(target, masterMask, clipBoard, target.getRect(), 0, 0, 0, 0);
1108  }
1109  } else {
1110  if (item == ImageSelectedState.SELECTED_LAYER) {
1111  Blender.removeFrom4ch(target, clipBoard, target.getRect(), 0, 0);
1112  } else {
1113  Blender.removeFrom(target, clipBoard, target.getRect(), 0, 0);
1114  }
1115  }
1116  } catch (IllegalArgumentException e) {
1117  tmpPatch.dispose();
1118  return;
1119  }
1120 
1121  if (patch != null) {
1122  patch.dispose();
1123  patch = tmpPatch;
1124  }
1125 
1127 
1128  if (pres != null) {
1129  synchronized (pres) {
1131  getLayer(itemId).updateInfo(pres.getLayerInfo(itemId));
1132  pres.hasChanged();
1133  } else {
1134  NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1135  Interpolator.resampleTo(masterMask, mskThumbWrap);
1136  mskThumbWrap.dispose();
1137  }
1138  }
1139  }
1140  return;
1141  }
1142 
1148  public void blendClipBoard(ImageSelectedState item, int itemId) {
1149  if (clipBoard == null || canvasOwner != null) {
1150  return;
1151  }
1152 
1153  NBitmap target = null;
1154  switch (item) {
1155  case SELECTED_LAYER:
1156  try {
1157  Layer l = getLayer(itemId);
1158  target = ((RasterLayer)l).getBitmap();
1159  } catch (LayerNotFoundException e) {
1160  return;
1161  } catch (ClassCastException e) {
1162  return;
1163  }
1164  break;
1165 
1166  case SELECTED_MASK:
1167  return;
1168 
1169  case SELECTED_MASTER_MASK:
1170  return;
1171 
1172  case SELECTED_NONE:
1173  return;
1174  }
1175 
1176  if (target == null ) {
1177  return; // maska neexistuje, jiny problem
1178  }
1179 
1180  UndoPatch tmpPatch = new UndoPatch(target, target.getRect(), selectedState, itemId);
1181 
1182  try {
1183  if (masterMaskActive) {
1184  Blender.drawTo(BlendMode.BLEND_MODE_NORMAL, target, masterMask, clipBoard, target.getRect(), 0, 0, 0, 0);
1185  } else {
1186  Blender.blendTo(BlendMode.BLEND_MODE_NORMAL, target, clipBoard, target.getRect(), 0, 0);
1187  }
1188  } catch (IllegalArgumentException e) {
1189  tmpPatch.dispose();
1190  return;
1191  }
1192 
1193  if (patch != null) {
1194  patch.dispose();
1195  patch = tmpPatch;
1196  }
1197 
1199 
1200  if (pres != null) {
1201  synchronized (pres) {
1203  getLayer(itemId).updateInfo(pres.getLayerInfo(itemId));
1204  pres.hasChanged();
1205  } else {
1206  NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1207  Interpolator.resampleTo(masterMask, mskThumbWrap);
1208  mskThumbWrap.dispose();
1209  }
1210  }
1211  }
1212  return;
1213  }
1214 
1215 
1216 
1226  public void resizeTo(int nWidth, int nHeight, InterpolatorType iType, double force) throws ImageStateException, BitmapAllocationException {
1227  if (canvasOwner != null) {
1228  throw new ImageStateException("Canvas transaction already pending"); // Nastroj by se aplikoval na vrstvu, na kterou nemusi byt pouzitelny
1229  }
1230  NBitmap tmp;
1231  tmp = new NBitmap(new BitmapInfo(nWidth, nHeight, ChannelCount.SINGLE_CHANNEL, depth, ColorMode.MONO, false));
1232  Interpolator.resampleTo(canvas, tmp, iType, force);
1233  canvas.dispose();
1234  canvas = tmp;
1235 
1236  tmp = new NBitmap(new BitmapInfo(nWidth, nHeight, ChannelCount.SINGLE_CHANNEL, depth, ColorMode.MONO, false));
1237  Interpolator.resampleTo(masterMask, tmp, iType, force);
1238  masterMask.dispose();
1239  masterMask = tmp;
1240 
1241  tmpLayer.resizeTo(nWidth, nHeight, iType, force);
1242 
1243  for (Layer l : layers) {
1244  l.resizeTo(nWidth, nHeight, iType, force);
1245  }
1246 
1247  width = tmpLayer.getWidth();
1249 
1250  if (patch != null) {
1251  patch.dispose();
1252  patch = null;
1253  }
1254 
1255  if (clipBoard != null) {
1256  clipBoard.dispose();
1257  clipBoard = null;
1258  }
1259 
1261 
1262  if (pres != null) {
1263  synchronized (pres) {
1264  NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1265  Interpolator.resampleTo(masterMask, mskThumbWrap);
1266  mskThumbWrap.dispose();
1267 
1268  for (int i = 0; i < layers.size(); i++) {
1269  Layer l = layers.get(i);
1271  }
1272  pres.hasChanged();
1273  }
1274  }
1275  }
1276 
1284  if (canvasOwner != null) {
1285  throw new ImageStateException("Canvas transaction already pending"); // Nastroj by se aplikoval na vrstvu, na kterou nemusi byt pouzitelny
1286  }
1287 
1288  Rect crop = r.cropBy(getRect());
1289 
1290  if (crop.getWidth() <= 0 || crop.getHeight() <= 0) {
1291  return;
1292  }
1293 
1294  canvas.cropTo(r);
1295  masterMask.cropTo(r);
1296  tmpLayer.cropTo(r);
1297 
1298  for (Layer l : layers) {
1299  l.cropTo(r);
1300  }
1301 
1302  width = tmpLayer.getWidth();
1304 
1305  if (patch != null) {
1306  patch.dispose();
1307  patch = null;
1308  }
1309 
1310  if (clipBoard != null) {
1311  clipBoard.dispose();
1312  clipBoard = null;
1313  }
1314 
1316 
1317  if (pres != null) {
1318  synchronized (pres) {
1319  NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1320  Interpolator.resampleTo(masterMask, mskThumbWrap);
1321  mskThumbWrap.dispose();
1322 
1323  for (int i = 0; i < layers.size(); i++) {
1324  Layer l = layers.get(i);
1326  }
1327  pres.hasChanged();
1328  }
1329  }
1330  }
1331 
1336  public void exportToFile(ImageFile f) {
1337  FileConstants c = new FileConstants();
1338  Document d = null;
1339  Element r = null;
1340  Element e = null;
1341 
1342  Element ii = null;
1343  Element il = null;
1344  try {
1345  d = f.getDocument();
1346 
1347  r = d.createElement(c.ROOT_NODE);
1348  d.appendChild(r);
1349 
1350  ii = d.createElement(c.INFO_NODE);
1351  r.appendChild(ii);
1352 
1353  il = d.createElement(c.IMAGE_LAYERS_NODE);
1354  r.appendChild(il);
1355 
1356  appendLeafElement(d, ii, c.WIDTH_NODE, Integer.toString(width));
1357  appendLeafElement(d, ii, c.HEIGHT_NODE, Integer.toString(height));
1358  appendLeafElement(d, ii, c.DEPTH_NODE, depth.toString());
1359  appendLeafElement(d, ii, c.NEXT_ID_NODE, Integer.toString(nextId));
1360  appendLeafElement(d, ii, c.SELECTED_STATE_NODE, selectedState.toString());
1361  appendLeafElement(d, ii, c.SELECTED_LAYER_ID_NODE, Integer.toString(selectedLayerId));
1362  appendLeafElement(d, ii, c.MASTER_MASK_ACTIVE_NODE, Boolean.toString(masterMaskActive));
1363  } catch (Exception exc) {
1364  throw new ImageSavingException(exc);
1365  }
1366  try {
1367  for (Layer l : layers) {
1368  e = d.createElement(c.LAYER_NODE);
1369  l.fillLayerElement(d, f, e);
1370  il.appendChild(e);
1371  }
1372  } catch (Exception exc) {
1373  throw new ImageSavingException(exc);
1374  }
1375  PDBitmap tmpBitmap = null;
1376  NBitmap tmpWrap = null;
1377  try {
1379  tmpWrap = new NBitmap(tmpBitmap);
1380  masterMask.copyTo(tmpWrap, masterMask.getRect(), 0, 0);
1381  tmpWrap.dispose();
1382  f.writeMask(tmpBitmap, c.MASTER_MASK_FILE_NAME);
1383  tmpBitmap.dispose();
1384  } catch (Exception exc) {
1385  if (tmpWrap != null) {
1386  tmpWrap.dispose();
1387  }
1388  if (tmpBitmap != null) {
1389  tmpBitmap.dispose();
1390  }
1391  throw new ImageSavingException(exc);
1392  }
1393  try {
1394  f.writeDocument();
1395  } catch (Exception exc) {
1396  throw new ImageSavingException(exc);
1397  }
1398  }
1399 
1403  public void applyUndoPatch() {
1404  if (patch != null) {
1405  if (patch.apply()) {
1407 
1408  if (pres != null) {
1409  synchronized (pres) {
1411  getLayer(patch.getId()).updateInfo(pres.getLayerInfo(patch.getId()));
1412  pres.hasChanged();
1413  } else {
1414  NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1415  Interpolator.resampleTo(masterMask, mskThumbWrap);
1416  mskThumbWrap.dispose();
1417  }
1418  }
1419  }
1420  }
1421  }
1422  }
1423 
1424 
1429  public int getWidth() {
1430  return width;
1431  }
1432 
1437  public int getHeight() {
1438  return height;
1439  }
1440 
1445  public Depth getDepth() {
1446  return depth;
1447  }
1448 
1453  public Rect getRect() {
1454  return new Rect(width, height);
1455  }
1456 
1462  return pres;
1463  }
1464 
1470  this.pres = pres;
1471  if (pres == null) {
1472  return;
1473  }
1474  synchronized (pres) {
1477 
1479  pres.masterMask = pres.createMaskThumb();
1480  NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1481  Interpolator.resampleTo(masterMask, mskThumbWrap);
1482  mskThumbWrap.dispose();
1483 
1484  pres.getLayers().clear();
1485  for (int i = 0; i < layers.size(); i++) {
1486  Layer l = layers.get(i);
1487  LayerPDInfo inf = new LayerPDInfo(pres);
1488  l.updateInfo(inf);
1489  pres.addLayerInfo(inf);
1490  }
1491  }
1492  }
1493 
1499  return selectedState;
1500  }
1501 
1503  return canvasOwner;
1504  }
1505 
1512  public int setSelectedState(ImageSelectedState state, int layerId) throws LayerNotFoundException {
1513  if (canvasOwner != null) {
1514  throw new ImageStateException("Canvas transaction already pending"); // Nastroj by se aplikoval na vrstvu, na kterou nemusi byt pouzitelny
1515  }
1516  if (state != selectedState) {
1518  }
1519  switch (state) {
1520  case SELECTED_NONE:
1521  // Toto by nemel byt spravny zpusob uziti
1522  selectedLayerId = -1;
1523  break;
1524  case SELECTED_LAYER: {
1525  Layer l = getLayer(layerId);
1526  selectedLayerId = layerId;
1527  break;
1528  }
1529  case SELECTED_MASK: {
1530  Layer l = getLayer(layerId);
1531  selectedLayerId = layerId;
1532  addChangedArea(getRect()); // Kvůli náhledu masky
1533  break;
1534  }
1535  case SELECTED_MASTER_MASK:
1536  selectedLayerId = -1;
1537  addChangedArea(getRect()); // Kvůli náhledu masky
1538  break;
1539  default:
1540  }
1541  selectedState = state;
1542  if (pres != null) {
1543  synchronized (pres) {
1544  pres.selectedState = state;
1546  pres.hasChanged();
1547  }
1548  }
1549  return 0;
1550  }
1551 
1558  public Layer getLayer(int id) throws LayerNotFoundException {
1559  for (Layer l : layers) {
1560  if (l.getId() == id) {
1561  return l;
1562  }
1563  }
1564  throw new LayerNotFoundException("Layer with id " + id + " doesn't exist");
1565  }
1566 
1567  // Musí mít zastavený displayer - pokud se změní uprostřed vykonávání, může posunout výstup
1568  public void requeryExrtaMargins() {
1569  int extra = 0;
1570  int tmp;
1571  for (Layer l : layers) {
1572  tmp = l.getExtraMargin();
1573  extra = Math.max(extra, tmp);
1574  }
1575  extraMargins = extra;
1576  }
1577 
1582  public boolean isMasterMaskActive() {
1583  return masterMaskActive;
1584  }
1585 
1590  public void setMasterMaskActive(boolean active) {
1591  masterMaskActive = active;
1592  if (pres != null) {
1593  pres.masterMaskActive = active;
1594  pres.hasChanged();
1595  }
1596  }
1597 
1603  return masterMask;
1604  }
1605 
1612  public void setLayerMaskActive(int layerId, boolean active) throws LayerNotFoundException {
1613  Layer l = getLayer(layerId);
1614  l.setMaskActive(active);
1615  if (pres != null) {
1616  LayerPDInfo i = pres.getLayerInfo(layerId);
1617  l.updateInfo(i);
1618  pres.hasChanged();
1619  }
1621  }
1622 
1630  public void setLayerOpacity(int layerId, double opacity) throws LayerNotFoundException {
1631  Layer l = getLayer(layerId);
1632  l.setOpacity(opacity);
1633  if (pres != null) {
1634  LayerPDInfo i = pres.getLayerInfo(layerId);
1635  l.updateInfo(i);
1636  pres.hasChanged();
1637  }
1638  if (l.isVisible()) {
1640  }
1641  }
1642 
1650  public int setLayerVisibility(int layerId, boolean visibility) throws LayerNotFoundException {
1651  Layer l = getLayer(layerId);
1652  l.setVisible(visibility);
1653  if (pres != null) {
1654  synchronized (pres) {
1655  LayerPDInfo inf = pres.getLayerInfo(layerId);
1656  l.updateInfo(inf);
1657  pres.hasChanged();
1658  }
1659  }
1661  return 0;
1662  }
1663 
1671  public int createLayer(LayerType type, int overLayerWithId) throws LayerNotFoundException {
1673  overLayerWithId = layers.get(layers.size() - 1).getId();
1674  }
1675  Layer l = createLayer(getClassFor(type));
1676  layers.add(getLayerPosition(overLayerWithId) + 1, l);
1677  if (pres != null) {
1678  synchronized (pres) {
1679  LayerPDInfo inf = new LayerPDInfo(pres);
1680  l.updateInfo(inf);
1681  pres.addLayerInfo(inf, overLayerWithId);
1682  pres.hasChanged();
1683  }
1684  }
1685  return 0;
1686  }
1687 
1688  public int duplicateLayer(int layerId) {
1689  Layer ol = getLayer(layerId);
1690  Layer nl = ol.duplicate(assignId());
1691  layers.add(getLayerPosition(layerId) + 1, nl);
1693  if (pres != null) {
1694  synchronized (pres) {
1695  LayerPDInfo inf = new LayerPDInfo(pres);
1696  nl.updateInfo(inf);
1697  pres.addLayerInfo(inf, layerId);
1698  pres.hasChanged();
1699  }
1700  }
1701  return 0;
1702  }
1703 
1711  public int deleteLayer(int layerId) throws LayerNotFoundException, ImageStateException {
1712  if (layers.size() == 1) {
1713  // Nelze odstranit poslední vrstvu.
1714  throw new ImageStateException("Could not deleta last layer");
1715  }
1716  Layer l = getLayer(layerId);
1717  // Aktivujeme vrstvu, ktera byla pod ni, pokud byla vrstva vubec vybrana... ID je platne, ptz jinak getLayer hodi vyjimku
1718  if (layerId == selectedLayerId) {
1719  if (canvasOwner != null) {
1720  throw new ImageStateException("Canvas transaction already pending"); // Nastroj by se aplikoval na vrstvu, na kterou nemusi byt pouzitelny
1721  }
1722  int oldIndex = layers.indexOf(l);
1723  if (oldIndex > 0) {
1724  selectedLayerId = layers.get(oldIndex - 1).getId();
1725  } else {
1726  selectedLayerId = layers.get(1).getId();
1727  }
1728  }
1729  l.dispose();
1730  layers.remove(l);
1733  if (pres != null) {
1734  synchronized (pres) {
1735  pres.removeLayer(layerId);
1737  pres.hasChanged();
1738  }
1739  }
1740  return 0;
1741  }
1742 
1750  public int moveLayer(int layerId, int beforeLayerWithId) throws LayerNotFoundException {
1751  Layer l = getLayer(layerId);
1752  int oldIndex = layers.indexOf(l);
1753  int newIndex = (beforeLayerWithId < 0) ? layers.size() : layers.indexOf(getLayer(beforeLayerWithId));
1754  layers.remove(l);
1755  if (oldIndex < newIndex) {
1756  newIndex--;
1757  }
1758  layers.add(newIndex, l);
1759  if (pres != null) {
1760  synchronized (pres) {
1761  pres.moveLayer(layerId, beforeLayerWithId);
1762  pres.hasChanged();
1763  }
1764  }
1766  return 0;
1767  }
1768 
1773  public void updateLayerFromSpecificPresentation(int layerId) {
1774  Layer l = getLayer(layerId);
1775  synchronized (pres) {
1777  pres.hasChanged();
1778  }
1780  }
1781 
1791  public NBitmap prepareCanvas(Tool tool, ChannelCount chCount) throws IllegalStateException, ImageException, ImageStateException{
1792  if (canvasOwner != null) {
1793  throw new IllegalStateException("Canvas is already pending.");
1794  }
1798  if (!(l instanceof RasterLayer)) {
1799  throw new ImageStateException("Selected layer doesn't support canvas"); // Pouze RasterLayer muze ziskat canvas, ostatni vrstvy nemaji co reagovat na kresleni...
1800  }
1801  tmpLayer.setMode(((RasterLayer) l).getMode());
1802  }
1804  if (!l.isVisible()) {
1805  throw new ImageStateException("Selected layer is invisible");
1806  }
1807  }
1811  }
1812  canvasOwner = tool;
1813  canvas.fill(canvas.getRect(), 0x00);
1814  canvasChangedArea = null;
1815  return canvas;
1816  }
1817 
1824  public NBitmap getCanvas(Tool tool) throws IllegalStateException {
1825  if (canvasOwner != tool) {
1826  throw new IllegalStateException("Tool is not canvas owner");
1827  }
1828  return canvas;
1829  }
1830 
1836  public void addCanvasChangedArea(Rect area) throws IllegalStateException {
1837  if (canvasOwner == null) {
1838  throw new IllegalStateException("Canvas is not prepared.");
1839  }
1840  if (canvasChangedArea == null) {
1841  canvasChangedArea = new Rect(area);
1842  } else {
1843  canvasChangedArea.cover(area);
1844  }
1845  addChangedArea(area);
1846  }
1847 
1855  public void submitCanvas(Tool tool, boolean commit) throws IllegalStateException, LayerNotFoundException {
1856  if (tool != canvasOwner) {
1857  throw new IllegalStateException("Canvas is not prepared.");
1858  }
1860  if (commit) {
1861  if (patch != null) {
1862  patch.dispose();
1863  patch = null;
1864  }
1865  switch (selectedState) {
1866  case SELECTED_LAYER: {
1868  NBitmap m = (masterMaskActive) ? masterMask : null;
1869  patch = new UndoPatch(l.getBitmap());
1870  canvasOwner.onCommit(this, canvas, tmpLayer.getBitmap(), l.getBitmap(), m, canvasChangedArea, canvasChangedArea.tlx, canvasChangedArea.tly);
1871 
1872  break;
1873  }
1874  case SELECTED_MASK: {
1876  NBitmap m = (masterMaskActive) ? masterMask : null;
1877  patch = new UndoPatch(l.getMask(true));
1878  canvasOwner.onCommit(this, canvas, tmpLayer.getMask(true), l.getMask(true), m, canvasChangedArea, canvasChangedArea.tlx, canvasChangedArea.tly);
1879  break;
1880  }
1881  case SELECTED_MASTER_MASK: {
1882  patch = new UndoPatch(masterMask);
1884  break;
1885  }
1886  default:
1887  break;
1888  }
1889  } else {
1891  }
1892  canvasOwner = null;
1893  if (pres != null) {
1894  synchronized (pres) {
1897  pres.hasChanged();
1898  } else {
1900  NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1901  Interpolator.resampleTo(masterMask, mskThumbWrap);
1902  mskThumbWrap.dispose();
1903  }
1904  }
1905  }
1906  }
1907 
1916  public int exportTo(NBitmap dst, Rect srcRect, int srcOrigX, int srcOrigY) {
1917  BitmapInfo dstInfo = dst.getInfo();
1918  if (dstInfo.channelCount == ChannelCount.FOUR_CHANNEL && dstInfo.depth == this.depth) {
1919 
1920  Rect tmpRect = new Rect(srcRect);
1921  tmpRect.growBy(2 * extraMargins);
1922  tmpRect.cropBy(getRect());
1923  srcOrigX = tmpRect.tlx;
1924  srcOrigY = tmpRect.tly;
1925 
1926  srcRect.growBy(extraMargins);
1927  srcRect.cropBy(getRect());
1928 
1929  dst.fill(tmpRect, 0xFF000000);
1930 
1931  for (Layer l : layers) {
1932  if (l.getId() == selectedLayerId) {
1933  if (canvasOwner != null) {
1934  NBitmap m = (masterMaskActive) ? masterMask : null;
1935  switch (selectedState) {
1936  case SELECTED_LAYER:
1937  canvasOwner.onRender(this, canvas, tmpLayer.getBitmap(), ((RasterLayer) l).getBitmap(), m, tmpRect, srcOrigX, srcOrigY);
1938  tmpLayer.applyTo(dst, tmpRect, srcOrigX, srcOrigY, l.getMask(false));
1939  break;
1940  case SELECTED_MASK:
1941  canvasOwner.onRender(this, canvas, tmpLayer.getMask(true), l.getMask(true), m, tmpRect, srcOrigX, srcOrigY);
1942  l.applyTo(dst, tmpRect, srcOrigX, srcOrigY, tmpLayer.getMask(true));
1943  break;
1944  case SELECTED_MASTER_MASK:
1945  l.applyTo(dst, tmpRect, srcOrigX, srcOrigY);
1946  default:
1947  break;
1948  }
1949  } else {
1950  l.applyTo(dst, tmpRect, srcOrigX, srcOrigY);
1951  }
1952  } else {
1953  l.applyTo(dst, tmpRect, srcOrigX, srcOrigY);
1954  }
1955  }
1957  if (canvasOwner != null) {
1958  Blender.drawTo(BlendMode.BLEND_MODE_NORMAL, dst, tmpLayer.getMask(true), 0xAA0000FF, tmpRect, srcOrigX, srcOrigY);
1959  } else {
1960  Blender.drawTo(BlendMode.BLEND_MODE_NORMAL, dst, getLayer(selectedLayerId).getMask(true), 0xAA0000FF, tmpRect, srcOrigX, srcOrigY);
1961  }
1963  if (canvasOwner != null) {
1964  canvasOwner.onRender(this, canvas, tmpLayer.getMask(true), masterMask, null, tmpRect, srcOrigX, srcOrigY);
1965  Blender.drawTo(BlendMode.BLEND_MODE_NORMAL, dst, tmpLayer.getMask(true), 0xAA0000FF, tmpRect, srcOrigX, srcOrigY);
1966  } else {
1967  Blender.drawTo(BlendMode.BLEND_MODE_NORMAL, dst, masterMask, 0xAA0000FF, tmpRect, srcOrigX, srcOrigY);
1968  }
1969  }
1970  } else {
1971  throw new IllegalArgumentException("Target bitmap is of incompatible type");
1972  }
1973  return 0;
1974  }
1975 
1988  Rect r;
1989  Rect master;
1990  Rect masterPreview;
1991  long incrementalArea;
1992  synchronized (toBeRendered) {
1993  master = toBeRendered.pollFirst();
1994  if (master == null) {
1995  return null;
1996  }
1997  incrementalArea = master.getArea();
1998  masterPreview = new Rect(master);
1999  while ((r = toBeRendered.peekFirst()) != null) {
2000  incrementalArea += r.getArea();
2001  masterPreview.cover(r);
2002  if (incrementalArea < masterPreview.getArea()) {
2003  break;
2004  }
2005  master.cover(r);
2006  toBeRendered.removeFirst();
2007  }
2008  }
2009  exportTo(dst, master, master.tlx, master.tly);
2010  return master;
2011  }
2012 }