- Timestamp:
- 2020-11-26T22:24:27+01:00 (4 years ago)
- Location:
- trunk/src
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/com/kitfox/svg/SVGUniverse.java
r14328 r17364 693 693 this.imageDataInlineOnly = imageDataInlineOnly; 694 694 } 695 696 public String statistics() { 697 return String.format("%s has loaded %d SVG images", this, loadedDocs.size()); 698 } 699 695 700 } -
trunk/src/org/openstreetmap/josm/data/cache/JCSCacheManager.java
r16401 r17364 31 31 import org.openstreetmap.josm.data.preferences.IntegerProperty; 32 32 import org.openstreetmap.josm.spi.preferences.Config; 33 import org.openstreetmap.josm.tools.ImageResource; 33 34 import org.openstreetmap.josm.tools.Logging; 34 35 import org.openstreetmap.josm.tools.Utils; … … 45 46 private static final String PREFERENCE_PREFIX = "jcs.cache"; 46 47 public static final BooleanProperty USE_BLOCK_CACHE = new BooleanProperty(PREFERENCE_PREFIX + ".use_block_cache", true); 48 49 /** 50 * The preference key {@code jcs.cache.use_image_resource_cache} controls the caching mechanism used for {@link ImageResource}. 51 * If set to {@code true}, a combined memory/disk is used. Otherwise, an in-memory-cache is used. 52 */ 53 public static final BooleanProperty USE_IMAGE_RESOURCE_CACHE = new BooleanProperty(PREFERENCE_PREFIX + ".use_image_resource_cache", false); 47 54 48 55 private static final AuxiliaryCacheFactory DISK_CACHE_FACTORY = … … 171 178 * @return cache access object 172 179 */ 180 public static <K, V> CacheAccess<K, V> getCache(String cacheName, int maxMemoryObjects, int maxDiskObjects, String cachePath) { 181 return getCache(cacheName, maxMemoryObjects, maxDiskObjects, cachePath, USE_BLOCK_CACHE.get() ? 4096 : 0); 182 } 183 173 184 @SuppressWarnings("unchecked") 174 public static <K, V> CacheAccess<K, V> getCache(String cacheName, int maxMemoryObjects, int maxDiskObjects, String cachePath) { 185 private static <K, V> CacheAccess<K, V> getCache(String cacheName, int maxMemoryObjects, int maxDiskObjects, 186 String cachePath, int blockSizeBytes) { 175 187 CacheAccess<K, V> cacheAccess = JCS.getInstance(cacheName, getCacheAttributes(maxMemoryObjects)); 176 188 CompositeCache<K, V> cc = cacheAccess.getCacheControl(); 177 189 178 190 if (cachePath != null && cacheDirLock != null) { 179 IDiskCacheAttributes diskAttributes = getDiskCacheAttributes(maxDiskObjects, cachePath, cacheName); 191 IDiskCacheAttributes diskAttributes = getDiskCacheAttributes(maxDiskObjects, cachePath, cacheName, blockSizeBytes); 192 Logging.debug("Setting up cache: {0}", diskAttributes); 180 193 try { 181 194 if (cc.getAuxCaches().length == 0) { … … 193 206 194 207 /** 208 * Returns a cache for {@link ImageResource} 209 * @param <K> key type 210 * @param <V> value type 211 * @return cache access object 212 */ 213 public static <K, V> CacheAccess<K, V> getImageResourceCache() { 214 if (!USE_IMAGE_RESOURCE_CACHE.get()) { 215 return getCache("images", 16 * 1024, 0, null); 216 } 217 String cachePath = new File(Config.getDirs().getCacheDirectory(true), "images").getAbsolutePath(); 218 Logging.warn("Using experimental disk cache {0} for ImageResource", cachePath); 219 return getCache("images", 16 * 1024, 512 * 1024, cachePath, 1024); 220 } 221 222 /** 195 223 * Close all files to ensure, that all indexes and data are properly written 196 224 */ … … 199 227 } 200 228 201 private static IDiskCacheAttributes getDiskCacheAttributes(int maxDiskObjects, String cachePath, String cacheName ) {229 private static IDiskCacheAttributes getDiskCacheAttributes(int maxDiskObjects, String cachePath, String cacheName, int blockSizeBytes) { 202 230 IDiskCacheAttributes ret; 203 removeStaleFiles(cachePath + File.separator + cacheName, USE_BLOCK_CACHE.get() ? "_INDEX_v2" : "_BLOCK_v2"); 204 String newCacheName = cacheName + (USE_BLOCK_CACHE.get() ? "_BLOCK_v2" : "_INDEX_v2"); 205 206 if (USE_BLOCK_CACHE.get()) { 231 boolean isBlockDiskCache = blockSizeBytes > 0; 232 removeStaleFiles(cachePath + File.separator + cacheName, isBlockDiskCache ? "_INDEX_v2" : "_BLOCK_v2"); 233 String newCacheName = cacheName + (isBlockDiskCache ? "_BLOCK_v2" : "_INDEX_v2"); 234 235 if (isBlockDiskCache) { 207 236 BlockDiskCacheAttributes blockAttr = new BlockDiskCacheAttributes(); 208 237 /* … … 218 247 blockAttr.setMaxKeySize(maxDiskObjects); 219 248 } 220 blockAttr.setBlockSizeBytes( 4096); // use 4k blocks249 blockAttr.setBlockSizeBytes(blockSizeBytes); 221 250 ret = blockAttr; 222 251 } else { -
trunk/src/org/openstreetmap/josm/gui/MainInitialization.java
r17188 r17364 153 153 MainApplication.toolbar.control.updateUI(); 154 154 MainApplication.contentPanePrivate.updateUI(); 155 // image provider statistics 156 ImageProvider.printStatistics(); 155 157 })) 156 158 ); -
trunk/src/org/openstreetmap/josm/tools/ImageProvider.java
r17144 r17364 954 954 continue; 955 955 } 956 ir = getIfAvailableLocalURL( path, type);956 ir = getIfAvailableLocalURL(subdir + name, path, type); 957 957 if (ir != null) { 958 958 cache.put(cacheName, ir); … … 984 984 svg = getSvgUniverse().getDiagram(uri); 985 985 } 986 return svg == null ? null : new ImageResource( svg);986 return svg == null ? null : new ImageResource(url, svg); 987 987 case OTHER: 988 988 BufferedImage img = null; … … 992 992 Logging.log(Logging.LEVEL_WARN, "Exception while reading HTTP image:", e); 993 993 } 994 return img == null ? null : new ImageResource( img);994 return img == null ? null : new ImageResource(url, img); 995 995 default: 996 996 throw new AssertionError("Unsupported type: " + type); … … 1041 1041 return null; 1042 1042 } 1043 return new ImageResource( svg);1043 return new ImageResource(url, svg); 1044 1044 } else { 1045 1045 try { … … 1050 1050 // CHECKSTYLE.ON: LineLength 1051 1051 Image img = read(new ByteArrayInputStream(bytes), false, true); 1052 return img == null ? null : new ImageResource( img);1052 return img == null ? null : new ImageResource(url, img); 1053 1053 } catch (IOException | UnsatisfiedLinkError e) { 1054 1054 Logging.log(Logging.LEVEL_WARN, "Exception while reading image:", e); … … 1125 1125 svg = getSvgUniverse().getDiagram(uri); 1126 1126 } 1127 return svg == null ? null : new ImageResource( svg);1127 return svg == null ? null : new ImageResource(fullName, svg); 1128 1128 case OTHER: 1129 1129 while (size > 0) { … … 1138 1138 Logging.warn(e); 1139 1139 } 1140 return img == null ? null : new ImageResource( img);1140 return img == null ? null : new ImageResource(fullName, img); 1141 1141 default: 1142 1142 throw new AssertionError("Unknown ImageType: "+type); … … 1157 1157 * @return the requested image or null if the request failed 1158 1158 */ 1159 private static ImageResource getIfAvailableLocalURL( URL path, ImageType type) {1159 private static ImageResource getIfAvailableLocalURL(String cacheKey, URL path, ImageType type) { 1160 1160 switch (type) { 1161 1161 case SVG: 1162 SVGDiagram svg = null; 1163 synchronized (getSvgUniverse()) { 1164 try { 1165 URI uri = null; 1162 return new ImageResource(cacheKey, () -> { 1163 synchronized (getSvgUniverse()) { 1166 1164 try { 1167 uri = getSvgUniverse().loadSVG(path); 1168 } catch (InvalidPathException e) { 1169 Logging.error("Cannot open {0}: {1}", path, e.getMessage()); 1170 Logging.trace(e); 1165 URI uri = null; 1166 try { 1167 uri = getSvgUniverse().loadSVG(path); 1168 } catch (InvalidPathException e) { 1169 Logging.error("Cannot open {0}: {1}", path, e.getMessage()); 1170 Logging.trace(e); 1171 } 1172 if (uri == null && "jar".equals(path.getProtocol())) { 1173 URL betterPath = Utils.betterJarUrl(path); 1174 if (betterPath != null) { 1175 uri = getSvgUniverse().loadSVG(betterPath); 1176 } 1177 } 1178 return getSvgUniverse().getDiagram(uri); 1179 } catch (SecurityException | IOException e) { 1180 Logging.log(Logging.LEVEL_WARN, "Unable to read SVG", e); 1171 1181 } 1172 if (uri == null && "jar".equals(path.getProtocol())) { 1173 URL betterPath = Utils.betterJarUrl(path); 1174 if (betterPath != null) { 1175 uri = getSvgUniverse().loadSVG(betterPath); 1176 } 1177 } 1178 svg = getSvgUniverse().getDiagram(uri); 1179 } catch (SecurityException | IOException e) { 1180 Logging.log(Logging.LEVEL_WARN, "Unable to read SVG", e); 1181 } 1182 } 1183 return svg == null ? null : new ImageResource(svg); 1182 } 1183 return null; 1184 }); 1184 1185 case OTHER: 1185 1186 BufferedImage img = null; … … 1196 1197 Logging.debug(e); 1197 1198 } 1198 return img == null ? null : new ImageResource( img);1199 return img == null ? null : new ImageResource(path.toString(), img); 1199 1200 default: 1200 1201 throw new AssertionError(); … … 1394 1395 */ 1395 1396 public static Image createBoundedImage(Image img, int maxSize) { 1396 return new ImageResource(img ).getImageIconBounded(new Dimension(maxSize, maxSize)).getImage();1397 return new ImageResource(img.toString(), img).getImageIconBounded(new Dimension(maxSize, maxSize)).getImage(); 1397 1398 } 1398 1399 … … 1933 1934 } 1934 1935 1936 /** 1937 * Prints statistics concerning the image loading caches. 1938 */ 1939 public static void printStatistics() { 1940 Logging.info(getSvgUniverse().statistics()); 1941 Logging.info(ImageResource.statistics()); 1942 } 1943 1935 1944 @Override 1936 1945 public String toString() { -
trunk/src/org/openstreetmap/josm/tools/ImageResource.java
r17144 r17364 5 5 import java.awt.Image; 6 6 import java.awt.image.BufferedImage; 7 import java.io.IOException; 8 import java.io.UncheckedIOException; 7 9 import java.util.List; 8 import java.util.Map; 9 import java.util.concurrent.ConcurrentHashMap; 10 import java.util.Locale; 11 import java.util.Objects; 12 import java.util.function.Supplier; 10 13 11 14 import javax.swing.AbstractAction; … … 15 18 import javax.swing.JPanel; 16 19 import javax.swing.UIManager; 20 21 import org.apache.commons.jcs3.access.behavior.ICacheAccess; 22 import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry; 23 import org.openstreetmap.josm.data.cache.JCSCacheManager; 17 24 18 25 import com.kitfox.svg.SVGDiagram; … … 29 36 30 37 /** 31 * Caches the image data for resized versions of the same image. The key is obtained using {@link ImageResizeMode#cacheKey(Dimension)}. 32 */ 33 private final Map<Integer, BufferedImage> imgCache = new ConcurrentHashMap<>(4); 38 * Caches the image data for resized versions of the same image. 39 * Depending on {@link JCSCacheManager#USE_IMAGE_RESOURCE_CACHE}, a combined memory/disk, or an in-memory-cache is used. 40 */ 41 private static final ICacheAccess<String, BufferedImageCacheEntry> imgCache = JCSCacheManager.getImageResourceCache(); 42 43 private final String cacheKey; 34 44 /** 35 45 * SVG diagram information in case of SVG vector image. … … 37 47 private SVGDiagram svg; 38 48 /** 49 * Supplier for SVG diagram information in case of possibly cached SVG vector image. 50 */ 51 private Supplier<SVGDiagram> svgSupplier; 52 /** 39 53 * Use this dimension to request original file dimension. 40 54 */ … … 55 69 /** 56 70 * Constructs a new {@code ImageResource} from an image. 71 * @param cacheKey the caching identifier of the image 57 72 * @param img the image 58 73 */ 59 public ImageResource( Image img) {60 CheckParameterUtil.ensureParameterNotNull(img);61 baseImage = img;74 public ImageResource(String cacheKey, Image img) { 75 this.cacheKey = Objects.requireNonNull(cacheKey); 76 this.baseImage = Objects.requireNonNull(img); 62 77 } 63 78 64 79 /** 65 80 * Constructs a new {@code ImageResource} from SVG data. 81 * @param cacheKey the caching identifier of the image 66 82 * @param svg SVG data 67 83 */ 68 public ImageResource(SVGDiagram svg) { 69 CheckParameterUtil.ensureParameterNotNull(svg); 70 this.svg = svg; 84 public ImageResource(String cacheKey, SVGDiagram svg) { 85 this.cacheKey = Objects.requireNonNull(cacheKey); 86 this.svg = Objects.requireNonNull(svg); 87 } 88 89 public ImageResource(String cacheKey, Supplier<SVGDiagram> svgSupplier) { 90 this.cacheKey = Objects.requireNonNull(cacheKey); 91 this.svgSupplier = Objects.requireNonNull(svgSupplier); 71 92 } 72 93 … … 78 99 */ 79 100 public ImageResource(ImageResource res, List<ImageOverlay> overlayInfo) { 101 this.cacheKey = res.cacheKey; 80 102 this.svg = res.svg; 103 this.svgSupplier = res.svgSupplier; 81 104 this.baseImage = res.baseImage; 82 105 this.overlayInfo = overlayInfo; … … 157 180 ImageIcon getImageIcon(Dimension dim, boolean multiResolution, ImageResizeMode resizeMode) { 158 181 return getImageIconAlreadyScaled(GuiSizesHelper.getDimensionDpiAdjusted(dim), multiResolution, false, resizeMode); 182 } 183 184 private BufferedImage getImageFromCache(String cacheKey) { 185 try { 186 BufferedImageCacheEntry image = imgCache.get(cacheKey); 187 if (image == null || image.getImage() == null) { 188 return null; 189 } 190 Logging.trace("{0} is in cache :-)", cacheKey); 191 return image.getImage(); 192 } catch (IOException e) { 193 throw new UncheckedIOException(e); 194 } 159 195 } 160 196 … … 181 217 resizeMode = ImageResizeMode.BOUNDED; 182 218 } 183 final int cacheKey = resizeMode.cacheKey(dim); 184 BufferedImage img = imgCache.get(cacheKey); 219 final String cacheKey = String.format(Locale.ROOT, "%s--%s--%d--%d", 220 this.cacheKey, resizeMode.name(), dim.width, dim.height); 221 BufferedImage img = getImageFromCache(cacheKey); 185 222 if (img == null) { 223 if (svgSupplier != null) { 224 svg = svgSupplier.get(); 225 Logging.trace("{0} is not in cache :-(", cacheKey); 226 svgSupplier = null; 227 } 186 228 if (svg != null) { 187 229 img = ImageProvider.createImageFromSvg(svg, dim, resizeMode); … … 211 253 disabledIcon.paintIcon(new JPanel(), img.getGraphics(), 0, 0); 212 254 } 213 imgCache.put(cacheKey, img); 255 if (img == null) { 256 return null; 257 } 258 BufferedImageCacheEntry cacheEntry = BufferedImageCacheEntry.pngEncoded(img); 259 Logging.trace("Storing {0} ({1} bytes) in cache...", cacheKey, cacheEntry.getContent().length); 260 imgCache.put(cacheKey, cacheEntry); 214 261 } 215 262 … … 251 298 } 252 299 300 static String statistics() { 301 return String.format("ImageResource cache: [%s]", imgCache.getStatistics()); 302 } 303 253 304 @Override 254 305 public String toString() {
Note:
See TracChangeset
for help on using the changeset viewer.