Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
0be06f1c
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
0be06f1c
编写于
1月 30, 2014
作者:
A
alexsch
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8011059: [macosx] Support automatic @2x images loading on Mac OS X
Reviewed-by: serb, flar
上级
a8304d97
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
1180 addition
and
78 deletion
+1180
-78
src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java
src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java
+58
-2
src/share/classes/java/awt/MediaTracker.java
src/share/classes/java/awt/MediaTracker.java
+44
-4
src/share/classes/sun/awt/SunHints.java
src/share/classes/sun/awt/SunHints.java
+26
-1
src/share/classes/sun/awt/SunToolkit.java
src/share/classes/sun/awt/SunToolkit.java
+133
-64
src/share/classes/sun/awt/image/MultiResolutionImage.java
src/share/classes/sun/awt/image/MultiResolutionImage.java
+83
-0
src/share/classes/sun/awt/image/MultiResolutionToolkitImage.java
...re/classes/sun/awt/image/MultiResolutionToolkitImage.java
+104
-0
src/share/classes/sun/java2d/SunGraphics2D.java
src/share/classes/sun/java2d/SunGraphics2D.java
+112
-7
test/java/awt/image/MultiResolutionImageTest.java
test/java/awt/image/MultiResolutionImageTest.java
+620
-0
未找到文件。
src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java
浏览文件 @
0be06f1c
...
...
@@ -35,14 +35,17 @@ import java.awt.event.KeyEvent;
import
java.awt.im.InputMethodHighlight
;
import
java.awt.peer.*
;
import
java.lang.reflect.*
;
import
java.net.URL
;
import
java.security.*
;
import
java.util.*
;
import
java.util.concurrent.Callable
;
import
java.net.MalformedURLException
;
import
sun.awt.*
;
import
sun.lwawt.*
;
import
sun.lwawt.LWWindowPeer.PeerType
;
import
sun.security.action.GetBooleanAction
;
import
sun.awt.image.MultiResolutionImage
;
import
sun.util.CoreResourceBundleControl
;
...
...
@@ -489,9 +492,30 @@ public final class LWCToolkit extends LWToolkit {
@Override
public
Image
getImage
(
final
String
filename
)
{
final
Image
nsImage
=
checkForNSImage
(
filename
);
if
(
nsImage
!=
null
)
return
nsImage
;
if
(
nsImage
!=
null
)
{
return
nsImage
;
}
if
(
imageCached
(
filename
))
{
return
super
.
getImage
(
filename
);
}
return
super
.
getImage
(
filename
);
String
fileneame2x
=
getScaledImageName
(
filename
);
return
(
imageExists
(
fileneame2x
))
?
getImageWithResolutionVariant
(
filename
,
fileneame2x
)
:
super
.
getImage
(
filename
);
}
@Override
public
Image
getImage
(
URL
url
)
{
if
(
imageCached
(
url
))
{
return
super
.
getImage
(
url
);
}
URL
url2x
=
getScaledImageURL
(
url
);
return
(
imageExists
(
url2x
))
?
getImageWithResolutionVariant
(
url
,
url2x
)
:
super
.
getImage
(
url
);
}
static
final
String
nsImagePrefix
=
"NSImage://"
;
...
...
@@ -781,4 +805,36 @@ public final class LWCToolkit extends LWToolkit {
public
boolean
enableInputMethodsForTextComponent
()
{
return
true
;
}
private
static
URL
getScaledImageURL
(
URL
url
)
{
try
{
String
scaledImagePath
=
getScaledImageName
(
url
.
getPath
());
return
scaledImagePath
==
null
?
null
:
new
URL
(
url
.
getProtocol
(),
url
.
getHost
(),
url
.
getPort
(),
scaledImagePath
);
}
catch
(
MalformedURLException
e
)
{
return
null
;
}
}
private
static
String
getScaledImageName
(
String
path
)
{
if
(!
isValidPath
(
path
))
{
return
null
;
}
int
slash
=
path
.
lastIndexOf
(
'/'
);
String
name
=
(
slash
<
0
)
?
path
:
path
.
substring
(
slash
+
1
);
if
(
name
.
contains
(
"@2x"
))
{
return
null
;
}
int
dot
=
name
.
lastIndexOf
(
'.'
);
String
name2x
=
(
dot
<
0
)
?
name
+
"@2x"
:
name
.
substring
(
0
,
dot
)
+
"@2x"
+
name
.
substring
(
dot
);
return
(
slash
<
0
)
?
name2x
:
path
.
substring
(
0
,
slash
+
1
)
+
name2x
;
}
private
static
boolean
isValidPath
(
String
path
)
{
return
!
path
.
isEmpty
()
&&
!
path
.
endsWith
(
"/"
)
&&
!
path
.
endsWith
(
"."
);
}
}
src/share/classes/java/awt/MediaTracker.java
浏览文件 @
0be06f1c
...
...
@@ -28,6 +28,7 @@ package java.awt;
import
java.awt.Component
;
import
java.awt.Image
;
import
java.awt.image.ImageObserver
;
import
sun.awt.image.MultiResolutionToolkitImage
;
/**
* The <code>MediaTracker</code> class is a utility class to track
...
...
@@ -222,10 +223,17 @@ public class MediaTracker implements java.io.Serializable {
* @param h the height at which the image is rendered
*/
public
synchronized
void
addImage
(
Image
image
,
int
id
,
int
w
,
int
h
)
{
addImageImpl
(
image
,
id
,
w
,
h
);
Image
rvImage
=
getResolutionVariant
(
image
);
if
(
rvImage
!=
null
)
{
addImageImpl
(
rvImage
,
id
,
2
*
w
,
2
*
h
);
}
}
private
void
addImageImpl
(
Image
image
,
int
id
,
int
w
,
int
h
)
{
head
=
MediaEntry
.
insert
(
head
,
new
ImageMediaEntry
(
this
,
image
,
id
,
w
,
h
));
}
/**
* Flag indicating that media is currently being loaded.
* @see java.awt.MediaTracker#statusAll
...
...
@@ -719,6 +727,15 @@ public class MediaTracker implements java.io.Serializable {
* @since JDK1.1
*/
public
synchronized
void
removeImage
(
Image
image
)
{
removeImageImpl
(
image
);
Image
rvImage
=
getResolutionVariant
(
image
);
if
(
rvImage
!=
null
)
{
removeImageImpl
(
rvImage
);
}
notifyAll
();
// Notify in case remaining images are "done".
}
private
void
removeImageImpl
(
Image
image
)
{
MediaEntry
cur
=
head
;
MediaEntry
prev
=
null
;
while
(
cur
!=
null
)
{
...
...
@@ -735,7 +752,6 @@ public class MediaTracker implements java.io.Serializable {
}
cur
=
next
;
}
notifyAll
();
// Notify in case remaining images are "done".
}
/**
...
...
@@ -750,6 +766,15 @@ public class MediaTracker implements java.io.Serializable {
* @since JDK1.1
*/
public
synchronized
void
removeImage
(
Image
image
,
int
id
)
{
removeImageImpl
(
image
,
id
);
Image
rvImage
=
getResolutionVariant
(
image
);
if
(
rvImage
!=
null
)
{
removeImageImpl
(
rvImage
,
id
);
}
notifyAll
();
// Notify in case remaining images are "done".
}
private
void
removeImageImpl
(
Image
image
,
int
id
)
{
MediaEntry
cur
=
head
;
MediaEntry
prev
=
null
;
while
(
cur
!=
null
)
{
...
...
@@ -766,7 +791,6 @@ public class MediaTracker implements java.io.Serializable {
}
cur
=
next
;
}
notifyAll
();
// Notify in case remaining images are "done".
}
/**
...
...
@@ -783,6 +807,16 @@ public class MediaTracker implements java.io.Serializable {
*/
public
synchronized
void
removeImage
(
Image
image
,
int
id
,
int
width
,
int
height
)
{
removeImageImpl
(
image
,
id
,
width
,
height
);
Image
rvImage
=
getResolutionVariant
(
image
);
if
(
rvImage
!=
null
)
{
removeImageImpl
(
rvImage
,
id
,
2
*
width
,
2
*
height
);
}
notifyAll
();
// Notify in case remaining images are "done".
}
private
void
removeImageImpl
(
Image
image
,
int
id
,
int
width
,
int
height
)
{
MediaEntry
cur
=
head
;
MediaEntry
prev
=
null
;
while
(
cur
!=
null
)
{
...
...
@@ -801,12 +835,18 @@ public class MediaTracker implements java.io.Serializable {
}
cur
=
next
;
}
notifyAll
();
// Notify in case remaining images are "done".
}
synchronized
void
setDone
()
{
notifyAll
();
}
private
static
Image
getResolutionVariant
(
Image
image
)
{
if
(
image
instanceof
MultiResolutionToolkitImage
)
{
return
((
MultiResolutionToolkitImage
)
image
).
getResolutionVariant
();
}
return
null
;
}
}
abstract
class
MediaEntry
{
...
...
src/share/classes/sun/awt/SunHints.java
浏览文件 @
0be06f1c
...
...
@@ -172,7 +172,7 @@ public class SunHints {
}
}
private
static
final
int
NUM_KEYS
=
9
;
private
static
final
int
NUM_KEYS
=
10
;
private
static
final
int
VALS_PER_KEY
=
8
;
/**
...
...
@@ -252,6 +252,13 @@ public class SunHints {
@Native
public
static
final
int
INTVAL_STROKE_NORMALIZE
=
1
;
@Native
public
static
final
int
INTVAL_STROKE_PURE
=
2
;
/**
* Image scaling hint key and values
*/
@Native
public
static
final
int
INTKEY_RESOLUTION_VARIANT
=
9
;
@Native
public
static
final
int
INTVAL_RESOLUTION_VARIANT_DEFAULT
=
0
;
@Native
public
static
final
int
INTVAL_RESOLUTION_VARIANT_OFF
=
1
;
@Native
public
static
final
int
INTVAL_RESOLUTION_VARIANT_ON
=
2
;
/**
* LCD text contrast control hint key.
* Value is "100" to make discontiguous with the others which
...
...
@@ -450,6 +457,24 @@ public class SunHints {
SunHints
.
INTVAL_STROKE_PURE
,
"Pure stroke conversion for accurate paths"
);
/**
* Image resolution variant hint key and value objects
*/
public
static
final
Key
KEY_RESOLUTION_VARIANT
=
new
SunHints
.
Key
(
SunHints
.
INTKEY_RESOLUTION_VARIANT
,
"Global image resolution variant key"
);
public
static
final
Object
VALUE_RESOLUTION_VARIANT_DEFAULT
=
new
SunHints
.
Value
(
KEY_RESOLUTION_VARIANT
,
SunHints
.
INTVAL_RESOLUTION_VARIANT_DEFAULT
,
"Choose image resolutions based on a default heuristic"
);
public
static
final
Object
VALUE_RESOLUTION_VARIANT_OFF
=
new
SunHints
.
Value
(
KEY_RESOLUTION_VARIANT
,
SunHints
.
INTVAL_RESOLUTION_VARIANT_OFF
,
"Use only the standard resolution of an image"
);
public
static
final
Object
VALUE_RESOLUTION_VARIANT_ON
=
new
SunHints
.
Value
(
KEY_RESOLUTION_VARIANT
,
SunHints
.
INTVAL_RESOLUTION_VARIANT_ON
,
"Always use resolution-specific variants of images"
);
public
static
class
LCDContrastKey
extends
Key
{
...
...
src/share/classes/sun/awt/SunToolkit.java
浏览文件 @
0be06f1c
...
...
@@ -36,6 +36,9 @@ import java.awt.image.*;
import
java.awt.TrayIcon
;
import
java.awt.SystemTray
;
import
java.awt.event.InputEvent
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.net.URL
;
import
java.util.*
;
import
java.util.concurrent.TimeUnit
;
...
...
@@ -715,33 +718,7 @@ public abstract class SunToolkit extends Toolkit
static
final
SoftCache
imgCache
=
new
SoftCache
();
static
Image
getImageFromHash
(
Toolkit
tk
,
URL
url
)
{
SecurityManager
sm
=
System
.
getSecurityManager
();
if
(
sm
!=
null
)
{
try
{
java
.
security
.
Permission
perm
=
url
.
openConnection
().
getPermission
();
if
(
perm
!=
null
)
{
try
{
sm
.
checkPermission
(
perm
);
}
catch
(
SecurityException
se
)
{
// fallback to checkRead/checkConnect for pre 1.2
// security managers
if
((
perm
instanceof
java
.
io
.
FilePermission
)
&&
perm
.
getActions
().
indexOf
(
"read"
)
!=
-
1
)
{
sm
.
checkRead
(
perm
.
getName
());
}
else
if
((
perm
instanceof
java
.
net
.
SocketPermission
)
&&
perm
.
getActions
().
indexOf
(
"connect"
)
!=
-
1
)
{
sm
.
checkConnect
(
url
.
getHost
(),
url
.
getPort
());
}
else
{
throw
se
;
}
}
}
}
catch
(
java
.
io
.
IOException
ioe
)
{
sm
.
checkConnect
(
url
.
getHost
(),
url
.
getPort
());
}
}
checkPermissions
(
url
);
synchronized
(
imgCache
)
{
Image
img
=
(
Image
)
imgCache
.
get
(
url
);
if
(
img
==
null
)
{
...
...
@@ -757,10 +734,7 @@ public abstract class SunToolkit extends Toolkit
static
Image
getImageFromHash
(
Toolkit
tk
,
String
filename
)
{
SecurityManager
security
=
System
.
getSecurityManager
();
if
(
security
!=
null
)
{
security
.
checkRead
(
filename
);
}
checkPermissions
(
filename
);
synchronized
(
imgCache
)
{
Image
img
=
(
Image
)
imgCache
.
get
(
filename
);
if
(
img
==
null
)
{
...
...
@@ -782,42 +756,42 @@ public abstract class SunToolkit extends Toolkit
return
getImageFromHash
(
this
,
url
);
}
public
Image
createImage
(
String
filename
)
{
SecurityManager
security
=
System
.
getSecurityManager
();
if
(
security
!=
null
)
{
security
.
checkRead
(
filename
);
protected
Image
getImageWithResolutionVariant
(
String
fileName
,
String
resolutionVariantName
)
{
synchronized
(
imgCache
)
{
Image
image
=
getImageFromHash
(
this
,
fileName
);
if
(
image
instanceof
MultiResolutionImage
)
{
return
image
;
}
Image
resolutionVariant
=
getImageFromHash
(
this
,
resolutionVariantName
);
image
=
createImageWithResolutionVariant
(
image
,
resolutionVariant
);
imgCache
.
put
(
fileName
,
image
);
return
image
;
}
return
createImage
(
new
FileImageSource
(
filename
));
}
public
Image
createImage
(
URL
url
)
{
SecurityManager
sm
=
System
.
getSecurityManager
();
if
(
sm
!=
null
)
{
try
{
java
.
security
.
Permission
perm
=
url
.
openConnection
().
getPermission
();
if
(
perm
!=
null
)
{
try
{
sm
.
checkPermission
(
perm
);
}
catch
(
SecurityException
se
)
{
// fallback to checkRead/checkConnect for pre 1.2
// security managers
if
((
perm
instanceof
java
.
io
.
FilePermission
)
&&
perm
.
getActions
().
indexOf
(
"read"
)
!=
-
1
)
{
sm
.
checkRead
(
perm
.
getName
());
}
else
if
((
perm
instanceof
java
.
net
.
SocketPermission
)
&&
perm
.
getActions
().
indexOf
(
"connect"
)
!=
-
1
)
{
sm
.
checkConnect
(
url
.
getHost
(),
url
.
getPort
());
}
else
{
throw
se
;
}
}
}
}
catch
(
java
.
io
.
IOException
ioe
)
{
sm
.
checkConnect
(
url
.
getHost
(),
url
.
getPort
());
protected
Image
getImageWithResolutionVariant
(
URL
url
,
URL
resolutionVariantURL
)
{
synchronized
(
imgCache
)
{
Image
image
=
getImageFromHash
(
this
,
url
);
if
(
image
instanceof
MultiResolutionImage
)
{
return
image
;
}
Image
resolutionVariant
=
getImageFromHash
(
this
,
resolutionVariantURL
);
image
=
createImageWithResolutionVariant
(
image
,
resolutionVariant
);
imgCache
.
put
(
url
,
image
);
return
image
;
}
}
public
Image
createImage
(
String
filename
)
{
checkPermissions
(
filename
);
return
createImage
(
new
FileImageSource
(
filename
));
}
public
Image
createImage
(
URL
url
)
{
checkPermissions
(
url
);
return
createImage
(
new
URLImageSource
(
url
));
}
...
...
@@ -829,6 +803,11 @@ public abstract class SunToolkit extends Toolkit
return
new
ToolkitImage
(
producer
);
}
public
static
Image
createImageWithResolutionVariant
(
Image
image
,
Image
resolutionVariant
)
{
return
new
MultiResolutionToolkitImage
(
image
,
resolutionVariant
);
}
public
int
checkImage
(
Image
img
,
int
w
,
int
h
,
ImageObserver
o
)
{
if
(!(
img
instanceof
ToolkitImage
))
{
return
ImageObserver
.
ALLBITS
;
...
...
@@ -841,7 +820,7 @@ public abstract class SunToolkit extends Toolkit
}
else
{
repbits
=
tkimg
.
getImageRep
().
check
(
o
);
}
return
tkimg
.
check
(
o
)
|
repbits
;
return
(
tkimg
.
check
(
o
)
|
repbits
)
&
checkResolutionVariant
(
img
,
w
,
h
,
o
)
;
}
public
boolean
prepareImage
(
Image
img
,
int
w
,
int
h
,
ImageObserver
o
)
{
...
...
@@ -863,7 +842,97 @@ public abstract class SunToolkit extends Toolkit
return
false
;
}
ImageRepresentation
ir
=
tkimg
.
getImageRep
();
return
ir
.
prepare
(
o
);
return
ir
.
prepare
(
o
)
&
prepareResolutionVariant
(
img
,
w
,
h
,
o
);
}
private
int
checkResolutionVariant
(
Image
img
,
int
w
,
int
h
,
ImageObserver
o
)
{
ToolkitImage
rvImage
=
getResolutionVariant
(
img
);
// Ignore the resolution variant in case of error
return
(
rvImage
==
null
||
rvImage
.
hasError
())
?
0xFFFF
:
checkImage
(
rvImage
,
2
*
w
,
2
*
h
,
MultiResolutionToolkitImage
.
getResolutionVariantObserver
(
img
,
o
,
w
,
h
,
2
*
w
,
2
*
h
));
}
private
boolean
prepareResolutionVariant
(
Image
img
,
int
w
,
int
h
,
ImageObserver
o
)
{
ToolkitImage
rvImage
=
getResolutionVariant
(
img
);
// Ignore the resolution variant in case of error
return
rvImage
==
null
||
rvImage
.
hasError
()
||
prepareImage
(
rvImage
,
2
*
w
,
2
*
h
,
MultiResolutionToolkitImage
.
getResolutionVariantObserver
(
img
,
o
,
w
,
h
,
2
*
w
,
2
*
h
));
}
private
static
ToolkitImage
getResolutionVariant
(
Image
image
)
{
if
(
image
instanceof
MultiResolutionToolkitImage
)
{
Image
resolutionVariant
=
((
MultiResolutionToolkitImage
)
image
).
getResolutionVariant
();
if
(
resolutionVariant
instanceof
ToolkitImage
)
{
return
(
ToolkitImage
)
resolutionVariant
;
}
}
return
null
;
}
protected
static
boolean
imageCached
(
Object
key
)
{
return
imgCache
.
containsKey
(
key
);
}
protected
static
boolean
imageExists
(
String
filename
)
{
checkPermissions
(
filename
);
return
filename
!=
null
&&
new
File
(
filename
).
exists
();
}
@SuppressWarnings
(
"try"
)
protected
static
boolean
imageExists
(
URL
url
)
{
checkPermissions
(
url
);
if
(
url
!=
null
)
{
try
(
InputStream
is
=
url
.
openStream
())
{
return
true
;
}
catch
(
IOException
e
){
return
false
;
}
}
return
false
;
}
private
static
void
checkPermissions
(
String
filename
)
{
SecurityManager
security
=
System
.
getSecurityManager
();
if
(
security
!=
null
)
{
security
.
checkRead
(
filename
);
}
}
private
static
void
checkPermissions
(
URL
url
)
{
SecurityManager
sm
=
System
.
getSecurityManager
();
if
(
sm
!=
null
)
{
try
{
java
.
security
.
Permission
perm
=
url
.
openConnection
().
getPermission
();
if
(
perm
!=
null
)
{
try
{
sm
.
checkPermission
(
perm
);
}
catch
(
SecurityException
se
)
{
// fallback to checkRead/checkConnect for pre 1.2
// security managers
if
((
perm
instanceof
java
.
io
.
FilePermission
)
&&
perm
.
getActions
().
indexOf
(
"read"
)
!=
-
1
)
{
sm
.
checkRead
(
perm
.
getName
());
}
else
if
((
perm
instanceof
java
.
net
.
SocketPermission
)
&&
perm
.
getActions
().
indexOf
(
"connect"
)
!=
-
1
)
{
sm
.
checkConnect
(
url
.
getHost
(),
url
.
getPort
());
}
else
{
throw
se
;
}
}
}
}
catch
(
java
.
io
.
IOException
ioe
)
{
sm
.
checkConnect
(
url
.
getHost
(),
url
.
getPort
());
}
}
}
/**
...
...
src/share/classes/sun/awt/image/MultiResolutionImage.java
0 → 100644
浏览文件 @
0be06f1c
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package
sun.awt.image
;
import
java.awt.Image
;
import
java.util.List
;
/**
* This interface is designed to provide a set of images at various resolutions.
*
* The <code>MultiResolutionImage</code> interface should be implemented by any
* class whose instances are intended to provide image resolution variants
* according to the given image width and height.
*
* For example,
* <pre>
* {@code
* public class ScaledImage extends BufferedImage
* implements MultiResolutionImage {
*
* @Override
* public Image getResolutionVariant(int width, int height) {
* return ((width <= getWidth() && height <= getHeight()))
* ? this : highResolutionImage;
* }
*
* @Override
* public List<Image> getResolutionVariants() {
* return Arrays.asList(this, highResolutionImage);
* }
* }
* }</pre>
*
* It is recommended to cache image variants for performance reasons.
*
* <b>WARNING</b>: This class is an implementation detail. This API may change
* between update release, and it may even be removed or be moved in some other
* package(s)/class(es).
*/
public
interface
MultiResolutionImage
{
/**
* Provides an image with necessary resolution which best fits to the given
* image width and height.
*
* @param width the desired image resolution width.
* @param height the desired image resolution height.
* @return image resolution variant.
*
* @since JDK1.8
*/
public
Image
getResolutionVariant
(
int
width
,
int
height
);
/**
* Gets list of all resolution variants including the base image
*
* @return list of resolution variants.
* @since JDK1.8
*/
public
List
<
Image
>
getResolutionVariants
();
}
src/share/classes/sun/awt/image/MultiResolutionToolkitImage.java
0 → 100644
浏览文件 @
0be06f1c
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package
sun.awt.image
;
import
java.awt.Image
;
import
java.awt.image.ImageObserver
;
import
java.util.Arrays
;
import
java.util.List
;
import
sun.misc.SoftCache
;
public
class
MultiResolutionToolkitImage
extends
ToolkitImage
implements
MultiResolutionImage
{
Image
resolutionVariant
;
public
MultiResolutionToolkitImage
(
Image
lowResolutionImage
,
Image
resolutionVariant
)
{
super
(
lowResolutionImage
.
getSource
());
this
.
resolutionVariant
=
resolutionVariant
;
}
@Override
public
Image
getResolutionVariant
(
int
width
,
int
height
)
{
return
((
width
<=
getWidth
()
&&
height
<=
getHeight
()))
?
this
:
resolutionVariant
;
}
public
Image
getResolutionVariant
()
{
return
resolutionVariant
;
}
@Override
public
List
<
Image
>
getResolutionVariants
()
{
return
Arrays
.<
Image
>
asList
(
this
,
resolutionVariant
);
}
private
static
final
int
BITS_INFO
=
ImageObserver
.
SOMEBITS
|
ImageObserver
.
FRAMEBITS
|
ImageObserver
.
ALLBITS
;
private
static
class
ObserverCache
{
static
final
SoftCache
INSTANCE
=
new
SoftCache
();
}
public
static
ImageObserver
getResolutionVariantObserver
(
final
Image
image
,
final
ImageObserver
observer
,
final
int
imgWidth
,
final
int
imgHeight
,
final
int
rvWidth
,
final
int
rvHeight
)
{
if
(
observer
==
null
)
{
return
null
;
}
synchronized
(
ObserverCache
.
INSTANCE
)
{
ImageObserver
o
=
(
ImageObserver
)
ObserverCache
.
INSTANCE
.
get
(
image
);
if
(
o
==
null
)
{
o
=
(
Image
resolutionVariant
,
int
flags
,
int
x
,
int
y
,
int
width
,
int
height
)
->
{
if
((
flags
&
(
ImageObserver
.
WIDTH
|
BITS_INFO
))
!=
0
)
{
width
=
(
width
+
1
)
/
2
;
}
if
((
flags
&
(
ImageObserver
.
HEIGHT
|
BITS_INFO
))
!=
0
)
{
height
=
(
height
+
1
)
/
2
;
}
if
((
flags
&
BITS_INFO
)
!=
0
)
{
x
/=
2
;
y
/=
2
;
}
return
observer
.
imageUpdate
(
image
,
flags
,
x
,
y
,
width
,
height
);
};
ObserverCache
.
INSTANCE
.
put
(
image
,
o
);
}
return
o
;
}
}
}
src/share/classes/sun/java2d/SunGraphics2D.java
浏览文件 @
0be06f1c
...
...
@@ -61,6 +61,7 @@ import java.awt.FontMetrics;
import
java.awt.Rectangle
;
import
java.text.AttributedCharacterIterator
;
import
java.awt.Font
;
import
java.awt.Point
;
import
java.awt.image.ImageObserver
;
import
java.awt.Transparency
;
import
java.awt.font.GlyphVector
;
...
...
@@ -93,6 +94,13 @@ import java.util.Iterator;
import
sun.misc.PerformanceLogger
;
import
java.lang.annotation.Native
;
import
sun.awt.image.MultiResolutionImage
;
import
static
java
.
awt
.
geom
.
AffineTransform
.
TYPE_FLIP
;
import
static
java
.
awt
.
geom
.
AffineTransform
.
TYPE_MASK_SCALE
;
import
static
java
.
awt
.
geom
.
AffineTransform
.
TYPE_TRANSLATION
;
import
sun.awt.image.MultiResolutionToolkitImage
;
import
sun.awt.image.ToolkitImage
;
/**
* This is a the master Graphics2D superclass for all of the Sun
...
...
@@ -237,6 +245,7 @@ public final class SunGraphics2D
protected
Region
devClip
;
// Actual physical drawable in pixels
private
final
int
devScale
;
// Actual physical scale factor
private
int
resolutionVariantHint
;
// cached state for text rendering
private
boolean
validFontInfo
;
...
...
@@ -274,6 +283,7 @@ public final class SunGraphics2D
lcdTextContrast
=
lcdTextContrastDefaultValue
;
interpolationHint
=
-
1
;
strokeHint
=
SunHints
.
INTVAL_STROKE_DEFAULT
;
resolutionVariantHint
=
SunHints
.
INTVAL_RESOLUTION_VARIANT_DEFAULT
;
interpolationType
=
AffineTransformOp
.
TYPE_NEAREST_NEIGHBOR
;
...
...
@@ -1249,6 +1259,10 @@ public final class SunGraphics2D
stateChanged
=
(
strokeHint
!=
newHint
);
strokeHint
=
newHint
;
break
;
case
SunHints
.
INTKEY_RESOLUTION_VARIANT
:
stateChanged
=
(
resolutionVariantHint
!=
newHint
);
resolutionVariantHint
=
newHint
;
break
;
default
:
recognized
=
false
;
stateChanged
=
false
;
...
...
@@ -1322,6 +1336,9 @@ public final class SunGraphics2D
case
SunHints
.
INTKEY_STROKE_CONTROL
:
return
SunHints
.
Value
.
get
(
SunHints
.
INTKEY_STROKE_CONTROL
,
strokeHint
);
case
SunHints
.
INTKEY_RESOLUTION_VARIANT
:
return
SunHints
.
Value
.
get
(
SunHints
.
INTKEY_RESOLUTION_VARIANT
,
resolutionVariantHint
);
}
return
null
;
}
...
...
@@ -3050,18 +3067,58 @@ public final class SunGraphics2D
}
// end of text rendering methods
private
static
boolean
isHiDPIImage
(
final
Image
img
)
{
return
SurfaceManager
.
getImageScale
(
img
)
!=
1
;
private
boolean
isHiDPIImage
(
final
Image
img
)
{
return
(
SurfaceManager
.
getImageScale
(
img
)
!=
1
)
||
(
resolutionVariantHint
!=
SunHints
.
INTVAL_RESOLUTION_VARIANT_OFF
&&
img
instanceof
MultiResolutionImage
);
}
private
boolean
drawHiDPIImage
(
Image
img
,
int
dx1
,
int
dy1
,
int
dx2
,
int
dy2
,
int
sx1
,
int
sy1
,
int
sx2
,
int
sy2
,
Color
bgcolor
,
ImageObserver
observer
)
{
final
int
scale
=
SurfaceManager
.
getImageScale
(
img
);
sx1
=
Region
.
clipScale
(
sx1
,
scale
);
sx2
=
Region
.
clipScale
(
sx2
,
scale
);
sy1
=
Region
.
clipScale
(
sy1
,
scale
);
sy2
=
Region
.
clipScale
(
sy2
,
scale
);
if
(
SurfaceManager
.
getImageScale
(
img
)
!=
1
)
{
// Volatile Image
final
int
scale
=
SurfaceManager
.
getImageScale
(
img
);
sx1
=
Region
.
clipScale
(
sx1
,
scale
);
sx2
=
Region
.
clipScale
(
sx2
,
scale
);
sy1
=
Region
.
clipScale
(
sy1
,
scale
);
sy2
=
Region
.
clipScale
(
sy2
,
scale
);
}
else
if
(
img
instanceof
MultiResolutionImage
)
{
// get scaled destination image size
int
width
=
img
.
getWidth
(
observer
);
int
height
=
img
.
getHeight
(
observer
);
Image
resolutionVariant
=
getResolutionVariant
(
(
MultiResolutionImage
)
img
,
width
,
height
,
dx1
,
dy1
,
dx2
,
dy2
,
sx1
,
sy1
,
sx2
,
sy2
);
if
(
resolutionVariant
!=
img
&&
resolutionVariant
!=
null
)
{
// recalculate source region for the resolution variant
ImageObserver
rvObserver
=
MultiResolutionToolkitImage
.
getResolutionVariantObserver
(
img
,
observer
,
width
,
height
,
-
1
,
-
1
);
int
rvWidth
=
resolutionVariant
.
getWidth
(
rvObserver
);
int
rvHeight
=
resolutionVariant
.
getHeight
(
rvObserver
);
if
(
0
<
width
&&
0
<
height
&&
0
<
rvWidth
&&
0
<
rvHeight
)
{
float
widthScale
=
((
float
)
rvWidth
)
/
width
;
float
heightScale
=
((
float
)
rvHeight
)
/
height
;
sx1
=
Region
.
clipScale
(
sx1
,
widthScale
);
sy1
=
Region
.
clipScale
(
sy1
,
heightScale
);
sx2
=
Region
.
clipScale
(
sx2
,
widthScale
);
sy2
=
Region
.
clipScale
(
sy2
,
heightScale
);
observer
=
rvObserver
;
img
=
resolutionVariant
;
}
}
}
try
{
return
imagepipe
.
scaleImage
(
this
,
img
,
dx1
,
dy1
,
dx2
,
dy2
,
sx1
,
sy1
,
sx2
,
sy2
,
bgcolor
,
observer
);
...
...
@@ -3081,6 +3138,54 @@ public final class SunGraphics2D
}
}
private
Image
getResolutionVariant
(
MultiResolutionImage
img
,
int
srcWidth
,
int
srcHeight
,
int
dx1
,
int
dy1
,
int
dx2
,
int
dy2
,
int
sx1
,
int
sy1
,
int
sx2
,
int
sy2
)
{
if
(
srcWidth
<=
0
||
srcHeight
<=
0
)
{
return
null
;
}
int
sw
=
sx2
-
sx1
;
int
sh
=
sy2
-
sy1
;
if
(
sw
==
0
||
sh
==
0
)
{
return
null
;
}
int
type
=
transform
.
getType
();
int
dw
=
dx2
-
dx1
;
int
dh
=
dy2
-
dy1
;
double
destRegionWidth
;
double
destRegionHeight
;
if
((
type
&
~(
TYPE_TRANSLATION
|
TYPE_FLIP
))
==
0
)
{
destRegionWidth
=
dw
;
destRegionHeight
=
dh
;
}
else
if
((
type
&
~(
TYPE_TRANSLATION
|
TYPE_FLIP
|
TYPE_MASK_SCALE
))
==
0
)
{
destRegionWidth
=
dw
*
transform
.
getScaleX
();
destRegionHeight
=
dh
*
transform
.
getScaleY
();
}
else
{
destRegionWidth
=
dw
*
Math
.
hypot
(
transform
.
getScaleX
(),
transform
.
getShearY
());
destRegionHeight
=
dh
*
Math
.
hypot
(
transform
.
getShearX
(),
transform
.
getScaleY
());
}
int
destImageWidth
=
(
int
)
Math
.
abs
(
srcWidth
*
destRegionWidth
/
sw
);
int
destImageHeight
=
(
int
)
Math
.
abs
(
srcHeight
*
destRegionHeight
/
sh
);
Image
resolutionVariant
=
img
.
getResolutionVariant
(
destImageWidth
,
destImageHeight
);
if
(
resolutionVariant
instanceof
ToolkitImage
&&
((
ToolkitImage
)
resolutionVariant
).
hasError
())
{
return
null
;
}
return
resolutionVariant
;
}
/**
* Draws an image scaled to x,y,w,h in nonblocking mode with a
* callback object.
...
...
test/java/awt/image/MultiResolutionImageTest.java
0 → 100644
浏览文件 @
0be06f1c
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import
java.awt.Color
;
import
java.awt.Graphics
;
import
java.awt.Graphics2D
;
import
java.awt.Image
;
import
java.awt.Toolkit
;
import
java.awt.image.BufferedImage
;
import
java.io.File
;
import
java.lang.reflect.Method
;
import
java.net.URL
;
import
javax.imageio.ImageIO
;
import
sun.awt.OSInfo
;
import
sun.awt.SunHints
;
import
java.awt.MediaTracker
;
import
java.awt.geom.AffineTransform
;
import
java.awt.image.ImageObserver
;
import
java.util.Arrays
;
import
java.util.List
;
import
javax.swing.JPanel
;
import
sun.awt.SunToolkit
;
import
sun.awt.image.MultiResolutionImage
;
/**
* @test
* @bug 8011059
* @author Alexander Scherbatiy
* @summary [macosx] Make JDK demos look perfect on retina displays
* @run main MultiResolutionImageTest CUSTOM
* @run main MultiResolutionImageTest TOOLKIT_PREPARE
* @run main MultiResolutionImageTest TOOLKIT_LOAD
* @run main MultiResolutionImageTest TOOLKIT
*/
public
class
MultiResolutionImageTest
{
private
static
final
int
IMAGE_WIDTH
=
300
;
private
static
final
int
IMAGE_HEIGHT
=
200
;
private
static
final
Color
COLOR_1X
=
Color
.
GREEN
;
private
static
final
Color
COLOR_2X
=
Color
.
BLUE
;
private
static
final
String
IMAGE_NAME_1X
=
"image.png"
;
private
static
final
String
IMAGE_NAME_2X
=
"image@2x.png"
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
System
.
out
.
println
(
"args: "
+
args
.
length
);
if
(
args
.
length
==
0
)
{
throw
new
RuntimeException
(
"Not found a test"
);
}
String
test
=
args
[
0
];
System
.
out
.
println
(
"TEST: "
+
test
);
System
.
out
.
println
(
"CHECK OS: "
+
checkOS
());
if
(
"CUSTOM"
.
equals
(
test
))
{
testCustomMultiResolutionImage
();
}
else
if
(
checkOS
())
{
switch
(
test
)
{
case
"CUSTOM"
:
break
;
case
"TOOLKIT_PREPARE"
:
testToolkitMultiResolutionImagePrepare
();
break
;
case
"TOOLKIT_LOAD"
:
testToolkitMultiResolutionImageLoad
();
break
;
case
"TOOLKIT"
:
testToolkitMultiResolutionImage
();
testImageNameTo2xParsing
();
break
;
default
:
throw
new
RuntimeException
(
"Unknown test: "
+
test
);
}
}
}
static
boolean
checkOS
()
{
return
OSInfo
.
getOSType
()
==
OSInfo
.
OSType
.
MACOSX
;
}
public
static
void
testCustomMultiResolutionImage
()
{
testCustomMultiResolutionImage
(
false
);
testCustomMultiResolutionImage
(
true
);
}
public
static
void
testCustomMultiResolutionImage
(
boolean
enableImageScaling
)
{
Image
image
=
new
MultiResolutionBufferedImage
();
// Same image size
BufferedImage
bufferedImage
=
new
BufferedImage
(
IMAGE_WIDTH
,
IMAGE_HEIGHT
,
BufferedImage
.
TYPE_INT_RGB
);
Graphics2D
g2d
=
(
Graphics2D
)
bufferedImage
.
getGraphics
();
setImageScalingHint
(
g2d
,
enableImageScaling
);
g2d
.
drawImage
(
image
,
0
,
0
,
null
);
checkColor
(
bufferedImage
.
getRGB
(
3
*
IMAGE_WIDTH
/
4
,
3
*
IMAGE_HEIGHT
/
4
),
false
);
// Twice image size
bufferedImage
=
new
BufferedImage
(
2
*
IMAGE_WIDTH
,
2
*
IMAGE_HEIGHT
,
BufferedImage
.
TYPE_INT_RGB
);
g2d
=
(
Graphics2D
)
bufferedImage
.
getGraphics
();
setImageScalingHint
(
g2d
,
enableImageScaling
);
g2d
.
drawImage
(
image
,
0
,
0
,
2
*
IMAGE_WIDTH
,
2
*
IMAGE_HEIGHT
,
0
,
0
,
IMAGE_WIDTH
,
IMAGE_HEIGHT
,
null
);
checkColor
(
bufferedImage
.
getRGB
(
3
*
IMAGE_WIDTH
/
2
,
3
*
IMAGE_HEIGHT
/
2
),
enableImageScaling
);
// Scale 2x
bufferedImage
=
new
BufferedImage
(
2
*
IMAGE_WIDTH
,
2
*
IMAGE_HEIGHT
,
BufferedImage
.
TYPE_INT_RGB
);
g2d
=
(
Graphics2D
)
bufferedImage
.
getGraphics
();
setImageScalingHint
(
g2d
,
enableImageScaling
);
g2d
.
scale
(
2
,
2
);
g2d
.
drawImage
(
image
,
0
,
0
,
IMAGE_WIDTH
,
IMAGE_HEIGHT
,
null
);
checkColor
(
bufferedImage
.
getRGB
(
3
*
IMAGE_WIDTH
/
2
,
3
*
IMAGE_HEIGHT
/
2
),
enableImageScaling
);
// Rotate
bufferedImage
=
new
BufferedImage
(
IMAGE_WIDTH
,
IMAGE_HEIGHT
,
BufferedImage
.
TYPE_INT_RGB
);
g2d
=
(
Graphics2D
)
bufferedImage
.
getGraphics
();
setImageScalingHint
(
g2d
,
enableImageScaling
);
g2d
.
drawImage
(
image
,
0
,
0
,
null
);
g2d
.
rotate
(
Math
.
PI
/
4
);
checkColor
(
bufferedImage
.
getRGB
(
3
*
IMAGE_WIDTH
/
4
,
3
*
IMAGE_HEIGHT
/
4
),
false
);
// Scale 2x and Rotate
bufferedImage
=
new
BufferedImage
(
2
*
IMAGE_WIDTH
,
2
*
IMAGE_HEIGHT
,
BufferedImage
.
TYPE_INT_RGB
);
g2d
=
(
Graphics2D
)
bufferedImage
.
getGraphics
();
setImageScalingHint
(
g2d
,
enableImageScaling
);
g2d
.
scale
(-
2
,
2
);
g2d
.
rotate
(-
Math
.
PI
/
10
);
g2d
.
drawImage
(
image
,
-
IMAGE_WIDTH
,
0
,
IMAGE_WIDTH
,
IMAGE_HEIGHT
,
null
);
checkColor
(
bufferedImage
.
getRGB
(
3
*
IMAGE_WIDTH
/
2
,
3
*
IMAGE_HEIGHT
/
2
),
enableImageScaling
);
// General Transform
bufferedImage
=
new
BufferedImage
(
2
*
IMAGE_WIDTH
,
2
*
IMAGE_HEIGHT
,
BufferedImage
.
TYPE_INT_RGB
);
g2d
=
(
Graphics2D
)
bufferedImage
.
getGraphics
();
setImageScalingHint
(
g2d
,
enableImageScaling
);
float
delta
=
0.05f
;
float
cos
=
1
-
delta
*
delta
/
2
;
float
sin
=
1
+
delta
;
AffineTransform
transform
=
new
AffineTransform
(
2
*
cos
,
0.1
,
0.3
,
-
2
*
sin
,
10
,
-
5
);
g2d
.
setTransform
(
transform
);
g2d
.
drawImage
(
image
,
0
,
-
IMAGE_HEIGHT
,
IMAGE_WIDTH
,
IMAGE_HEIGHT
,
null
);
checkColor
(
bufferedImage
.
getRGB
(
3
*
IMAGE_WIDTH
/
2
,
3
*
IMAGE_HEIGHT
/
2
),
enableImageScaling
);
int
D
=
10
;
// From Source to small Destination region
bufferedImage
=
new
BufferedImage
(
IMAGE_WIDTH
,
IMAGE_HEIGHT
,
BufferedImage
.
TYPE_INT_RGB
);
g2d
=
(
Graphics2D
)
bufferedImage
.
getGraphics
();
setImageScalingHint
(
g2d
,
enableImageScaling
);
g2d
.
drawImage
(
image
,
IMAGE_WIDTH
/
2
,
IMAGE_HEIGHT
/
2
,
IMAGE_WIDTH
-
D
,
IMAGE_HEIGHT
-
D
,
D
,
D
,
IMAGE_WIDTH
-
D
,
IMAGE_HEIGHT
-
D
,
null
);
checkColor
(
bufferedImage
.
getRGB
(
3
*
IMAGE_WIDTH
/
4
,
3
*
IMAGE_HEIGHT
/
4
),
false
);
// From Source to large Destination region
bufferedImage
=
new
BufferedImage
(
2
*
IMAGE_WIDTH
,
2
*
IMAGE_HEIGHT
,
BufferedImage
.
TYPE_INT_RGB
);
g2d
=
(
Graphics2D
)
bufferedImage
.
getGraphics
();
setImageScalingHint
(
g2d
,
enableImageScaling
);
g2d
.
drawImage
(
image
,
D
,
D
,
2
*
IMAGE_WIDTH
-
D
,
2
*
IMAGE_HEIGHT
-
D
,
IMAGE_WIDTH
/
2
,
IMAGE_HEIGHT
/
2
,
IMAGE_WIDTH
-
D
,
IMAGE_HEIGHT
-
D
,
null
);
checkColor
(
bufferedImage
.
getRGB
(
3
*
IMAGE_WIDTH
/
2
,
3
*
IMAGE_HEIGHT
/
2
),
enableImageScaling
);
}
static
class
MultiResolutionBufferedImage
extends
BufferedImage
implements
MultiResolutionImage
{
Image
highResolutionImage
;
public
MultiResolutionBufferedImage
()
{
super
(
IMAGE_WIDTH
,
IMAGE_HEIGHT
,
BufferedImage
.
TYPE_INT_RGB
);
highResolutionImage
=
new
BufferedImage
(
2
*
IMAGE_WIDTH
,
2
*
IMAGE_HEIGHT
,
BufferedImage
.
TYPE_INT_RGB
);
draw
(
getGraphics
(),
1
);
draw
(
highResolutionImage
.
getGraphics
(),
2
);
}
void
draw
(
Graphics
graphics
,
float
resolution
)
{
Graphics2D
g2
=
(
Graphics2D
)
graphics
;
g2
.
scale
(
resolution
,
resolution
);
g2
.
setColor
((
resolution
==
1
)
?
COLOR_1X
:
COLOR_2X
);
g2
.
fillRect
(
0
,
0
,
IMAGE_WIDTH
,
IMAGE_HEIGHT
);
}
@Override
public
Image
getResolutionVariant
(
int
width
,
int
height
)
{
return
((
width
<=
getWidth
()
&&
height
<=
getHeight
()))
?
this
:
highResolutionImage
;
}
@Override
public
List
<
Image
>
getResolutionVariants
()
{
return
Arrays
.
asList
(
this
,
highResolutionImage
);
}
}
static
void
testToolkitMultiResolutionImagePrepare
()
throws
Exception
{
generateImages
();
File
imageFile
=
new
File
(
IMAGE_NAME_1X
);
String
fileName
=
imageFile
.
getAbsolutePath
();
Image
image
=
Toolkit
.
getDefaultToolkit
().
getImage
(
fileName
);
SunToolkit
toolkit
=
(
SunToolkit
)
Toolkit
.
getDefaultToolkit
();
toolkit
.
prepareImage
(
image
,
IMAGE_WIDTH
,
IMAGE_HEIGHT
,
new
LoadImageObserver
(
image
));
testToolkitMultiResolutionImageLoad
(
image
);
}
static
void
testToolkitMultiResolutionImageLoad
()
throws
Exception
{
generateImages
();
File
imageFile
=
new
File
(
IMAGE_NAME_1X
);
String
fileName
=
imageFile
.
getAbsolutePath
();
Image
image
=
Toolkit
.
getDefaultToolkit
().
getImage
(
fileName
);
testToolkitMultiResolutionImageLoad
(
image
);
}
static
void
testToolkitMultiResolutionImageLoad
(
Image
image
)
throws
Exception
{
MediaTracker
tracker
=
new
MediaTracker
(
new
JPanel
());
tracker
.
addImage
(
image
,
0
);
tracker
.
waitForID
(
0
);
if
(
tracker
.
isErrorAny
())
{
throw
new
RuntimeException
(
"Error during image loading"
);
}
tracker
.
removeImage
(
image
,
0
);
testImageLoaded
(
image
);
int
w
=
image
.
getWidth
(
null
);
int
h
=
image
.
getHeight
(
null
);
Image
resolutionVariant
=
((
MultiResolutionImage
)
image
)
.
getResolutionVariant
(
2
*
w
,
2
*
h
);
if
(
image
==
resolutionVariant
)
{
throw
new
RuntimeException
(
"Resolution variant is not loaded"
);
}
testImageLoaded
(
resolutionVariant
);
}
static
void
testImageLoaded
(
Image
image
)
{
SunToolkit
toolkit
=
(
SunToolkit
)
Toolkit
.
getDefaultToolkit
();
int
flags
=
toolkit
.
checkImage
(
image
,
IMAGE_WIDTH
,
IMAGE_WIDTH
,
new
SilentImageObserver
());
if
((
flags
&
(
ImageObserver
.
FRAMEBITS
|
ImageObserver
.
ALLBITS
))
==
0
)
{
throw
new
RuntimeException
(
"Image is not loaded!"
);
}
}
static
class
SilentImageObserver
implements
ImageObserver
{
@Override
public
boolean
imageUpdate
(
Image
img
,
int
infoflags
,
int
x
,
int
y
,
int
width
,
int
height
)
{
throw
new
RuntimeException
(
"Observer should not be called!"
);
}
}
static
class
LoadImageObserver
implements
ImageObserver
{
Image
image
;
public
LoadImageObserver
(
Image
image
)
{
this
.
image
=
image
;
}
@Override
public
boolean
imageUpdate
(
Image
img
,
int
infoflags
,
int
x
,
int
y
,
int
width
,
int
height
)
{
if
(
image
!=
img
)
{
throw
new
RuntimeException
(
"Original image is not passed to the observer"
);
}
if
((
infoflags
&
ImageObserver
.
WIDTH
)
!=
0
)
{
if
(
width
!=
IMAGE_WIDTH
)
{
throw
new
RuntimeException
(
"Original width is not passed to the observer"
);
}
}
if
((
infoflags
&
ImageObserver
.
HEIGHT
)
!=
0
)
{
if
(
height
!=
IMAGE_HEIGHT
)
{
throw
new
RuntimeException
(
"Original height is not passed to the observer"
);
}
}
return
(
infoflags
&
ALLBITS
)
==
0
;
}
}
static
void
testToolkitMultiResolutionImage
()
throws
Exception
{
generateImages
();
File
imageFile
=
new
File
(
IMAGE_NAME_1X
);
String
fileName
=
imageFile
.
getAbsolutePath
();
URL
url
=
imageFile
.
toURI
().
toURL
();
testToolkitMultiResolutionImageChache
(
fileName
,
url
);
Image
image
=
Toolkit
.
getDefaultToolkit
().
getImage
(
fileName
);
testToolkitImageObserver
(
image
);
testToolkitMultiResolutionImage
(
image
,
false
);
testToolkitMultiResolutionImage
(
image
,
true
);
image
=
Toolkit
.
getDefaultToolkit
().
getImage
(
url
);
testToolkitImageObserver
(
image
);
testToolkitMultiResolutionImage
(
image
,
false
);
testToolkitMultiResolutionImage
(
image
,
true
);
}
static
void
testToolkitMultiResolutionImageChache
(
String
fileName
,
URL
url
)
{
Image
img1
=
Toolkit
.
getDefaultToolkit
().
getImage
(
fileName
);
if
(!(
img1
instanceof
MultiResolutionImage
))
{
throw
new
RuntimeException
(
"Not a MultiResolutionImage"
);
}
Image
img2
=
Toolkit
.
getDefaultToolkit
().
getImage
(
fileName
);
if
(
img1
!=
img2
)
{
throw
new
RuntimeException
(
"Image is not cached"
);
}
img1
=
Toolkit
.
getDefaultToolkit
().
getImage
(
url
);
if
(!(
img1
instanceof
MultiResolutionImage
))
{
throw
new
RuntimeException
(
"Not a MultiResolutionImage"
);
}
img2
=
Toolkit
.
getDefaultToolkit
().
getImage
(
url
);
if
(
img1
!=
img2
)
{
throw
new
RuntimeException
(
"Image is not cached"
);
}
}
static
void
testToolkitMultiResolutionImage
(
Image
image
,
boolean
enableImageScaling
)
throws
Exception
{
MediaTracker
tracker
=
new
MediaTracker
(
new
JPanel
());
tracker
.
addImage
(
image
,
0
);
tracker
.
waitForID
(
0
);
if
(
tracker
.
isErrorAny
())
{
throw
new
RuntimeException
(
"Error during image loading"
);
}
final
BufferedImage
bufferedImage1x
=
new
BufferedImage
(
IMAGE_WIDTH
,
IMAGE_HEIGHT
,
BufferedImage
.
TYPE_INT_RGB
);
Graphics2D
g1x
=
(
Graphics2D
)
bufferedImage1x
.
getGraphics
();
setImageScalingHint
(
g1x
,
false
);
g1x
.
drawImage
(
image
,
0
,
0
,
null
);
checkColor
(
bufferedImage1x
.
getRGB
(
3
*
IMAGE_WIDTH
/
4
,
3
*
IMAGE_HEIGHT
/
4
),
false
);
Image
resolutionVariant
=
((
MultiResolutionImage
)
image
).
getResolutionVariant
(
2
*
IMAGE_WIDTH
,
2
*
IMAGE_HEIGHT
);
if
(
resolutionVariant
==
null
)
{
throw
new
RuntimeException
(
"Resolution variant is null"
);
}
MediaTracker
tracker2x
=
new
MediaTracker
(
new
JPanel
());
tracker2x
.
addImage
(
resolutionVariant
,
0
);
tracker2x
.
waitForID
(
0
);
if
(
tracker2x
.
isErrorAny
())
{
throw
new
RuntimeException
(
"Error during scalable image loading"
);
}
final
BufferedImage
bufferedImage2x
=
new
BufferedImage
(
2
*
IMAGE_WIDTH
,
2
*
IMAGE_HEIGHT
,
BufferedImage
.
TYPE_INT_RGB
);
Graphics2D
g2x
=
(
Graphics2D
)
bufferedImage2x
.
getGraphics
();
setImageScalingHint
(
g2x
,
enableImageScaling
);
g2x
.
drawImage
(
image
,
0
,
0
,
2
*
IMAGE_WIDTH
,
2
*
IMAGE_HEIGHT
,
0
,
0
,
IMAGE_WIDTH
,
IMAGE_HEIGHT
,
null
);
checkColor
(
bufferedImage2x
.
getRGB
(
3
*
IMAGE_WIDTH
/
2
,
3
*
IMAGE_HEIGHT
/
2
),
enableImageScaling
);
if
(!(
image
instanceof
MultiResolutionImage
))
{
throw
new
RuntimeException
(
"Not a MultiResolutionImage"
);
}
MultiResolutionImage
multiResolutionImage
=
(
MultiResolutionImage
)
image
;
Image
image1x
=
multiResolutionImage
.
getResolutionVariant
(
IMAGE_WIDTH
,
IMAGE_HEIGHT
);
Image
image2x
=
multiResolutionImage
.
getResolutionVariant
(
2
*
IMAGE_WIDTH
,
2
*
IMAGE_HEIGHT
);
if
(
image1x
.
getWidth
(
null
)
*
2
!=
image2x
.
getWidth
(
null
)
||
image1x
.
getHeight
(
null
)
*
2
!=
image2x
.
getHeight
(
null
))
{
throw
new
RuntimeException
(
"Wrong resolution variant size"
);
}
}
static
void
testToolkitImageObserver
(
final
Image
image
)
{
ImageObserver
observer
=
new
ImageObserver
()
{
@Override
public
boolean
imageUpdate
(
Image
img
,
int
infoflags
,
int
x
,
int
y
,
int
width
,
int
height
)
{
if
(
img
!=
image
)
{
throw
new
RuntimeException
(
"Wrong image in observer"
);
}
if
((
infoflags
&
(
ImageObserver
.
ERROR
|
ImageObserver
.
ABORT
))
!=
0
)
{
throw
new
RuntimeException
(
"Error during image loading"
);
}
return
(
infoflags
&
ImageObserver
.
ALLBITS
)
==
0
;
}
};
final
BufferedImage
bufferedImage2x
=
new
BufferedImage
(
2
*
IMAGE_WIDTH
,
2
*
IMAGE_HEIGHT
,
BufferedImage
.
TYPE_INT_RGB
);
Graphics2D
g2x
=
(
Graphics2D
)
bufferedImage2x
.
getGraphics
();
setImageScalingHint
(
g2x
,
true
);
g2x
.
drawImage
(
image
,
0
,
0
,
2
*
IMAGE_WIDTH
,
2
*
IMAGE_HEIGHT
,
0
,
0
,
IMAGE_WIDTH
,
IMAGE_HEIGHT
,
observer
);
}
static
void
setImageScalingHint
(
Graphics2D
g2d
,
boolean
enableImageScaling
)
{
g2d
.
setRenderingHint
(
SunHints
.
KEY_RESOLUTION_VARIANT
,
enableImageScaling
?
SunHints
.
VALUE_RESOLUTION_VARIANT_ON
:
SunHints
.
VALUE_RESOLUTION_VARIANT_OFF
);
}
static
void
checkColor
(
int
rgb
,
boolean
isImageScaled
)
{
if
(!
isImageScaled
&&
COLOR_1X
.
getRGB
()
!=
rgb
)
{
throw
new
RuntimeException
(
"Wrong 1x color: "
+
new
Color
(
rgb
));
}
if
(
isImageScaled
&&
COLOR_2X
.
getRGB
()
!=
rgb
)
{
throw
new
RuntimeException
(
"Wrong 2x color"
+
new
Color
(
rgb
));
}
}
static
void
generateImages
()
throws
Exception
{
if
(!
new
File
(
IMAGE_NAME_1X
).
exists
())
{
generateImage
(
1
);
}
if
(!
new
File
(
IMAGE_NAME_2X
).
exists
())
{
generateImage
(
2
);
}
}
static
void
generateImage
(
int
scale
)
throws
Exception
{
BufferedImage
image
=
new
BufferedImage
(
scale
*
IMAGE_WIDTH
,
scale
*
IMAGE_HEIGHT
,
BufferedImage
.
TYPE_INT_RGB
);
Graphics
g
=
image
.
getGraphics
();
g
.
setColor
(
scale
==
1
?
COLOR_1X
:
COLOR_2X
);
g
.
fillRect
(
0
,
0
,
scale
*
IMAGE_WIDTH
,
scale
*
IMAGE_HEIGHT
);
File
file
=
new
File
(
scale
==
1
?
IMAGE_NAME_1X
:
IMAGE_NAME_2X
);
ImageIO
.
write
(
image
,
"png"
,
file
);
}
static
void
testImageNameTo2xParsing
()
throws
Exception
{
for
(
String
[]
testNames
:
TEST_FILE_NAMES
)
{
String
testName
=
testNames
[
0
];
String
goldenName
=
testNames
[
1
];
String
resultName
=
getTestScaledImageName
(
testName
);
if
(!
isValidPath
(
testName
)
&&
resultName
==
null
)
{
continue
;
}
if
(
goldenName
.
equals
(
resultName
))
{
continue
;
}
throw
new
RuntimeException
(
"Test name "
+
testName
+
", result name: "
+
resultName
);
}
for
(
URL
[]
testURLs
:
TEST_URLS
)
{
URL
testURL
=
testURLs
[
0
];
URL
goldenURL
=
testURLs
[
1
];
URL
resultURL
=
getTestScaledImageURL
(
testURL
);
if
(!
isValidPath
(
testURL
.
getPath
())
&&
resultURL
==
null
)
{
continue
;
}
if
(
goldenURL
.
equals
(
resultURL
))
{
continue
;
}
throw
new
RuntimeException
(
"Test url: "
+
testURL
+
", result url: "
+
resultURL
);
}
}
static
URL
getTestScaledImageURL
(
URL
url
)
throws
Exception
{
Method
method
=
getScalableImageMethod
(
"getScaledImageURL"
,
URL
.
class
);
return
(
URL
)
method
.
invoke
(
null
,
url
);
}
static
String
getTestScaledImageName
(
String
name
)
throws
Exception
{
Method
method
=
getScalableImageMethod
(
"getScaledImageName"
,
String
.
class
);
return
(
String
)
method
.
invoke
(
null
,
name
);
}
private
static
boolean
isValidPath
(
String
path
)
{
return
!
path
.
isEmpty
()
&&
!
path
.
endsWith
(
"/"
)
&&
!
path
.
endsWith
(
"."
)
&&
!
path
.
contains
(
"@2x"
);
}
private
static
Method
getScalableImageMethod
(
String
name
,
Class
...
parameterTypes
)
throws
Exception
{
Toolkit
toolkit
=
Toolkit
.
getDefaultToolkit
();
Method
method
=
toolkit
.
getClass
().
getDeclaredMethod
(
name
,
parameterTypes
);
method
.
setAccessible
(
true
);
return
method
;
}
private
static
final
String
[][]
TEST_FILE_NAMES
;
private
static
final
URL
[][]
TEST_URLS
;
static
{
TEST_FILE_NAMES
=
new
String
[][]{
{
""
,
null
},
{
"."
,
null
},
{
".."
,
null
},
{
"/"
,
null
},
{
"/."
,
null
},
{
"dir/"
,
null
},
{
"dir/."
,
null
},
{
"aaa@2x.png"
,
null
},
{
"/dir/aaa@2x.png"
,
null
},
{
"image"
,
"image@2x"
},
{
"image.ext"
,
"image@2x.ext"
},
{
"image.aaa.ext"
,
"image.aaa@2x.ext"
},
{
"dir/image"
,
"dir/image@2x"
},
{
"dir/image.ext"
,
"dir/image@2x.ext"
},
{
"dir/image.aaa.ext"
,
"dir/image.aaa@2x.ext"
},
{
"dir/aaa.bbb/image"
,
"dir/aaa.bbb/image@2x"
},
{
"dir/aaa.bbb/image.ext"
,
"dir/aaa.bbb/image@2x.ext"
},
{
"dir/aaa.bbb/image.ccc.ext"
,
"dir/aaa.bbb/image.ccc@2x.ext"
},
{
"/dir/image"
,
"/dir/image@2x"
},
{
"/dir/image.ext"
,
"/dir/image@2x.ext"
},
{
"/dir/image.aaa.ext"
,
"/dir/image.aaa@2x.ext"
},
{
"/dir/aaa.bbb/image"
,
"/dir/aaa.bbb/image@2x"
},
{
"/dir/aaa.bbb/image.ext"
,
"/dir/aaa.bbb/image@2x.ext"
},
{
"/dir/aaa.bbb/image.ccc.ext"
,
"/dir/aaa.bbb/image.ccc@2x.ext"
}
};
try
{
TEST_URLS
=
new
URL
[][]{
// file
{
new
URL
(
"file:/aaa"
),
new
URL
(
"file:/aaa@2x"
)},
{
new
URL
(
"file:/aaa.ext"
),
new
URL
(
"file:/aaa@2x.ext"
)},
{
new
URL
(
"file:/aaa.bbb.ext"
),
new
URL
(
"file:/aaa.bbb@2x.ext"
)},
{
new
URL
(
"file:/ccc/aaa.bbb.ext"
),
new
URL
(
"file:/ccc/aaa.bbb@2x.ext"
)},
{
new
URL
(
"file:/ccc.ddd/aaa.bbb.ext"
),
new
URL
(
"file:/ccc.ddd/aaa.bbb@2x.ext"
)},
{
new
URL
(
"file:///~/image"
),
new
URL
(
"file:///~/image@2x"
)},
{
new
URL
(
"file:///~/image.ext"
),
new
URL
(
"file:///~/image@2x.ext"
)},
// http
{
new
URL
(
"http://www.test.com"
),
null
},
{
new
URL
(
"http://www.test.com/"
),
null
},
{
new
URL
(
"http://www.test.com///"
),
null
},
{
new
URL
(
"http://www.test.com/image"
),
new
URL
(
"http://www.test.com/image@2x"
)},
{
new
URL
(
"http://www.test.com/image.ext"
),
new
URL
(
"http://www.test.com/image@2x.ext"
)},
{
new
URL
(
"http://www.test.com/dir/image"
),
new
URL
(
"http://www.test.com/dir/image@2x"
)},
{
new
URL
(
"http://www.test.com:80/dir/image.aaa.ext"
),
new
URL
(
"http://www.test.com:80/dir/image.aaa@2x.ext"
)},
{
new
URL
(
"http://www.test.com:8080/dir/image.aaa.ext"
),
new
URL
(
"http://www.test.com:8080/dir/image.aaa@2x.ext"
)},
// jar
{
new
URL
(
"jar:file:/dir/Java2D.jar!/image"
),
new
URL
(
"jar:file:/dir/Java2D.jar!/image@2x"
)},
{
new
URL
(
"jar:file:/dir/Java2D.jar!/image.aaa.ext"
),
new
URL
(
"jar:file:/dir/Java2D.jar!/image.aaa@2x.ext"
)},
{
new
URL
(
"jar:file:/dir/Java2D.jar!/images/image"
),
new
URL
(
"jar:file:/dir/Java2D.jar!/images/image@2x"
)},
{
new
URL
(
"jar:file:/dir/Java2D.jar!/images/image.ext"
),
new
URL
(
"jar:file:/dir/Java2D.jar!/images/image@2x.ext"
)},
{
new
URL
(
"jar:file:/aaa.bbb/Java2D.jar!/images/image.ext"
),
new
URL
(
"jar:file:/aaa.bbb/Java2D.jar!/images/image@2x.ext"
)},
{
new
URL
(
"jar:file:/dir/Java2D.jar!/aaa.bbb/image.ext"
),
new
URL
(
"jar:file:/dir/Java2D.jar!/aaa.bbb/image@2x.ext"
)},};
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
}
static
class
PreloadedImageObserver
implements
ImageObserver
{
@Override
public
boolean
imageUpdate
(
Image
img
,
int
infoflags
,
int
x
,
int
y
,
int
width
,
int
height
)
{
throw
new
RuntimeException
(
"Image should be already preloaded"
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录