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

Last change on this file since 8256 was 8103, checked in by bastiK, 9 years ago

fixed #11163 - map symbols of an inactive (for editing) data layer have a black background (full rectangle)

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