-
Notifications
You must be signed in to change notification settings - Fork 89
Expand file tree
/
Copy pathCanvas.java
More file actions
254 lines (213 loc) · 6.68 KB
/
Canvas.java
File metadata and controls
254 lines (213 loc) · 6.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/*
* This file is part of NodeBox.
*
* Copyright (C) 2008 Frederik De Bleser (frederik@pandora.be)
*
* NodeBox 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
* (at your option) any later version.
*
* NodeBox 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 NodeBox. If not, see <http://www.gnu.org/licenses/>.
*/
package nodebox.graphics;
import nodebox.util.FileUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
public class Canvas extends AbstractTransformable {
public static final float DEFAULT_WIDTH = 1000;
public static final float DEFAULT_HEIGHT = 1000;
private Color background = new Color(1, 1, 1);
private float offsetX, offsetY;
private float width, height;
private ArrayList<Grob> items = new ArrayList<Grob>();
public Canvas() {
this(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
public Canvas(float width, float height) {
setSize(width, height);
}
public Canvas(Canvas other) {
this.offsetX = other.offsetX;
this.offsetY = other.offsetY;
this.width = other.width;
this.height = other.height;
this.background = other.background == null ? null : other.background.clone();
for (Grob g : other.items) {
add(g.clone());
}
}
/**
* Convert the current canvas into a geometry object.
* Only objects of a geometric nature can be present in the output.
*
* @return a Geometry object
*/
public Geometry asGeometry() {
return asGeometry(true);
}
/**
* Convert the current canvas into a geometry object.
* Only objects of a geometric nature can be present in the output.
*
* @param clone if the items on the canvas need to be cloned.
* @return a Geometry object
*/
public Geometry asGeometry(boolean clone) {
Geometry g = new Geometry();
for (Grob item : items) {
if (item instanceof Path)
g.add((Path) (clone ? item.clone() : item));
else if (item instanceof Text)
g.add(((Text) item).getPath());
else if (item instanceof Geometry)
g.extend((Geometry) (clone ? item.clone() : item));
}
return g;
}
public Color getBackground() {
return background;
}
public Color setBackground(Color background) {
return this.background = background;
}
public float getOffsetX() {
return offsetX;
}
public void setOffsetX(float offsetX) {
this.offsetX = offsetX;
}
public float getOffsetY() {
return offsetY;
}
public void setOffsetY(float offsetY) {
this.offsetY = offsetY;
}
public float getWidth() {
return width;
}
public void setWidth(float width) {
this.width = width;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public void setSize(float width, float height) {
this.width = width;
this.height = height;
}
//// Container operations ////
public void add(Grob g) {
items.add(g);
}
public int size() {
return items.size();
}
public void clear() {
items.clear();
}
public java.util.List<Grob> getItems() {
return items;
}
public Grob get(int index) {
try {
return items.get(index);
} catch (IndexOutOfBoundsException e) {
return null;
}
}
/**
* Create copies of all grobs of the given group and append them to myself.
*
* @param c the canvas whose elements are appended.
*/
public void extend(Canvas c) {
for (Grob grob : c.getItems()) {
add(grob.clone());
}
}
public void transform(Transform t) {
for (Grob g : items) {
g.transform(t);
}
}
//// Geometry ////
public boolean isEmpty() {
return items.isEmpty();
}
/**
* Returns the bounding box of the canvas.
* <p/>
* This does not compute the bounding boxes of the children, but always returns the requested canvas bounds.
*
* @return a bounding box with x/y at the center and width/height of the canvas.
*/
public Rect getBounds() {
return new Rect(-width / 2 + offsetX, -height / 2 + offsetY, width, height);
}
public Canvas clone() {
return new Canvas(this);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Canvas)) return false;
Canvas other = (Canvas) obj;
return width == other.width
&& height == other.height
&& background.equals(other.background)
&& super.equals(other);
}
//// Drawing ////
public void inheritFromContext(GraphicsContext ctx) {
// TODO: Implement
}
public void draw(Graphics2D g) {
if (background != null) {
g.setColor(background.getAwtColor());
g.fill(getBounds().getRectangle2D());
}
g.clip(getBounds().getRectangle2D());
for (Grob grob : items) {
grob.draw(g);
}
}
public BufferedImage asImage() {
Rect bounds = getBounds();
BufferedImage img = new BufferedImage(Math.round(bounds.getWidth()), Math.round(bounds.getHeight()), BufferedImage.TYPE_INT_ARGB);
Graphics2D g = img.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.translate(-bounds.getX(), -bounds.getY());
draw(g);
img.flush();
return img;
}
public void save(File file) {
if (file.getName().endsWith(".pdf")) {
PDFRenderer.render(this, file);
} else {
try {
ImageIO.write(asImage(), FileUtils.getExtension(file), file);
} catch (IOException e) {
throw new RuntimeException("Could not write image file " + file, e);
}
}
}
@Override
public String toString() {
return "<" + getClass().getSimpleName() + ": " + width + ", " + height + ">";
}
}