Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
93d6ecca
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看板
提交
93d6ecca
编写于
4月 30, 2008
作者:
P
prr
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6656651: Windows Look and Feel LCD glyph images have some differences from native applications.
Reviewed-by: igor, tdv
上级
5c07bb3a
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
718 addition
and
25 deletion
+718
-25
make/sun/font/FILES_c.gmk
make/sun/font/FILES_c.gmk
+3
-1
make/sun/font/Makefile
make/sun/font/Makefile
+1
-0
src/share/classes/sun/font/FileFontStrike.java
src/share/classes/sun/font/FileFontStrike.java
+119
-20
src/share/classes/sun/font/FontManager.java
src/share/classes/sun/font/FontManager.java
+4
-2
src/share/classes/sun/font/TrueTypeFont.java
src/share/classes/sun/font/TrueTypeFont.java
+25
-0
src/windows/classes/sun/awt/Win32GraphicsEnvironment.java
src/windows/classes/sun/awt/Win32GraphicsEnvironment.java
+3
-2
src/windows/native/sun/font/lcdglyph.c
src/windows/native/sun/font/lcdglyph.c
+481
-0
test/java/awt/Graphics2D/DrawString/ScaledLCDTextMetrics.java
.../java/awt/Graphics2D/DrawString/ScaledLCDTextMetrics.java
+82
-0
未找到文件。
make/sun/font/FILES_c.gmk
浏览文件 @
93d6ecca
...
...
@@ -113,7 +113,9 @@ FILES_cpp_shared = \
ifeq ($(PLATFORM),windows)
FILES_c_platform = fontpath.c
FILES_c_platform = fontpath.c \
lcdglyph.c
FILES_cpp_platform = D3DTextRenderer.cpp
else
FILES_c_platform = X11FontScaler.c \
...
...
make/sun/font/Makefile
浏览文件 @
93d6ecca
...
...
@@ -63,6 +63,7 @@ FILES_export = \
java/awt/Font.java
\
java/text/Bidi.java
\
sun/font/FileFont.java
\
sun/font/FileFontStrike.java
\
sun/font/FontManager.java
\
sun/font/GlyphList.java
\
sun/font/NativeFont.java
\
...
...
src/share/classes/sun/font/FileFontStrike.java
浏览文件 @
93d6ecca
...
...
@@ -27,6 +27,7 @@ package sun.font;
import
java.lang.ref.SoftReference
;
import
java.awt.Font
;
import
java.awt.GraphicsEnvironment
;
import
java.awt.Rectangle
;
import
java.awt.geom.AffineTransform
;
import
java.awt.geom.GeneralPath
;
...
...
@@ -105,6 +106,19 @@ public class FileFontStrike extends PhysicalStrike {
boolean
useNatives
;
NativeStrike
[]
nativeStrikes
;
/* Used only for communication to native layer */
private
int
intPtSize
;
/* Perform global initialisation needed for Windows native rasterizer */
private
static
native
boolean
initNative
();
private
static
boolean
isXPorLater
=
false
;
static
{
if
(
FontManager
.
isWindows
&&
!
FontManager
.
useT2K
&&
!
GraphicsEnvironment
.
isHeadless
())
{
isXPorLater
=
initNative
();
}
}
FileFontStrike
(
FileFont
fileFont
,
FontStrikeDesc
desc
)
{
super
(
fileFont
,
desc
);
this
.
fileFont
=
fileFont
;
...
...
@@ -165,7 +179,7 @@ public class FileFontStrike extends PhysicalStrike {
* should not segment unless there's another reason to do so.
*/
float
ptSize
=
(
float
)
matrix
[
3
];
// interpreted only when meaningful.
int
iSize
=
(
int
)
ptSize
;
int
iSize
=
intPtSize
=
(
int
)
ptSize
;
boolean
isSimpleTx
=
(
at
.
getType
()
&
complexTX
)
==
0
;
segmentedCache
=
(
numGlyphs
>
SEGSIZE
<<
3
)
||
...
...
@@ -189,8 +203,26 @@ public class FileFontStrike extends PhysicalStrike {
FontManager
.
deRegisterBadFont
(
fileFont
);
return
;
}
if
(
fileFont
.
checkUseNatives
()
&&
desc
.
aaHint
==
0
&&
!
algoStyle
)
{
/* First, see if native code should be used to create the glyph.
* GDI will return the integer metrics, not fractional metrics, which
* may be requested for this strike, so we would require here that :
* desc.fmHint != INTVAL_FRACTIONALMETRICS_ON
* except that the advance returned by GDI is always overwritten by
* the JDK rasteriser supplied one (see getGlyphImageFromWindows()).
*/
if
(
FontManager
.
isWindows
&&
isXPorLater
&&
!
FontManager
.
useT2K
&&
!
GraphicsEnvironment
.
isHeadless
()
&&
!
fileFont
.
useJavaRasterizer
&&
(
desc
.
aaHint
==
INTVAL_TEXT_ANTIALIAS_LCD_HRGB
||
desc
.
aaHint
==
INTVAL_TEXT_ANTIALIAS_LCD_HBGR
)
&&
(
matrix
[
1
]
==
0.0
&&
matrix
[
2
]
==
0.0
&&
matrix
[
0
]
==
matrix
[
3
]
&&
matrix
[
0
]
>=
3.0
&&
matrix
[
0
]
<=
100.0
)
&&
!((
TrueTypeFont
)
fileFont
).
useEmbeddedBitmapsForSize
(
intPtSize
))
{
useNatives
=
true
;
}
else
if
(
fileFont
.
checkUseNatives
()
&&
desc
.
aaHint
==
0
&&
!
algoStyle
)
{
/* Check its a simple scale of a pt size in the range
* where native bitmaps typically exist (6-36 pts) */
if
(
matrix
[
1
]
==
0.0
&&
matrix
[
2
]
==
0.0
&&
...
...
@@ -208,7 +240,16 @@ public class FileFontStrike extends PhysicalStrike {
}
}
}
if
(
FontManager
.
logging
&&
FontManager
.
isWindows
)
{
FontManager
.
logger
.
info
(
"Strike for "
+
fileFont
+
" at size = "
+
intPtSize
+
" use natives = "
+
useNatives
+
" useJavaRasteriser = "
+
fileFont
.
useJavaRasterizer
+
" AAHint = "
+
desc
.
aaHint
+
" Has Embedded bitmaps = "
+
((
TrueTypeFont
)
fileFont
).
useEmbeddedBitmapsForSize
(
intPtSize
));
}
this
.
disposer
=
new
FontStrikeDisposer
(
fileFont
,
desc
,
pScalerContext
);
/* Always get the image and the advance together for smaller sizes
...
...
@@ -255,8 +296,50 @@ public class FileFontStrike extends PhysicalStrike {
return
fileFont
.
getNumGlyphs
();
}
/* Try the native strikes first, then try the fileFont strike */
long
getGlyphImageFromNative
(
int
glyphCode
)
{
if
(
FontManager
.
isWindows
)
{
return
getGlyphImageFromWindows
(
glyphCode
);
}
else
{
return
getGlyphImageFromX11
(
glyphCode
);
}
}
/* There's no global state conflicts, so this method is not
* presently synchronized.
*/
private
native
long
_getGlyphImageFromWindows
(
String
family
,
int
style
,
int
size
,
int
glyphCode
,
boolean
fracMetrics
);
long
getGlyphImageFromWindows
(
int
glyphCode
)
{
String
family
=
fileFont
.
getFamilyName
(
null
);
int
style
=
desc
.
style
&
Font
.
BOLD
|
desc
.
style
&
Font
.
ITALIC
|
fileFont
.
getStyle
();
int
size
=
intPtSize
;
long
ptr
=
_getGlyphImageFromWindows
(
family
,
style
,
size
,
glyphCode
,
desc
.
fmHint
==
INTVAL_FRACTIONALMETRICS_ON
);
if
(
ptr
!=
0
)
{
/* Get the advance from the JDK rasterizer. This is mostly
* necessary for the fractional metrics case, but there are
* also some very small number (<0.25%) of marginal cases where
* there is some rounding difference between windows and JDK.
* After these are resolved, we can restrict this extra
* work to the FM case.
*/
float
advance
=
getGlyphAdvance
(
glyphCode
,
false
);
StrikeCache
.
unsafe
.
putFloat
(
ptr
+
StrikeCache
.
xAdvanceOffset
,
advance
);
return
ptr
;
}
else
{
return
fileFont
.
getGlyphImage
(
pScalerContext
,
glyphCode
);
}
}
/* Try the native strikes first, then try the fileFont strike */
long
getGlyphImageFromX11
(
int
glyphCode
)
{
long
glyphPtr
;
char
charCode
=
fileFont
.
glyphToCharMap
[
glyphCode
];
for
(
int
i
=
0
;
i
<
nativeStrikes
.
length
;
i
++)
{
...
...
@@ -276,13 +359,19 @@ public class FileFontStrike extends PhysicalStrike {
if
(
glyphCode
>=
INVISIBLE_GLYPHS
)
{
return
StrikeCache
.
invisibleGlyphPtr
;
}
long
glyphPtr
;
long
glyphPtr
=
0L
;
if
((
glyphPtr
=
getCachedGlyphPtr
(
glyphCode
))
!=
0L
)
{
return
glyphPtr
;
}
else
{
if
(
useNatives
)
{
glyphPtr
=
getGlyphImageFromNative
(
glyphCode
);
}
else
{
if
(
glyphPtr
==
0L
&&
FontManager
.
logging
)
{
FontManager
.
logger
.
info
(
"Strike for "
+
fileFont
+
" at size = "
+
intPtSize
+
" couldn't get native glyph for code = "
+
glyphCode
);
}
}
if
(
glyphPtr
==
0L
)
{
glyphPtr
=
fileFont
.
getGlyphImage
(
pScalerContext
,
glyphCode
);
}
...
...
@@ -300,10 +389,10 @@ public class FileFontStrike extends PhysicalStrike {
}
else
if
((
images
[
i
]
=
getCachedGlyphPtr
(
glyphCode
))
!=
0L
)
{
continue
;
}
else
{
long
glyphPtr
;
long
glyphPtr
=
0L
;
if
(
useNatives
)
{
glyphPtr
=
getGlyphImageFromNative
(
glyphCode
);
}
else
{
}
if
(
glyphPtr
==
0L
)
{
glyphPtr
=
fileFont
.
getGlyphImage
(
pScalerContext
,
glyphCode
);
}
...
...
@@ -332,10 +421,11 @@ public class FileFontStrike extends PhysicalStrike {
}
else
if
((
images
[
i
]
=
getCachedGlyphPtr
(
glyphCode
))
!=
0L
)
{
continue
;
}
else
{
long
glyphPtr
;
long
glyphPtr
=
0L
;
if
(
useNatives
)
{
glyphPtr
=
getGlyphImageFromNative
(
glyphCode
);
}
else
{
}
if
(
glyphPtr
==
0L
)
{
glyphPtr
=
fileFont
.
getGlyphImage
(
pScalerContext
,
glyphCode
);
}
...
...
@@ -459,11 +549,16 @@ public class FileFontStrike extends PhysicalStrike {
}
}
float
getGlyphAdvance
(
int
glyphCode
)
{
return
getGlyphAdvance
(
glyphCode
,
true
);
}
/* Metrics info is always retrieved. If the GlyphInfo address is non-zero
* then metrics info there is valid and can just be copied.
* This is in user space coordinates.
* This is in user space coordinates unless getUserAdv == false.
* Device space advance should not be propagated out of this class.
*/
float
getGlyphAdvance
(
int
glyphCode
)
{
private
float
getGlyphAdvance
(
int
glyphCode
,
boolean
getUserAdv
)
{
float
advance
;
if
(
glyphCode
>=
INVISIBLE_GLYPHS
)
{
...
...
@@ -485,11 +580,11 @@ public class FileFontStrike extends PhysicalStrike {
}
}
if
(
invertDevTx
!=
null
)
{
if
(
invertDevTx
!=
null
||
!
getUserAdv
)
{
/* If there is a device transform need x & y advance to
* transform back into user space.
*/
advance
=
getGlyphMetrics
(
glyphCode
).
x
;
advance
=
getGlyphMetrics
(
glyphCode
,
getUserAdv
).
x
;
}
else
{
long
glyphPtr
;
if
(
getImageWithAdvance
)
{
...
...
@@ -625,6 +720,10 @@ public class FileFontStrike extends PhysicalStrike {
}
Point2D
.
Float
getGlyphMetrics
(
int
glyphCode
)
{
return
getGlyphMetrics
(
glyphCode
,
true
);
}
private
Point2D
.
Float
getGlyphMetrics
(
int
glyphCode
,
boolean
getUserAdv
)
{
Point2D
.
Float
metrics
=
new
Point2D
.
Float
();
// !!! or do we force sgv user glyphs?
...
...
@@ -632,7 +731,7 @@ public class FileFontStrike extends PhysicalStrike {
return
metrics
;
}
long
glyphPtr
;
if
(
getImageWithAdvance
)
{
if
(
getImageWithAdvance
&&
getUserAdv
)
{
/* A heuristic optimisation says that for most cases its
* worthwhile retrieving the image at the same time as the
* metrics. So here we get the image data even if its not
...
...
@@ -649,9 +748,9 @@ public class FileFontStrike extends PhysicalStrike {
metrics
.
y
=
StrikeCache
.
unsafe
.
getFloat
(
glyphPtr
+
StrikeCache
.
yAdvanceOffset
);
/* advance is currently in device space, need to convert back
* into user space.
* into user space
, unless getUserAdv == false
.
* This must not include the translation component. */
if
(
invertDevTx
!=
null
)
{
if
(
invertDevTx
!=
null
&&
getUserAdv
)
{
invertDevTx
.
deltaTransform
(
metrics
,
metrics
);
}
}
else
{
...
...
@@ -680,9 +779,9 @@ public class FileFontStrike extends PhysicalStrike {
if
(
value
==
null
)
{
fileFont
.
getGlyphMetrics
(
pScalerContext
,
glyphCode
,
metrics
);
/* advance is currently in device space, need to convert back
* into user space.
* into user space
, unless getUserAdv == false
.
*/
if
(
invertDevTx
!=
null
)
{
if
(
invertDevTx
!=
null
&&
getUserAdv
)
{
invertDevTx
.
deltaTransform
(
metrics
,
metrics
);
}
value
=
new
Point2D
.
Float
(
metrics
.
x
,
metrics
.
y
);
...
...
src/share/classes/sun/font/FontManager.java
浏览文件 @
93d6ecca
...
...
@@ -244,9 +244,11 @@ public final class FontManager {
osName
=
System
.
getProperty
(
"os.name"
,
"unknownOS"
);
isSolaris
=
osName
.
startsWith
(
"SunOS"
);
if
(
isSolaris
)
{
String
t2kStr
=
System
.
getProperty
(
"sun.java2d.font.scaler"
);
String
t2kStr
=
System
.
getProperty
(
"sun.java2d.font.scaler"
);
if
(
t2kStr
!=
null
)
{
useT2K
=
"t2k"
.
equals
(
t2kStr
);
}
if
(
isSolaris
)
{
String
version
=
System
.
getProperty
(
"os.version"
,
"unk"
);
isSolaris8
=
version
.
equals
(
"5.8"
);
isSolaris9
=
version
.
equals
(
"5.9"
);
...
...
src/share/classes/sun/font/TrueTypeFont.java
浏览文件 @
93d6ecca
...
...
@@ -893,6 +893,31 @@ public class TrueTypeFont extends FileFont {
return
null
;
}
/* Used to determine if this size has embedded bitmaps, which
* for CJK fonts should be used in preference to LCD glyphs.
*/
boolean
useEmbeddedBitmapsForSize
(
int
ptSize
)
{
if
(!
supportsCJK
)
{
return
false
;
}
if
(
getDirectoryEntry
(
EBLCTag
)
==
null
)
{
return
false
;
}
ByteBuffer
eblcTable
=
getTableBuffer
(
EBLCTag
);
int
numSizes
=
eblcTable
.
getInt
(
4
);
/* The bitmapSizeTable's start at offset of 8.
* Each bitmapSizeTable entry is 48 bytes.
* The offset of ppemY in the entry is 45.
*/
for
(
int
i
=
0
;
i
<
numSizes
;
i
++)
{
int
ppemY
=
eblcTable
.
get
(
8
+(
i
*
48
)+
45
)
&
0xff
;
if
(
ppemY
==
ptSize
)
{
return
true
;
}
}
return
false
;
}
public
String
getFullName
()
{
return
fullName
;
}
...
...
src/windows/classes/sun/awt/Win32GraphicsEnvironment.java
浏览文件 @
93d6ecca
...
...
@@ -260,6 +260,7 @@ public class Win32GraphicsEnvironment
try
{
while
(!
found
&&
parser
.
hasMoreTokens
())
{
String
newPath
=
parser
.
nextToken
();
boolean
ujr
=
newPath
.
equals
(
jreFontDirName
);
File
theFile
=
new
File
(
newPath
,
fontFileName
);
if
(
theFile
.
canRead
())
{
found
=
true
;
...
...
@@ -267,11 +268,11 @@ public class Win32GraphicsEnvironment
if
(
defer
)
{
FontManager
.
registerDeferredFont
(
fontFileName
,
path
,
nativeNames
,
fontFormat
,
true
,
fontFormat
,
ujr
,
fontRank
);
}
else
{
FontManager
.
registerFontFile
(
path
,
nativeNames
,
fontFormat
,
true
,
fontFormat
,
ujr
,
fontRank
);
}
break
;
...
...
src/windows/native/sun/font/lcdglyph.c
0 → 100644
浏览文件 @
93d6ecca
/*
* Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* The function here is used to get a GDI rasterized LCD glyph and place it
* into the JDK glyph cache. The benefit is rendering fidelity for the
* most common cases, with no impact on the 2D rendering pipelines.
*
* Requires that the font and graphics are unrotated, and the scale is
* a simple one, and the font is a TT font registered with windows.
* Those conditions are established by the calling code.
*
* This code
* - Receives the family name, style, and size of the font
* and creates a Font object.
* - Create a surface from which we can get a DC : must be 16 bit or more.
* Ideally we'd be able to specify the depth of this, but in practice we
* have to accept it will be the same as the default screen.
* - Selects the GDI font on to the device
* - Uses GetGlyphOutline to estimate the bounds.
* - Creates a DIB on to which to blit the image.
* - Creates a GlyphInfo structure and copies the GDI glyph and offsets
* into the glyph which is returned.
*/
#include <stdio.h>
#include <malloc.h>
#include <math.h>
#include <windows.h>
#include <winuser.h>
#include <jni.h>
#include <jni_util.h>
#include <jlong_md.h>
#include <sun_font_FileFontStrike.h>
#include "fontscalerdefs.h"
/* Some of these are also defined in awtmsg.h but I don't want a dependency
* on that here. They are needed here - and in awtmsg.h - until we
* move up our build to define WIN32_WINNT >= 0x501 (ie XP), since MS
* headers will not define them otherwise.
*/
#ifndef SPI_GETFONTSMOOTHINGTYPE
#define SPI_GETFONTSMOOTHINGTYPE 0x200A
#endif //SPI_GETFONTSMOOTHINGTYPE
#ifndef SPI_GETFONTSMOOTHINGCONTRAST
#define SPI_GETFONTSMOOTHINGCONTRAST 0x200C
#endif //SPI_GETFONTSMOOTHINGCONTRAST
#ifndef SPI_GETFONTSMOOTHINGORIENTATION
#define SPI_GETFONTSMOOTHINGORIENTATION 0x2012
#endif //SPI_GETFONTSMOOTHINGORIENTATION
#ifndef FE_FONTSMOOTHINGORIENTATIONBGR
#define FE_FONTSMOOTHINGORIENTATIONBGR 0x0000
#endif //FE_FONTSMOOTHINGORIENTATIONBGR
#ifndef FE_FONTSMOOTHINGORIENTATIONRGB
#define FE_FONTSMOOTHINGORIENTATIONRGB 0x0001
#endif //FE_FONTSMOOTHINGORIENTATIONRGB
#define MIN_GAMMA 100
#define MAX_GAMMA 220
#define LCDLUTCOUNT (MAX_GAMMA-MIN_GAMMA+1)
static
unsigned
char
*
igLUTable
[
LCDLUTCOUNT
];
static
unsigned
char
*
getIGTable
(
int
gamma
)
{
int
i
,
index
;
double
ig
;
char
*
igTable
;
if
(
gamma
<
MIN_GAMMA
)
{
gamma
=
MIN_GAMMA
;
}
else
if
(
gamma
>
MAX_GAMMA
)
{
gamma
=
MAX_GAMMA
;
}
index
=
gamma
-
MIN_GAMMA
;
if
(
igLUTable
[
index
]
!=
NULL
)
{
return
igLUTable
[
index
];
}
igTable
=
(
unsigned
char
*
)
malloc
(
256
);
if
(
igTable
==
NULL
)
{
return
NULL
;
}
igTable
[
0
]
=
0
;
igTable
[
255
]
=
255
;
ig
=
((
double
)
gamma
)
/
100
.
0
;
for
(
i
=
1
;
i
<
255
;
i
++
)
{
igTable
[
i
]
=
(
unsigned
char
)(
pow
(((
double
)
i
)
/
255
.
0
,
ig
)
*
255
);
}
igLUTable
[
index
]
=
igTable
;
return
igTable
;
}
JNIEXPORT
jboolean
JNICALL
Java_sun_font_FileFontStrike_initNative
(
JNIEnv
*
env
,
jclass
unused
)
{
DWORD
osVersion
=
GetVersion
();
DWORD
majorVersion
=
(
DWORD
)(
LOBYTE
(
LOWORD
(
osVersion
)));
DWORD
minorVersion
=
(
DWORD
)(
HIBYTE
(
LOWORD
(
osVersion
)));
/* Need at least XP which is 5.1 */
if
(
majorVersion
<
5
||
(
majorVersion
==
5
&&
minorVersion
<
1
))
{
return
JNI_FALSE
;
}
memset
(
igLUTable
,
0
,
LCDLUTCOUNT
);
return
JNI_TRUE
;
}
#ifndef CLEARTYPE_QUALITY
#define CLEARTYPE_QUALITY 5
#endif
#ifndef CLEARTYPE_NATURAL_QUALITY
#define CLEARTYPE_NATURAL_QUALITY 6
#endif
#define FREE_AND_RETURN \
if (hDesktopDC != 0 && hWnd != 0) { \
ReleaseDC(hWnd, hDesktopDC); \
}\
if (hMemoryDC != 0) { \
DeleteObject(hMemoryDC); \
} \
if (hBitmap != 0) { \
DeleteObject(hBitmap); \
} \
if (dibImage != NULL) { \
free(dibImage); \
} \
if (glyphInfo != NULL) { \
free(glyphInfo); \
} \
return (jlong)0;
/* end define */
JNIEXPORT
jlong
JNICALL
Java_sun_font_FileFontStrike__1getGlyphImageFromWindows
(
JNIEnv
*
env
,
jobject
unused
,
jstring
fontFamily
,
jint
style
,
jint
size
,
jint
glyphCode
,
jboolean
fm
)
{
GLYPHMETRICS
glyphMetrics
;
LOGFONTW
lf
;
BITMAPINFO
bmi
;
TEXTMETRIC
textMetric
;
RECT
rect
;
int
bytesWidth
,
dibBytesWidth
,
extra
,
imageSize
,
dibImageSize
;
unsigned
char
*
dibImage
=
NULL
,
*
rowPtr
,
*
pixelPtr
,
*
dibPixPtr
,
*
dibRowPtr
;
unsigned
char
r
,
g
,
b
;
unsigned
char
*
igTable
;
GlyphInfo
*
glyphInfo
=
NULL
;
int
nameLen
;
LPWSTR
name
;
HFONT
oldFont
,
hFont
;
MAT2
mat2
;
unsigned
short
width
;
unsigned
short
height
;
short
advanceX
;
short
advanceY
;
int
topLeftX
;
int
topLeftY
;
int
err
;
int
bmWidth
,
bmHeight
;
int
x
,
y
;
HBITMAP
hBitmap
=
NULL
,
hOrigBM
;
int
gamma
,
orient
;
HWND
hWnd
=
NULL
;
HDC
hDesktopDC
=
NULL
;
HDC
hMemoryDC
=
NULL
;
hWnd
=
GetDesktopWindow
();
hDesktopDC
=
GetWindowDC
(
hWnd
);
if
(
hDesktopDC
==
NULL
)
{
return
(
jlong
)
0
;
}
if
(
GetDeviceCaps
(
hDesktopDC
,
BITSPIXEL
)
<
15
)
{
FREE_AND_RETURN
;
}
hMemoryDC
=
CreateCompatibleDC
(
hDesktopDC
);
if
(
hMemoryDC
==
NULL
||
fontFamily
==
NULL
)
{
FREE_AND_RETURN
;
}
err
=
SetMapMode
(
hMemoryDC
,
MM_TEXT
);
if
(
err
==
0
)
{
FREE_AND_RETURN
;
}
memset
(
&
lf
,
0
,
sizeof
(
LOGFONTW
));
lf
.
lfHeight
=
-
size
;
lf
.
lfWeight
=
(
style
&
1
)
?
FW_BOLD
:
FW_NORMAL
;
lf
.
lfItalic
=
(
style
&
2
)
?
0xff
:
0
;
lf
.
lfCharSet
=
DEFAULT_CHARSET
;
lf
.
lfQuality
=
CLEARTYPE_QUALITY
;
lf
.
lfOutPrecision
=
OUT_TT_PRECIS
;
lf
.
lfClipPrecision
=
CLIP_DEFAULT_PRECIS
;
lf
.
lfPitchAndFamily
=
DEFAULT_PITCH
;
nameLen
=
(
*
env
)
->
GetStringLength
(
env
,
fontFamily
);
name
=
(
LPWSTR
)
alloca
((
nameLen
+
1
)
*
2
);
if
(
name
==
NULL
)
{
FREE_AND_RETURN
;
}
(
*
env
)
->
GetStringRegion
(
env
,
fontFamily
,
0
,
nameLen
,
name
);
name
[
nameLen
]
=
'\0'
;
if
(
nameLen
<
(
sizeof
(
lf
.
lfFaceName
)
/
sizeof
(
lf
.
lfFaceName
[
0
])))
{
wcscpy
(
lf
.
lfFaceName
,
name
);
}
else
{
FREE_AND_RETURN
;
}
hFont
=
CreateFontIndirectW
(
&
lf
);
if
(
hFont
==
NULL
)
{
FREE_AND_RETURN
;
}
oldFont
=
SelectObject
(
hMemoryDC
,
hFont
);
memset
(
&
textMetric
,
0
,
sizeof
(
TEXTMETRIC
));
err
=
GetTextMetrics
(
hMemoryDC
,
&
textMetric
);
if
(
err
==
0
)
{
FREE_AND_RETURN
;
}
memset
(
&
glyphMetrics
,
0
,
sizeof
(
GLYPHMETRICS
));
memset
(
&
mat2
,
0
,
sizeof
(
MAT2
));
mat2
.
eM11
.
value
=
1
;
mat2
.
eM22
.
value
=
1
;
err
=
GetGlyphOutline
(
hMemoryDC
,
glyphCode
,
GGO_METRICS
|
GGO_GLYPH_INDEX
,
&
glyphMetrics
,
0
,
NULL
,
&
mat2
);
if
(
err
==
GDI_ERROR
)
{
/* Probably no such glyph - ie the font wasn't the one we expected. */
FREE_AND_RETURN
;
}
width
=
(
unsigned
short
)
glyphMetrics
.
gmBlackBoxX
;
height
=
(
unsigned
short
)
glyphMetrics
.
gmBlackBoxY
;
/* Don't handle "invisible" glyphs in this code */
if
(
width
<=
0
||
height
==
0
)
{
FREE_AND_RETURN
;
}
advanceX
=
glyphMetrics
.
gmCellIncX
;
advanceY
=
glyphMetrics
.
gmCellIncY
;
topLeftX
=
glyphMetrics
.
gmptGlyphOrigin
.
x
;
topLeftY
=
glyphMetrics
.
gmptGlyphOrigin
.
y
;
/* GetGlyphOutline pre-dates cleartype and I'm not sure that it will
* account for all pixels touched by the rendering. Need to widen,
* and also adjust by one the x position at which it is rendered.
* The extra pixels of width are used as follows :
* One extra pixel at the left and the right will be needed to absorb
* the pixels that will be touched by filtering by GDI to compensate
* for colour fringing.
* However there seem to be some cases where GDI renders two extra
* pixels to the right, so we add one additional pixel to the right,
* and in the code that copies this to the image cache we test for
* the (rare) cases when this is touched, and if its not reduce the
* stated image width for the blitting loops.
* For fractional metrics :
* One extra pixel at each end to account for sub-pixel positioning used
* when fractional metrics is on in LCD mode.
* The pixel at the left is needed so the blitting loop can index into
* that a byte at a time to more accurately position the glyph.
* The pixel at the right is needed so that when such indexing happens,
* the blitting still can use the same width.
* Consequently the width that is specified for the glyph is one less
* than that of the actual image.
* Note that in the FM case as a consequence we need to adjust the
* position at which GDI renders, and the declared width of the glyph
* See the if (fm) {} cases in the code.
* For the non-FM case, we not only save 3 bytes per row, but this
* prevents apparent glyph overlapping which affects the rendering
* performance of accelerated pipelines since it adds additional
* read-back requirements.
*/
width
+=
3
;
if
(
fm
)
{
width
+=
1
;
}
/* DIB scanline must end on a DWORD boundary. We specify 3 bytes per pixel,
* so must round up as needed to a multiple of 4 bytes.
*/
dibBytesWidth
=
bytesWidth
=
width
*
3
;
extra
=
dibBytesWidth
%
4
;
if
(
extra
!=
0
)
{
dibBytesWidth
+=
(
4
-
extra
);
}
/* The glyph cache image must be a multiple of 3 bytes wide. */
extra
=
bytesWidth
%
3
;
if
(
extra
!=
0
)
{
bytesWidth
+=
(
3
-
extra
);
}
bmWidth
=
width
;
bmHeight
=
height
;
/* Must use desktop DC to create a bitmap of that depth */
hBitmap
=
CreateCompatibleBitmap
(
hDesktopDC
,
bmWidth
,
bmHeight
);
if
(
hBitmap
==
NULL
)
{
FREE_AND_RETURN
;
}
hOrigBM
=
(
HBITMAP
)
SelectObject
(
hMemoryDC
,
hBitmap
);
/* Fill in black */
rect
.
left
=
0
;
rect
.
top
=
0
;
rect
.
right
=
bmWidth
;
rect
.
bottom
=
bmHeight
;
FillRect
(
hMemoryDC
,
(
LPRECT
)
&
rect
,
GetStockObject
(
BLACK_BRUSH
));
/* Set text color to white, background to black. */
SetBkColor
(
hMemoryDC
,
RGB
(
0
,
0
,
0
));
SetTextColor
(
hMemoryDC
,
RGB
(
255
,
255
,
255
));
/* adjust rendering position */
x
=
-
topLeftX
+
1
;
if
(
fm
)
{
x
+=
1
;
}
y
=
topLeftY
-
textMetric
.
tmAscent
;
err
=
ExtTextOutW
(
hMemoryDC
,
x
,
y
,
ETO_GLYPH_INDEX
|
ETO_OPAQUE
,
(
LPRECT
)
&
rect
,
(
LPCWSTR
)
&
glyphCode
,
1
,
NULL
);
if
(
err
==
0
)
{
FREE_AND_RETURN
;
}
/* Now get the image into a DIB.
* MS docs for GetDIBits says the compatible bitmap must not be
* selected into a DC, so restore the original first.
*/
SelectObject
(
hMemoryDC
,
hOrigBM
);
SelectObject
(
hMemoryDC
,
oldFont
);
DeleteObject
(
hFont
);
memset
(
&
bmi
,
0
,
sizeof
(
BITMAPINFO
));
bmi
.
bmiHeader
.
biSize
=
sizeof
(
bmi
.
bmiHeader
);
bmi
.
bmiHeader
.
biWidth
=
width
;
bmi
.
bmiHeader
.
biHeight
=
-
height
;
bmi
.
bmiHeader
.
biPlanes
=
1
;
bmi
.
bmiHeader
.
biBitCount
=
24
;
bmi
.
bmiHeader
.
biCompression
=
BI_RGB
;
dibImageSize
=
dibBytesWidth
*
height
;
dibImage
=
malloc
(
dibImageSize
);
if
(
dibImage
==
NULL
)
{
FREE_AND_RETURN
;
}
memset
(
dibImage
,
0
,
dibImageSize
);
err
=
GetDIBits
(
hMemoryDC
,
hBitmap
,
0
,
height
,
dibImage
,
&
bmi
,
DIB_RGB_COLORS
);
if
(
err
==
0
)
{
/* GetDIBits failed. */
FREE_AND_RETURN
;
}
err
=
SystemParametersInfo
(
SPI_GETFONTSMOOTHINGORIENTATION
,
0
,
&
orient
,
0
);
if
(
err
==
0
)
{
FREE_AND_RETURN
;
}
err
=
SystemParametersInfo
(
SPI_GETFONTSMOOTHINGCONTRAST
,
0
,
&
gamma
,
0
);
if
(
err
==
0
)
{
FREE_AND_RETURN
;
}
igTable
=
getIGTable
(
gamma
/
10
);
if
(
igTable
==
NULL
)
{
FREE_AND_RETURN
;
}
/* Now copy glyph image into a GlyphInfo structure and return it.
* NB the xadvance calculated here may be overwritten by the caller.
* 1 is subtracted from the bitmap width to get the glyph width, since
* that extra "1" was added as padding, so the sub-pixel positioning of
* fractional metrics could index into it.
*/
imageSize
=
bytesWidth
*
height
;
glyphInfo
=
(
GlyphInfo
*
)
malloc
(
sizeof
(
GlyphInfo
)
+
imageSize
);
if
(
malloc
==
NULL
)
{
FREE_AND_RETURN
;
}
glyphInfo
->
cellInfo
=
NULL
;
glyphInfo
->
rowBytes
=
bytesWidth
;
glyphInfo
->
width
=
width
;
if
(
fm
)
{
glyphInfo
->
width
-=
1
;
// must subtract 1
}
glyphInfo
->
height
=
height
;
glyphInfo
->
advanceX
=
advanceX
;
glyphInfo
->
advanceY
=
advanceY
;
glyphInfo
->
topLeftX
=
(
float
)(
topLeftX
-
1
);
if
(
fm
)
{
glyphInfo
->
topLeftX
-=
1
;
}
glyphInfo
->
topLeftY
=
(
float
)
-
topLeftY
;
glyphInfo
->
image
=
(
unsigned
char
*
)
glyphInfo
+
sizeof
(
GlyphInfo
);
memset
(
glyphInfo
->
image
,
0
,
imageSize
);
/* DIB 24bpp data is always stored in BGR order, but we usually
* need this in RGB, so we can't just memcpy and need to swap B and R.
* Also need to apply inverse gamma adjustment here.
* We re-use the variable "extra" to see if the last pixel is touched
* at all. If its not we can reduce the glyph image width. This comes
* into play in some cases where GDI touches more pixels than accounted
* for by increasing width by two pixels over the B&W image. Whilst
* the bytes are in the cache, it doesn't affect rendering performance
* of the hardware pipelines.
*/
extra
=
0
;
if
(
fm
)
{
extra
=
1
;
// always need it.
}
dibRowPtr
=
dibImage
;
rowPtr
=
glyphInfo
->
image
;
for
(
y
=
0
;
y
<
height
;
y
++
)
{
pixelPtr
=
rowPtr
;
dibPixPtr
=
dibRowPtr
;
for
(
x
=
0
;
x
<
width
;
x
++
)
{
if
(
orient
==
FE_FONTSMOOTHINGORIENTATIONRGB
)
{
b
=
*
dibPixPtr
++
;
g
=
*
dibPixPtr
++
;
r
=
*
dibPixPtr
++
;
}
else
{
r
=
*
dibPixPtr
++
;
g
=
*
dibPixPtr
++
;
b
=
*
dibPixPtr
++
;
}
*
pixelPtr
++
=
igTable
[
r
];
*
pixelPtr
++
=
igTable
[
g
];
*
pixelPtr
++
=
igTable
[
b
];
if
(
!
fm
&&
(
x
==
(
width
-
1
))
&&
(
r
|
g
|
b
))
{
extra
=
1
;
}
}
dibRowPtr
+=
dibBytesWidth
;
rowPtr
+=
bytesWidth
;
}
if
(
!
extra
)
{
glyphInfo
->
width
-=
1
;
}
free
(
dibImage
);
ReleaseDC
(
hWnd
,
hDesktopDC
);
DeleteObject
(
hMemoryDC
);
DeleteObject
(
hBitmap
);
return
ptr_to_jlong
(
glyphInfo
);
}
test/java/awt/Graphics2D/DrawString/ScaledLCDTextMetrics.java
0 → 100644
浏览文件 @
93d6ecca
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/**
* @test
* @bug 6685312
* @summary Check advance of LCD text on a scaled graphics.
*/
import
javax.swing.*
;
import
java.awt.*
;
import
static
java
.
awt
.
RenderingHints
.*;
public
class
ScaledLCDTextMetrics
extends
Component
{
public
static
void
main
(
String
[]
args
)
{
JFrame
f
=
new
JFrame
();
f
.
setDefaultCloseOperation
(
JFrame
.
EXIT_ON_CLOSE
);
f
.
add
(
"Center"
,
new
ScaledLCDTextMetrics
());
f
.
pack
();
f
.
setVisible
(
true
);
}
public
Dimension
getPreferredSize
()
{
return
new
Dimension
(
200
,
100
);
}
public
void
paint
(
Graphics
g
)
{
Graphics2D
g2
=
(
Graphics2D
)
g
;
Font
f
=
new
Font
(
"Tahoma"
,
Font
.
PLAIN
,
11
);
g
.
setFont
(
f
);
g
.
setColor
(
Color
.
white
);
g
.
fillRect
(
0
,
0
,
400
,
300
);
g
.
setColor
(
Color
.
black
);
g2
.
setRenderingHint
(
KEY_TEXT_ANTIALIASING
,
VALUE_TEXT_ANTIALIAS_LCD_HRGB
);
String
text
=
"ABCDEFGHIJKLI"
;
FontMetrics
fm1
=
g2
.
getFontMetrics
();
int
adv1
=
fm1
.
stringWidth
(
text
);
g
.
drawString
(
text
,
5
,
20
);
g2
.
scale
(
2
,
2
);
FontMetrics
fm2
=
g2
.
getFontMetrics
();
int
adv2
=
fm2
.
stringWidth
(
text
);
g
.
drawString
(
text
,
5
,
40
);
double
frac
=
Math
.
abs
(
adv1
/(
double
)
adv2
);
System
.
out
.
println
(
"scalex1: "
+
adv1
);
System
.
out
.
println
(
"scalex2: "
+
adv2
);
System
.
out
.
println
(
"Fraction : "
+
frac
);
// adv1 will not be exactly the same as adv2, but should differ
// only by a fraction.
if
(
frac
<
0.8
||
frac
>
1.2
)
{
throw
new
RuntimeException
(
"Metrics differ "
+
"Adv1="
+
adv1
+
" Adv2="
+
adv2
+
" Fraction="
+
frac
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录