App
BrushLikeTool.java
Go to the documentation of this file.
1 package mhr.appcore.tools.brushlike;
2 
3 import mhr.appcore.bitmap.BitmapInfo;
4 import mhr.appcore.bitmap.ChannelCount;
5 import mhr.appcore.bitmap.NBitmap;
6 import mhr.appcore.blending.BlendMode;
7 import mhr.appcore.blending.Blender;
8 import mhr.appcore.image.Image;
9 import mhr.appcore.image.layers.RasterLayer;
10 import mhr.appcore.tools.Tool;
11 import mhr.appcore.tools.actiondata.BrushLikeToolActionData;
12 import mhr.appcore.tools.actiondata.ToolActionData;
13 import mhr.appcore.utils.LinearInt;
14 import mhr.appcore.utils.Rect;
15 
23 public abstract class BrushLikeTool implements Tool {
24 
25  //===================================================================================================================================================//
26  //===== PUBLIC ==============================================================================================================================//
27  //----- interface a třídy -------------------------------------------------------------------------------------------------------------------//
31  public static enum BrushMode {
32  MODE_ADD, MODE_REMOVE
33  }
34  //----- pole --------------------------------------------------------------------------------------------------------------------------------//
35  @Deprecated // Patří do blenderu...
36  public static final double flowAsFull = 0.9999;
37  @Deprecated // Patří do blenderu...
38  public static final double flowAsNone = 0.0001;
39  //----- acesory a primitivní metody ---------------------------------------------------------------------------------------------------------//
40  //----- konstruktory ------------------------------------------------------------------------------------------------------------------------//
41 
43 
51  public BrushLikeTool (NBitmap brush, BrushMode mode, double opacity, double flow, double spacing) {
52  BitmapInfo i = brush.getInfo();
54  throw new IllegalArgumentException("Requires single channel bitmap.");
55  }
56  this.brush = brush;
57  this.brushMode = mode;
58  this.opacity = opacity;
59  this.flow = flow;
60  this.spacing = spacing;
61 
62  brushRect = brush.getRect();
63  centerX = brushRect.getWidth() / 2;
64  centerY = brushRect.getHeight() / 2;
65  }
66  //----- destruktory -------------------------------------------------------------------------------------------------------------------------//
67  @Override
68  public synchronized void dispose() {
69  if (brush != null ) {
70  brush.dispose();
71  brush = null;
72  }
73  }
74 
75  //----- metody ------------------------------------------------------------------------------------------------------------------------------//
76  @Override
77  public void applyTo(Image img, ToolActionData data) {
78  if (!(data instanceof BrushLikeToolActionData)) {
79  throw new IllegalArgumentException("Received data for different tool");
80  }
81  BrushLikeToolActionData d = (BrushLikeToolActionData) data;
82  switch (d.action) {
83  case DRAW_BEGIN:
84  bgnDraw(img, d.eventAtX, d.eventAtY);
85  break;
86  case DRAW_TO:
87  drawTo(img, d.eventAtX, d.eventAtY);
88  break;
89  case DRAW_END:
90  endDraw(img, d.eventAtX, d.eventAtY);
91  break;
92  }
93  }
94 
95  //===================================================================================================================================================//
96  //===== NON-PUBLIC ==========================================================================================================================//
97  //----- interface a třídy -------------------------------------------------------------------------------------------------------------------//
98  //----- pole --------------------------------------------------------------------------------------------------------------------------------//
99  protected int lastX;
100  protected int lastY;
101 
102  protected double opacity;
103  protected double flow;
104  protected double spacing;
105  public NBitmap brush;
106  public Rect brushRect;
107  public int centerX;
108  public int centerY;
109 
110  protected BrushMode brushMode;
111 
112  protected Rect maskRect;
113 
114  //----- acesory a primitivní metody ---------------------------------------------------------------------------------------------------------//
115  //----- konstruktory ------------------------------------------------------------------------------------------------------------------------//
116  //----- destruktory -------------------------------------------------------------------------------------------------------------------------//
117  @Override
118  protected void finalize() throws Throwable {
119  dispose();
120  super.finalize();
121  }
122  //----- metody ------------------------------------------------------------------------------------------------------------------------------//
123 
130  public void bgnDraw(Image img, int atX, int atY) {
131  NBitmap canvas = img.prepareCanvas(this, ChannelCount.SINGLE_CHANNEL);
132  NBitmap mask = null;
133  if (img.isMasterMaskActive()) {
134  mask = img.getMasterMask();
135  maskRect = mask.getRect();
136  }
137  drawAt(img, canvas, mask, atX, atY);
138  }
139 
146  public void drawTo(Image img, int toX, int toY) {
147  NBitmap canvas = img.getCanvas(this);
148  NBitmap mask = null;
149  if (img.isMasterMaskActive()) {
150  mask = img.getMasterMask();
151  maskRect = mask.getRect();
152  }
153  int[][] pts = LinearInt.interpolate(lastX, lastY, toX, toY, spacing);
154  for (int i = 1; i < pts[0].length; i++) {
155  drawAt(img, canvas, mask, pts[0][i], pts[1][i]);
156  }
157  }
158 
165  public void endDraw(Image img, int atX, int atY) {
166  NBitmap canvas = img.getCanvas(this);
167  NBitmap mask = (img.isMasterMaskActive()) ? img.getMasterMask() : null;
168  drawTo(img, atX, atY);
169  img.submitCanvas(this, true);
170  }
171 
180  protected void drawAt(Image img, NBitmap canvas, NBitmap mask, int atX, int atY) {
181  lastX = atX;
182  lastY = atY;
183  if (flow > flowAsFull) {
184  if (brushMode == BrushMode.MODE_ADD) {
185  if (mask != null) {
186  Blender.addTo(canvas, mask, brush, maskRect, atX - centerX, atY - centerY, 0, 0);
187 
188 
189  } else {
190  Blender.addTo(canvas, brush, brushRect, atX - centerX, atY - centerY);
191  }
192  } else {
193  if (mask != null) {
194  Blender.removeFrom(canvas, mask, brush, maskRect, atX - centerX, atY - centerY, 0, 0);
195  } else {
196  Blender.removeFrom(canvas, brush, brushRect, atX - centerX, atY - centerY);
197  }
198  }
199  } else if (flow < flowAsNone) {
200  return;
201  } else {
202  if (brushMode == BrushMode.MODE_ADD) {
203  if (mask != null) {
204  Blender.addTo(canvas, mask, brush, maskRect, atX - centerX, atY - centerY, 0, 0, flow);
205  } else {
206  Blender.addTo(canvas, brush, brushRect, atX - centerX, atY - centerY, flow);
207  }
208  } else {
209  if (mask != null) {
210  Blender.removeFrom(canvas, mask, brush, maskRect, atX - centerX, atY - centerY, 0, 0, flow);
211  } else {
212  Blender.removeFrom(canvas, brush, brushRect, atX - centerX, atY - centerY, flow);
213  }
214  }
215  }
216  img.addCanvasChangedArea((new Rect(brushRect)).moveBy(atX - centerX, atY - centerY).cropBy(img.getRect()));
217  }
218 
219  //===================================================================================================================================================//
220  //===== DEPRECATED ==========================================================================================================================//
221 
222 }