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

Last change on this file since 9278 was 9278, checked in by bastiK, 8 years ago

move ElemStyle classes to new package, rename to (Style)Element

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