1 7 package com.sun.java.swing.plaf.nimbus; 8 9 import java.awt.GraphicsConfiguration ; 10 import java.awt.Image ; 11 import java.lang.ref.ReferenceQueue ; 12 import java.lang.ref.SoftReference ; 13 import java.util.Arrays ; 14 import java.util.Iterator ; 15 import java.util.LinkedHashMap ; 16 import java.util.Map ; 17 import java.util.concurrent.locks.ReadWriteLock ; 18 import java.util.concurrent.locks.ReentrantReadWriteLock ; 19 20 28 class ImageCache { 29 private final LinkedHashMap <Integer , PixelCountSoftReference> map = 31 new LinkedHashMap <Integer , PixelCountSoftReference>(16, 0.75f, true); 32 private final int maxPixelCount; 34 private final int maxSingleImagePixelSize; 36 private int currentPixelCount = 0; 38 private ReadWriteLock lock = new ReentrantReadWriteLock (); 40 private ReferenceQueue <Image > referenceQueue = new ReferenceQueue <Image >(); 42 private static final ImageCache instance = new ImageCache(); 44 45 46 47 static ImageCache getInstance() { 48 return instance; 49 } 50 51 public ImageCache() { 52 this.maxPixelCount = (8 * 1024 * 1024) / 4; this.maxSingleImagePixelSize = 300 * 300; 54 } 55 56 public ImageCache(int maxPixelCount, int maxSingleImagePixelSize) { 57 this.maxPixelCount = maxPixelCount; 58 this.maxSingleImagePixelSize = maxSingleImagePixelSize; 59 } 60 61 62 public void flush() { 63 lock.readLock().lock(); 64 try { 65 map.clear(); 66 } finally { 67 lock.readLock().unlock(); 68 } 69 } 70 71 78 public boolean isImageCachable(int w, int h) { 79 return (w * h) < maxSingleImagePixelSize; 80 } 81 82 91 public Image getImage(GraphicsConfiguration config, int w, int h, Object ... args) { 92 lock.readLock().lock(); 93 try { 94 PixelCountSoftReference ref = map.get(hash(config, w, h, args)); 95 if (ref != null && ref.equals(config,w, h, args)) { 97 return ref.get(); 98 } else { 99 return null; 100 } 101 } finally { 102 lock.readLock().unlock(); 103 } 104 } 105 106 116 public boolean setImage(Image image, GraphicsConfiguration config, int w, int h, Object ... args) { 117 if (!isImageCachable(w, h)) return false; 118 int hash = hash(config, w, h, args); 119 lock.writeLock().lock(); 120 try { 121 PixelCountSoftReference ref = map.get(hash); 122 if (ref != null && ref.get() == image) { 124 return true; 125 } 126 if (ref != null) { 128 currentPixelCount -= ref.pixelCount; 129 map.remove(hash); 130 } 131 int newPixelCount = image.getWidth(null) * image.getHeight(null); 133 currentPixelCount += newPixelCount; 134 if (currentPixelCount > maxPixelCount) { 136 while ((ref = (PixelCountSoftReference)referenceQueue.poll()) != null){ 137 map.remove(ref.hash); 139 currentPixelCount -= ref.pixelCount; 140 } 141 } 142 if (currentPixelCount > maxPixelCount) { 144 Iterator <Map.Entry <Integer , PixelCountSoftReference>> mapIter = map.entrySet().iterator(); 145 while ((currentPixelCount > maxPixelCount) && mapIter.hasNext()) { 146 Map.Entry <Integer , PixelCountSoftReference> entry = mapIter.next(); 147 mapIter.remove(); 148 Image img = entry.getValue().get(); 149 if (img != null) img.flush(); 150 currentPixelCount -= entry.getValue().pixelCount; 151 } 152 } 153 map.put(hash, new PixelCountSoftReference(image, referenceQueue, newPixelCount,hash, config, w, h, args)); 155 return true; 156 } finally { 157 lock.writeLock().unlock(); 158 } 159 } 160 161 162 private int hash(GraphicsConfiguration config, int w, int h, Object ... args) { 163 int hash; 164 hash = (config != null ? config.hashCode() : 0); 165 hash = 31 * hash + w; 166 hash = 31 * hash + h; 167 hash = 31 * hash + Arrays.deepHashCode(args); 168 return hash; 169 } 170 171 172 173 private static class PixelCountSoftReference extends SoftReference <Image > { 174 private final int pixelCount; 175 private final int hash; 176 private final GraphicsConfiguration config; 178 private final int w; 179 private final int h; 180 private final Object [] args; 181 182 public PixelCountSoftReference(Image referent, ReferenceQueue <? super Image > q, int pixelCount, int hash, 183 GraphicsConfiguration config, int w, int h, Object [] args) { 184 super(referent, q); 185 this.pixelCount = pixelCount; 186 this.hash = hash; 187 this.config = config; 188 this.w = w; 189 this.h = h; 190 this.args = args; 191 } 192 193 public boolean equals (GraphicsConfiguration config, int w, int h, Object [] args){ 194 return config == this.config && 195 w == this.w && 196 h == this.h && 197 Arrays.equals(args, this.args); 198 } 199 } 200 } 201 | Popular Tags |