source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/MapImage.java@ 12378

Last change on this file since 12378 was 12303, checked in by michael2402, 7 years ago

Javadoc for package org.openstreetmap.josm.gui.mappaint.styleelement

  • Property svn:eol-style set to native
File size: 9.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint.styleelement;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Graphics;
7import java.awt.Image;
8import java.awt.Rectangle;
9import java.awt.image.BufferedImage;
10import java.util.Objects;
11
12import javax.swing.ImageIcon;
13
14import org.openstreetmap.josm.Main;
15import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
16import org.openstreetmap.josm.gui.mappaint.StyleSource;
17import org.openstreetmap.josm.gui.mappaint.styleelement.BoxTextElement.BoxProvider;
18import org.openstreetmap.josm.gui.mappaint.styleelement.BoxTextElement.BoxProviderResult;
19import org.openstreetmap.josm.gui.util.GuiHelper;
20import org.openstreetmap.josm.tools.ImageProvider;
21import org.openstreetmap.josm.tools.Utils;
22
23/**
24 * An image that will be displayed on the map.
25 */
26public class MapImage {
27
28 private static final int MAX_SIZE = 48;
29
30 /**
31 * ImageIcon can change while the image is loading.
32 */
33 private BufferedImage img;
34
35 /**
36 * The alpha (opacity) value of the image. It is multiplied to the image alpha channel.
37 * Range: 0...255
38 */
39 public int alpha = 255;
40 /**
41 * The name of the image that should be displayed. It is given to the {@link ImageProvider}
42 */
43 public String name;
44 /**
45 * The StyleSource that registered the image
46 */
47 public StyleSource source;
48 /**
49 * A flag indicating that the image should automatically be scaled to the right size.
50 */
51 public boolean autoRescale;
52 /**
53 * The width of the image, as set by MapCSS
54 */
55 public int width = -1;
56 /**
57 * The height of the image, as set by MapCSS
58 */
59 public int height = -1;
60 /**
61 * The x offset of the anchor of this image
62 */
63 public int offsetX;
64 /**
65 * The y offset of the anchor of this image
66 */
67 public int offsetY;
68
69 private boolean temporary;
70
71 /**
72 * A cache that holds a disabled (gray) version of this image
73 */
74 private BufferedImage disabledImgCache;
75
76 /**
77 * Creates a new {@link MapImage}
78 * @param name The image name
79 * @param source The style source that requests this image
80 */
81 public MapImage(String name, StyleSource source) {
82 this(name, source, true);
83 }
84
85 /**
86 * Creates a new {@link MapImage}
87 * @param name The image name
88 * @param source The style source that requests this image
89 * @param autoRescale A flag indicating to automatically adjust the width/height of the image
90 */
91 public MapImage(String name, StyleSource source, boolean autoRescale) {
92 this.name = name;
93 this.source = source;
94 this.autoRescale = autoRescale;
95 }
96
97 /**
98 * Get the image associated with this MapImage object.
99 *
100 * @param disabled {@code} true to request disabled version, {@code false} for the standard version
101 * @return the image
102 */
103 public BufferedImage getImage(boolean disabled) {
104 if (disabled) {
105 return getDisabled();
106 } else {
107 return getImage();
108 }
109 }
110
111 private BufferedImage getDisabled() {
112 if (disabledImgCache != null)
113 return disabledImgCache;
114 if (img == null)
115 getImage(); // fix #7498 ?
116 Image disImg = GuiHelper.getDisabledImage(img);
117 if (disImg instanceof BufferedImage) {
118 disabledImgCache = (BufferedImage) disImg;
119 } else {
120 disabledImgCache = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
121 Graphics g = disabledImgCache.getGraphics();
122 g.drawImage(disImg, 0, 0, null);
123 g.dispose();
124 }
125 return disabledImgCache;
126 }
127
128 private BufferedImage getImage() {
129 if (img != null)
130 return img;
131 temporary = false;
132 new ImageProvider(name)
133 .setDirs(MapPaintStyles.getIconSourceDirs(source))
134 .setId("mappaint."+source.getPrefName())
135 .setArchive(source.zipIcons)
136 .setInArchiveDir(source.getZipEntryDirName())
137 .setWidth(width)
138 .setHeight(height)
139 .setOptional(true)
140 .getAsync().thenAccept(result -> {
141 synchronized (this) {
142 if (result == null) {
143 source.logWarning(tr("Failed to locate image ''{0}''", name));
144 ImageIcon noIcon = MapPaintStyles.getNoIconIcon(source);
145 img = noIcon == null ? null : (BufferedImage) noIcon.getImage();
146 } else {
147 img = (BufferedImage) rescale(result.getImage());
148 }
149 if (temporary) {
150 disabledImgCache = null;
151 Main.map.mapView.preferenceChanged(null); // otherwise repaint is ignored, because layer hasn't changed
152 Main.map.mapView.repaint();
153 }
154 temporary = false;
155 }
156 }
157 );
158 synchronized (this) {
159 if (img == null) {
160 img = (BufferedImage) ImageProvider.get("clock").getImage();
161 temporary = true;
162 }
163 }
164 return img;
165 }
166
167 /**
168 * Gets the image width
169 * @return The real image width
170 */
171 public int getWidth() {
172 return getImage().getWidth(null);
173 }
174
175 /**
176 * Gets the image height
177 * @return The real image height
178 */
179 public int getHeight() {
180 return getImage().getHeight(null);
181 }
182
183 /**
184 * Gets the alpha value the image should be multiplied with
185 * @return The value in range 0..1
186 */
187 public float getAlphaFloat() {
188 return Utils.colorInt2float(alpha);
189 }
190
191 /**
192 * Determines if image is not completely loaded and {@code getImage()} returns a temporary image.
193 * @return {@code true} if image is not completely loaded and getImage() returns a temporary image
194 */
195 public boolean isTemporary() {
196 return temporary;
197 }
198
199 protected class MapImageBoxProvider implements BoxProvider {
200 @Override
201 public BoxProviderResult get() {
202 return new BoxProviderResult(box(), temporary);
203 }
204
205 private Rectangle box() {
206 int w = getWidth(), h = getHeight();
207 if (mustRescale(getImage())) {
208 w = 16;
209 h = 16;
210 }
211 return new Rectangle(-w/2, -h/2, w, h);
212 }
213
214 private MapImage getParent() {
215 return MapImage.this;
216 }
217
218 @Override
219 public int hashCode() {
220 return MapImage.this.hashCode();
221 }
222
223 @Override
224 public boolean equals(Object obj) {
225 if (!(obj instanceof BoxProvider))
226 return false;
227 if (obj instanceof MapImageBoxProvider) {
228 MapImageBoxProvider other = (MapImageBoxProvider) obj;
229 return MapImage.this.equals(other.getParent());
230 } else if (temporary) {
231 return false;
232 } else {
233 final BoxProvider other = (BoxProvider) obj;
234 BoxProviderResult resultOther = other.get();
235 if (resultOther.isTemporary()) return false;
236 return box().equals(resultOther.getBox());
237 }
238 }
239 }
240
241 /**
242 * Gets a box provider that provides a box that covers the size of this image
243 * @return The box provider
244 */
245 public BoxProvider getBoxProvider() {
246 return new MapImageBoxProvider();
247 }
248
249 /**
250 * Rescale excessively large images.
251 * @param image the unscaled image
252 * @return The scaled down version to 16x16 pixels if the image height and width exceeds 48 pixels and no size has been explicitely specified
253 */
254 private Image rescale(Image image) {
255 if (image == null) return null;
256 // Scale down large (.svg) images to 16x16 pixels if no size is explicitely specified
257 if (mustRescale(image)) {
258 return ImageProvider.createBoundedImage(image, 16);
259 } else {
260 return image;
261 }
262 }
263
264 private boolean mustRescale(Image image) {
265 return autoRescale && width == -1 && image.getWidth(null) > MAX_SIZE
266 && height == -1 && image.getHeight(null) > MAX_SIZE;
267 }
268
269 @Override
270 public boolean equals(Object obj) {
271 if (this == obj) return true;
272 if (obj == null || getClass() != obj.getClass()) return false;
273 MapImage mapImage = (MapImage) obj;
274 return alpha == mapImage.alpha &&
275 autoRescale == mapImage.autoRescale &&
276 width == mapImage.width &&
277 height == mapImage.height &&
278 Objects.equals(name, mapImage.name) &&
279 Objects.equals(source, mapImage.source);
280 }
281
282 @Override
283 public int hashCode() {
284 return Objects.hash(alpha, name, source, autoRescale, width, height);
285 }
286
287 @Override
288 public String toString() {
289 return name;
290 }
291}
Note: See TracBrowser for help on using the repository browser.