Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/sun/swing/CachedPainter.java
41153 views
1
/*
2
* Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
package sun.swing;
26
27
import sun.awt.image.SurfaceManager;
28
import sun.java2d.SurfaceData;
29
import java.awt.Component;
30
import java.awt.Graphics;
31
import java.awt.Graphics2D;
32
import java.awt.GraphicsConfiguration;
33
import java.awt.Image;
34
import java.awt.geom.AffineTransform;
35
import java.awt.image.AbstractMultiResolutionImage;
36
import java.awt.image.BufferedImage;
37
import java.awt.image.ImageObserver;
38
import java.awt.image.VolatileImage;
39
import java.util.Arrays;
40
import java.util.HashMap;
41
import java.util.Map;
42
43
/**
44
* A base class used for icons or images that are expensive to paint.
45
* A subclass will do the following:
46
* <ol>
47
* <li>Invoke <code>paint</code> when you want to paint the image,
48
* if you are implementing <code>Icon</code> you'll invoke this from
49
* <code>paintIcon</code>.
50
* The args argument is useful when additional state is needed.
51
* <li>Override <code>paintToImage</code> to render the image. The code that
52
* lives here is equivalent to what previously would go in
53
* <code>paintIcon</code>, for an <code>Icon</code>.
54
* </ol>
55
* The two ways to use this class are:
56
* <ol>
57
* <li>Invoke <code>paint</code> to draw the cached reprensentation at
58
* the specified location.
59
* <li>Invoke <code>getImage</code> to get the cached reprensentation and
60
* draw the image yourself. This is primarly useful when you are not
61
* using <code>VolatileImage</code>.
62
* </ol>
63
*
64
*
65
*/
66
public abstract class CachedPainter {
67
// CacheMap maps from class to ImageCache.
68
private static final Map<Object,ImageCache> cacheMap = new HashMap<>();
69
70
private static ImageCache getCache(Object key) {
71
synchronized(CachedPainter.class) {
72
ImageCache cache = cacheMap.get(key);
73
if (cache == null) {
74
if (key == PainterMultiResolutionCachedImage.class) {
75
cache = new ImageCache(32);
76
} else {
77
cache = new ImageCache(1);
78
}
79
cacheMap.put(key, cache);
80
}
81
return cache;
82
}
83
}
84
85
/**
86
* Creates an instance of <code>CachedPainter</code> that will cache up
87
* to <code>cacheCount</code> images of this class.
88
*
89
* @param cacheCount Max number of images to cache
90
*/
91
public CachedPainter(int cacheCount) {
92
getCache(getClass()).setMaxCount(cacheCount);
93
}
94
95
/**
96
* Renders the cached image to the passed in <code>Graphic</code>.
97
* If there is no cached image <code>paintToImage</code> will be invoked.
98
* <code>paintImage</code> is invoked to paint the cached image.
99
*
100
* @param c Component rendering to, this may be null.
101
* @param g Graphics to paint to
102
* @param x X-coordinate to render to
103
* @param y Y-coordinate to render to
104
* @param w Width to render in
105
* @param h Height to render in
106
* @param args Variable arguments that will be passed to paintToImage
107
*/
108
public void paint(Component c, Graphics g, int x,
109
int y, int w, int h, Object... args) {
110
if (w <= 0 || h <= 0) {
111
return;
112
}
113
synchronized (CachedPainter.class) {
114
paint0(c, g, x, y, w, h, args);
115
}
116
}
117
118
private Image getImage(Object key, Component c,
119
int baseWidth, int baseHeight,
120
int w, int h, Object... args) {
121
GraphicsConfiguration config = getGraphicsConfiguration(c);
122
ImageCache cache = getCache(key);
123
Image image = cache.getImage(key, config, w, h, args);
124
int attempts = 0;
125
VolatileImage volatileImage = (image instanceof VolatileImage)
126
? (VolatileImage) image
127
: null;
128
do {
129
boolean draw = false;
130
if (volatileImage != null) {
131
// See if we need to recreate the image
132
switch (volatileImage.validate(config)) {
133
case VolatileImage.IMAGE_INCOMPATIBLE:
134
volatileImage.flush();
135
image = null;
136
break;
137
case VolatileImage.IMAGE_RESTORED:
138
draw = true;
139
break;
140
}
141
}
142
if (image == null) {
143
// Recreate the image
144
if( config != null && (w != baseHeight || h != baseWidth)) {
145
AffineTransform tx = config.getDefaultTransform();
146
double sx = tx.getScaleX();
147
double sy = tx.getScaleY();
148
if ( Double.compare(sx, 1) != 0 ||
149
Double.compare(sy, 1) != 0) {
150
if (Math.abs(sx * baseWidth - w) < 1 &&
151
Math.abs(sy * baseHeight - h) < 1) {
152
w = baseWidth;
153
h = baseHeight;
154
} else {
155
w = (int)Math.ceil(w / sx);
156
h = (int)Math.ceil(w / sy);
157
}
158
}
159
}
160
image = createImage(c, w, h, config, args);
161
cache.setImage(key, config, w, h, args, image);
162
draw = true;
163
volatileImage = (image instanceof VolatileImage)
164
? (VolatileImage) image
165
: null;
166
}
167
if (draw) {
168
// Render to the Image
169
Graphics2D g2 = (Graphics2D) image.getGraphics();
170
if (volatileImage == null) {
171
if ((w != baseWidth || h != baseHeight)) {
172
g2.scale((double) w / baseWidth,
173
(double) h / baseHeight);
174
}
175
paintToImage(c, image, g2, baseWidth, baseHeight, args);
176
} else {
177
SurfaceData sd = SurfaceManager.getManager(volatileImage)
178
.getPrimarySurfaceData();
179
double sx = sd.getDefaultScaleX();
180
double sy = sd.getDefaultScaleY();
181
if ( Double.compare(sx, 1) != 0 ||
182
Double.compare(sy, 1) != 0) {
183
g2.scale(1 / sx, 1 / sy);
184
}
185
paintToImage(c, image, g2, (int)Math.ceil(w * sx),
186
(int)Math.ceil(h * sy), args);
187
}
188
g2.dispose();
189
}
190
191
// If we did this 3 times and the contents are still lost
192
// assume we're painting to a VolatileImage that is bogus and
193
// give up. Presumably we'll be called again to paint.
194
} while ((volatileImage != null) &&
195
volatileImage.contentsLost() && ++attempts < 3);
196
197
return image;
198
}
199
200
private void paint0(Component c, Graphics g, int x,
201
int y, int w, int h, Object... args) {
202
Object key = getClass();
203
GraphicsConfiguration config = getGraphicsConfiguration(c);
204
ImageCache cache = getCache(key);
205
Image image = cache.getImage(key, config, w, h, args);
206
207
if (image == null) {
208
image = new PainterMultiResolutionCachedImage(w, h);
209
cache.setImage(key, config, w, h, args, image);
210
}
211
212
if (image instanceof PainterMultiResolutionCachedImage) {
213
((PainterMultiResolutionCachedImage) image).setParams(c, args);
214
}
215
216
// Render to the passed in Graphics
217
paintImage(c, g, x, y, w, h, image, args);
218
}
219
220
/**
221
* Paints the representation to cache to the supplied Graphics.
222
*
223
* @param c Component painting to, may be null.
224
* @param image Image to paint to
225
* @param g Graphics to paint to, obtained from the passed in Image.
226
* @param w Width to paint to
227
* @param h Height to paint to
228
* @param args Arguments supplied to <code>paint</code>
229
*/
230
protected abstract void paintToImage(Component c, Image image, Graphics g,
231
int w, int h, Object[] args);
232
233
234
/**
235
* Paints the image to the specified location.
236
*
237
* @param c Component painting to
238
* @param g Graphics to paint to
239
* @param x X coordinate to paint to
240
* @param y Y coordinate to paint to
241
* @param w Width to paint to
242
* @param h Height to paint to
243
* @param image Image to paint
244
* @param args Arguments supplied to <code>paint</code>
245
*/
246
protected void paintImage(Component c, Graphics g,
247
int x, int y, int w, int h, Image image,
248
Object[] args) {
249
g.drawImage(image, x, y, null);
250
}
251
252
/**
253
* Creates the image to cache. This returns an opaque image, subclasses
254
* that require translucency or transparency will need to override this
255
* method.
256
*
257
* @param c Component painting to
258
* @param w Width of image to create
259
* @param h Height to image to create
260
* @param config GraphicsConfiguration that will be
261
* rendered to, this may be null.
262
* @param args Arguments passed to paint
263
*/
264
protected Image createImage(Component c, int w, int h,
265
GraphicsConfiguration config, Object[] args) {
266
if (config == null) {
267
return new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
268
}
269
return config.createCompatibleVolatileImage(w, h);
270
}
271
272
/**
273
* Clear the image cache
274
*/
275
protected void flush() {
276
synchronized(CachedPainter.class) {
277
getCache(getClass()).flush();
278
}
279
}
280
281
private GraphicsConfiguration getGraphicsConfiguration(Component c) {
282
if (c == null) {
283
return null;
284
}
285
return c.getGraphicsConfiguration();
286
}
287
288
class PainterMultiResolutionCachedImage extends AbstractMultiResolutionImage {
289
290
private final int baseWidth;
291
private final int baseHeight;
292
private Component c;
293
private Object[] args;
294
295
public PainterMultiResolutionCachedImage(int baseWidth, int baseHeight) {
296
this.baseWidth = baseWidth;
297
this.baseHeight = baseHeight;
298
}
299
300
public void setParams(Component c, Object[] args) {
301
this.c = c;
302
this.args = args;
303
}
304
305
@Override
306
public int getWidth(ImageObserver observer) {
307
return baseWidth;
308
}
309
310
@Override
311
public int getHeight(ImageObserver observer) {
312
return baseHeight;
313
}
314
315
@Override
316
public Image getResolutionVariant(double destWidth, double destHeight) {
317
int w = (int) Math.ceil(destWidth);
318
int h = (int) Math.ceil(destHeight);
319
return getImage(PainterMultiResolutionCachedImage.class,
320
c, baseWidth, baseHeight, w, h, args);
321
}
322
323
@Override
324
protected Image getBaseImage() {
325
return getResolutionVariant(baseWidth, baseHeight);
326
}
327
328
@Override
329
public java.util.List<Image> getResolutionVariants() {
330
return Arrays.asList(getResolutionVariant(baseWidth, baseHeight));
331
}
332
}
333
}
334
335