Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
beff7858
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看板
提交
beff7858
编写于
12月 14, 2010
作者:
F
flar
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6766342: Improve performance of Ductus rasterizer
Reviewed-by: jgodinez, prr
上级
2dfaa02f
变更
19
隐藏空白更改
内联
并排
Showing
19 changed file
with
3204 addition
and
133 deletion
+3204
-133
make/sun/awt/make.depend
make/sun/awt/make.depend
+3
-3
make/sun/awt/mapfile-vers
make/sun/awt/mapfile-vers
+2
-0
make/sun/awt/mapfile-vers-linux
make/sun/awt/mapfile-vers-linux
+2
-0
src/share/classes/sun/dc/DuctusRenderingEngine.java
src/share/classes/sun/dc/DuctusRenderingEngine.java
+82
-0
src/share/classes/sun/java2d/SurfaceData.java
src/share/classes/sun/java2d/SurfaceData.java
+60
-27
src/share/classes/sun/java2d/loops/CompositeType.java
src/share/classes/sun/java2d/loops/CompositeType.java
+33
-6
src/share/classes/sun/java2d/loops/MaskFill.java
src/share/classes/sun/java2d/loops/MaskFill.java
+66
-0
src/share/classes/sun/java2d/pipe/AAShapePipe.java
src/share/classes/sun/java2d/pipe/AAShapePipe.java
+65
-3
src/share/classes/sun/java2d/pipe/AlphaColorPipe.java
src/share/classes/sun/java2d/pipe/AlphaColorPipe.java
+20
-1
src/share/classes/sun/java2d/pipe/RenderingEngine.java
src/share/classes/sun/java2d/pipe/RenderingEngine.java
+85
-0
src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java
...hare/classes/sun/java2d/pisces/PiscesRenderingEngine.java
+63
-0
src/share/native/sun/java2d/loops/DrawParallelogram.c
src/share/native/sun/java2d/loops/DrawParallelogram.c
+5
-42
src/share/native/sun/java2d/loops/FillParallelogram.c
src/share/native/sun/java2d/loops/FillParallelogram.c
+5
-37
src/share/native/sun/java2d/loops/MaskFill.c
src/share/native/sun/java2d/loops/MaskFill.c
+965
-0
src/share/native/sun/java2d/loops/ParallelogramUtils.h
src/share/native/sun/java2d/loops/ParallelogramUtils.h
+83
-0
src/solaris/native/sun/java2d/loops/vis_IntArgbPre_Mask.c
src/solaris/native/sun/java2d/loops/vis_IntArgbPre_Mask.c
+8
-4
src/solaris/native/sun/java2d/loops/vis_SrcMaskFill.c
src/solaris/native/sun/java2d/loops/vis_SrcMaskFill.c
+20
-10
test/java/awt/Graphics2D/RenderClipTest/6766342.tests
test/java/awt/Graphics2D/RenderClipTest/6766342.tests
+3
-0
test/java/awt/Graphics2D/RenderClipTest/RenderClipTest.java
test/java/awt/Graphics2D/RenderClipTest/RenderClipTest.java
+1634
-0
未找到文件。
make/sun/awt/make.depend
浏览文件 @
beff7858
...
...
@@ -224,7 +224,7 @@ $(OBJDIR)/DllUtil.obj:: ../../../src/windows/native/sun/windows/DllUtil.h
$(OBJDIR)/DrawLine.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_DrawLine.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h
$(OBJDIR)/DrawParallelogram.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_DrawParallelogram.h
$(CLASSHDRDIR)/sun_java2d_loops_FillParallelogram.h ../../../src/share/javavm/export/classfile_constants.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/loops/LoopMacro
s.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h
$(OBJDIR)/DrawParallelogram.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_DrawParallelogram.h
../../../src/share/javavm/export/classfile_constants.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/loops/ParallelogramUtil
s.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h
$(OBJDIR)/DrawPath.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_DrawPath.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/DrawPath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/loops/ProcessPath.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h
...
...
@@ -232,7 +232,7 @@ $(OBJDIR)/DrawPolygons.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDR
$(OBJDIR)/DrawRect.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_DrawRect.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h
$(OBJDIR)/FillParallelogram.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_FillParallelogram.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h
$(OBJDIR)/FillParallelogram.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_FillParallelogram.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/
loops/ParallelogramUtils.h ../../../src/share/native/sun/java2d/
pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h
$(OBJDIR)/FillPath.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_FillPath.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/DrawPath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/loops/ProcessPath.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h
...
...
@@ -284,7 +284,7 @@ $(OBJDIR)/IntRgbx.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h ../../../src/sh
$(OBJDIR)/MaskBlit.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_MaskBlit.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/pipe/Region.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/awt/utility/rect.h ../../../src/windows/native/sun/java2d/j2d_md.h
$(OBJDIR)/MaskFill.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_MaskFill.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h
$(OBJDIR)/MaskFill.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_MaskFill.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/
loops/ParallelogramUtils.h ../../../src/share/native/sun/java2d/
pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h
$(OBJDIR)/MouseInfo.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/classfile_constants.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h
...
...
make/sun/awt/mapfile-vers
浏览文件 @
beff7858
...
...
@@ -118,6 +118,8 @@ SUNWprivate_1.1 {
Java_sun_java2d_loops_GraphicsPrimitiveMgr_registerNativeLoops;
Java_sun_java2d_loops_MaskBlit_MaskBlit;
Java_sun_java2d_loops_MaskFill_MaskFill;
Java_sun_java2d_loops_MaskFill_FillAAPgram;
Java_sun_java2d_loops_MaskFill_DrawAAPgram;
Java_sun_java2d_loops_TransformHelper_Transform;
Java_sun_java2d_pipe_Region_initIDs;
Java_sun_java2d_pipe_SpanClipRenderer_initIDs;
...
...
make/sun/awt/mapfile-vers-linux
浏览文件 @
beff7858
...
...
@@ -115,6 +115,8 @@ SUNWprivate_1.1 {
Java_sun_java2d_loops_GraphicsPrimitiveMgr_registerNativeLoops;
Java_sun_java2d_loops_MaskBlit_MaskBlit;
Java_sun_java2d_loops_MaskFill_MaskFill;
Java_sun_java2d_loops_MaskFill_FillAAPgram;
Java_sun_java2d_loops_MaskFill_DrawAAPgram;
Java_sun_java2d_pipe_BufferedRenderPipe_fillSpans;
Java_sun_java2d_pipe_SpanClipRenderer_initIDs;
sun_awt_image_GifImageDecoder_initIDs;
...
...
src/share/classes/sun/dc/DuctusRenderingEngine.java
浏览文件 @
beff7858
...
...
@@ -635,6 +635,88 @@ public class DuctusRenderingEngine extends RenderingEngine {
return
r
;
}
/**
* {@inheritDoc}
*/
@Override
public
AATileGenerator
getAATileGenerator
(
double
x
,
double
y
,
double
dx1
,
double
dy1
,
double
dx2
,
double
dy2
,
double
lw1
,
double
lw2
,
Region
clip
,
int
bbox
[])
{
// REMIND: Deal with large coordinates!
double
ldx1
,
ldy1
,
ldx2
,
ldy2
;
boolean
innerpgram
=
(
lw1
>
0
&&
lw2
>
0
);
if
(
innerpgram
)
{
ldx1
=
dx1
*
lw1
;
ldy1
=
dy1
*
lw1
;
ldx2
=
dx2
*
lw2
;
ldy2
=
dy2
*
lw2
;
x
-=
(
ldx1
+
ldx2
)
/
2.0
;
y
-=
(
ldy1
+
ldy2
)
/
2.0
;
dx1
+=
ldx1
;
dy1
+=
ldy1
;
dx2
+=
ldx2
;
dy2
+=
ldy2
;
if
(
lw1
>
1
&&
lw2
>
1
)
{
// Inner parallelogram was entirely consumed by stroke...
innerpgram
=
false
;
}
}
else
{
ldx1
=
ldy1
=
ldx2
=
ldy2
=
0
;
}
Rasterizer
r
=
getRasterizer
();
r
.
setUsage
(
Rasterizer
.
EOFILL
);
r
.
beginPath
();
r
.
beginSubpath
((
float
)
x
,
(
float
)
y
);
r
.
appendLine
((
float
)
(
x
+
dx1
),
(
float
)
(
y
+
dy1
));
r
.
appendLine
((
float
)
(
x
+
dx1
+
dx2
),
(
float
)
(
y
+
dy1
+
dy2
));
r
.
appendLine
((
float
)
(
x
+
dx2
),
(
float
)
(
y
+
dy2
));
r
.
closedSubpath
();
if
(
innerpgram
)
{
x
+=
ldx1
+
ldx2
;
y
+=
ldy1
+
ldy2
;
dx1
-=
2.0
*
ldx1
;
dy1
-=
2.0
*
ldy1
;
dx2
-=
2.0
*
ldx2
;
dy2
-=
2.0
*
ldy2
;
r
.
beginSubpath
((
float
)
x
,
(
float
)
y
);
r
.
appendLine
((
float
)
(
x
+
dx1
),
(
float
)
(
y
+
dy1
));
r
.
appendLine
((
float
)
(
x
+
dx1
+
dx2
),
(
float
)
(
y
+
dy1
+
dy2
));
r
.
appendLine
((
float
)
(
x
+
dx2
),
(
float
)
(
y
+
dy2
));
r
.
closedSubpath
();
}
try
{
r
.
endPath
();
r
.
getAlphaBox
(
bbox
);
clip
.
clipBoxToBounds
(
bbox
);
if
(
bbox
[
0
]
>=
bbox
[
2
]
||
bbox
[
1
]
>=
bbox
[
3
])
{
dropRasterizer
(
r
);
return
null
;
}
r
.
setOutputArea
(
bbox
[
0
],
bbox
[
1
],
bbox
[
2
]
-
bbox
[
0
],
bbox
[
3
]
-
bbox
[
1
]);
}
catch
(
PRException
e
)
{
/*
* This exeption is thrown from the native part of the Ductus
* (only in case of a debug build) to indicate that some
* segments of the path have very large coordinates.
* See 4485298 for more info.
*/
System
.
err
.
println
(
"DuctusRenderingEngine.getAATileGenerator: "
+
e
);
}
return
r
;
}
private
void
feedConsumer
(
PathConsumer
consumer
,
PathIterator
pi
)
{
try
{
consumer
.
beginPath
();
...
...
src/share/classes/sun/java2d/SurfaceData.java
浏览文件 @
beff7858
...
...
@@ -367,16 +367,17 @@ public abstract class SurfaceData
public
static
final
TextPipe
aaTextRenderer
;
public
static
final
TextPipe
lcdTextRenderer
;
protected
static
final
Composite
Pipe
colorPipe
;
protected
static
final
AlphaColor
Pipe
colorPipe
;
protected
static
final
PixelToShapeConverter
colorViaShape
;
protected
static
final
PixelToParallelogramConverter
colorViaPgram
;
protected
static
final
TextPipe
colorText
;
protected
static
final
CompositePipe
clipColorPipe
;
protected
static
final
TextPipe
clipColorText
;
protected
static
final
AAShapePipe
AAColorShape
;
protected
static
final
PixelToShapeConverter
AAColorViaShape
;
protected
static
final
PixelToParallelogramConverter
AAColorViaShape
;
protected
static
final
PixelToParallelogramConverter
AAColorViaPgram
;
protected
static
final
AAShapePipe
AAClipColorShape
;
protected
static
final
PixelTo
Shape
Converter
AAClipColorViaShape
;
protected
static
final
PixelTo
Parallelogram
Converter
AAClipColorViaShape
;
protected
static
final
CompositePipe
paintPipe
;
protected
static
final
SpanShapeRenderer
paintShape
;
...
...
@@ -385,9 +386,9 @@ public abstract class SurfaceData
protected
static
final
CompositePipe
clipPaintPipe
;
protected
static
final
TextPipe
clipPaintText
;
protected
static
final
AAShapePipe
AAPaintShape
;
protected
static
final
PixelTo
Shape
Converter
AAPaintViaShape
;
protected
static
final
PixelTo
Parallelogram
Converter
AAPaintViaShape
;
protected
static
final
AAShapePipe
AAClipPaintShape
;
protected
static
final
PixelTo
Shape
Converter
AAClipPaintViaShape
;
protected
static
final
PixelTo
Parallelogram
Converter
AAClipPaintViaShape
;
protected
static
final
CompositePipe
compPipe
;
protected
static
final
SpanShapeRenderer
compShape
;
...
...
@@ -396,9 +397,9 @@ public abstract class SurfaceData
protected
static
final
CompositePipe
clipCompPipe
;
protected
static
final
TextPipe
clipCompText
;
protected
static
final
AAShapePipe
AACompShape
;
protected
static
final
PixelTo
Shape
Converter
AACompViaShape
;
protected
static
final
PixelTo
Parallelogram
Converter
AACompViaShape
;
protected
static
final
AAShapePipe
AAClipCompShape
;
protected
static
final
PixelTo
Shape
Converter
AAClipCompViaShape
;
protected
static
final
PixelTo
Parallelogram
Converter
AAClipCompViaShape
;
protected
static
final
DrawImagePipe
imagepipe
;
...
...
@@ -427,6 +428,22 @@ public abstract class SurfaceData
}
}
private
static
PixelToParallelogramConverter
makeConverter
(
AAShapePipe
renderer
,
ParallelogramPipe
pgrampipe
)
{
return
new
PixelToParallelogramConverter
(
renderer
,
pgrampipe
,
1.0
/
8.0
,
0.499
,
false
);
}
private
static
PixelToParallelogramConverter
makeConverter
(
AAShapePipe
renderer
)
{
return
makeConverter
(
renderer
,
renderer
);
}
static
{
colorPrimitives
=
new
LoopPipe
();
...
...
@@ -445,9 +462,10 @@ public abstract class SurfaceData
clipColorPipe
=
new
SpanClipRenderer
(
colorPipe
);
clipColorText
=
new
TextRenderer
(
clipColorPipe
);
AAColorShape
=
new
AAShapePipe
(
colorPipe
);
AAColorViaShape
=
new
PixelToShapeConverter
(
AAColorShape
);
AAColorViaShape
=
makeConverter
(
AAColorShape
);
AAColorViaPgram
=
makeConverter
(
AAColorShape
,
colorPipe
);
AAClipColorShape
=
new
AAShapePipe
(
clipColorPipe
);
AAClipColorViaShape
=
new
PixelToShap
eConverter
(
AAClipColorShape
);
AAClipColorViaShape
=
mak
eConverter
(
AAClipColorShape
);
paintPipe
=
new
AlphaPaintPipe
();
paintShape
=
new
SpanShapeRenderer
.
Composite
(
paintPipe
);
...
...
@@ -456,9 +474,9 @@ public abstract class SurfaceData
clipPaintPipe
=
new
SpanClipRenderer
(
paintPipe
);
clipPaintText
=
new
TextRenderer
(
clipPaintPipe
);
AAPaintShape
=
new
AAShapePipe
(
paintPipe
);
AAPaintViaShape
=
new
PixelToShap
eConverter
(
AAPaintShape
);
AAPaintViaShape
=
mak
eConverter
(
AAPaintShape
);
AAClipPaintShape
=
new
AAShapePipe
(
clipPaintPipe
);
AAClipPaintViaShape
=
new
PixelToShap
eConverter
(
AAClipPaintShape
);
AAClipPaintViaShape
=
mak
eConverter
(
AAClipPaintShape
);
compPipe
=
new
GeneralCompositePipe
();
compShape
=
new
SpanShapeRenderer
.
Composite
(
compPipe
);
...
...
@@ -467,9 +485,9 @@ public abstract class SurfaceData
clipCompPipe
=
new
SpanClipRenderer
(
compPipe
);
clipCompText
=
new
TextRenderer
(
clipCompPipe
);
AACompShape
=
new
AAShapePipe
(
compPipe
);
AACompViaShape
=
new
PixelToShap
eConverter
(
AACompShape
);
AACompViaShape
=
mak
eConverter
(
AACompShape
);
AAClipCompShape
=
new
AAShapePipe
(
clipCompPipe
);
AAClipCompViaShape
=
new
PixelToShap
eConverter
(
AAClipCompShape
);
AAClipCompViaShape
=
mak
eConverter
(
AAClipCompShape
);
imagepipe
=
new
DrawImage
();
}
...
...
@@ -591,12 +609,12 @@ public abstract class SurfaceData
if
(
sg2d
.
clipState
==
sg2d
.
CLIP_SHAPE
)
{
sg2d
.
drawpipe
=
AAClipCompViaShape
;
sg2d
.
fillpipe
=
AAClipCompViaShape
;
sg2d
.
shapepipe
=
AAClipCompShape
;
sg2d
.
shapepipe
=
AAClipComp
Via
Shape
;
sg2d
.
textpipe
=
clipCompText
;
}
else
{
sg2d
.
drawpipe
=
AACompViaShape
;
sg2d
.
fillpipe
=
AACompViaShape
;
sg2d
.
shapepipe
=
AACompShape
;
sg2d
.
shapepipe
=
AAComp
Via
Shape
;
sg2d
.
textpipe
=
compText
;
}
}
else
{
...
...
@@ -616,12 +634,16 @@ public abstract class SurfaceData
if
(
sg2d
.
clipState
==
sg2d
.
CLIP_SHAPE
)
{
sg2d
.
drawpipe
=
AAClipColorViaShape
;
sg2d
.
fillpipe
=
AAClipColorViaShape
;
sg2d
.
shapepipe
=
AAClipColorShape
;
sg2d
.
shapepipe
=
AAClipColor
Via
Shape
;
sg2d
.
textpipe
=
clipColorText
;
}
else
{
sg2d
.
drawpipe
=
AAColorViaShape
;
sg2d
.
fillpipe
=
AAColorViaShape
;
sg2d
.
shapepipe
=
AAColorShape
;
PixelToParallelogramConverter
converter
=
(
sg2d
.
alphafill
.
canDoParallelograms
()
?
AAColorViaPgram
:
AAColorViaShape
);
sg2d
.
drawpipe
=
converter
;
sg2d
.
fillpipe
=
converter
;
sg2d
.
shapepipe
=
converter
;
if
(
sg2d
.
paintState
>
sg2d
.
PAINT_OPAQUECOLOR
||
sg2d
.
compositeState
>
sg2d
.
COMP_ISCOPY
)
{
...
...
@@ -634,12 +656,12 @@ public abstract class SurfaceData
if
(
sg2d
.
clipState
==
sg2d
.
CLIP_SHAPE
)
{
sg2d
.
drawpipe
=
AAClipPaintViaShape
;
sg2d
.
fillpipe
=
AAClipPaintViaShape
;
sg2d
.
shapepipe
=
AAClipPaintShape
;
sg2d
.
shapepipe
=
AAClipPaint
Via
Shape
;
sg2d
.
textpipe
=
clipPaintText
;
}
else
{
sg2d
.
drawpipe
=
AAPaintViaShape
;
sg2d
.
fillpipe
=
AAPaintViaShape
;
sg2d
.
shapepipe
=
AAPaintShape
;
sg2d
.
shapepipe
=
AAPaint
Via
Shape
;
sg2d
.
textpipe
=
paintText
;
}
}
...
...
@@ -793,6 +815,18 @@ public abstract class SurfaceData
}
}
private
static
CompositeType
getFillCompositeType
(
SunGraphics2D
sg2d
)
{
CompositeType
compType
=
sg2d
.
imageComp
;
if
(
sg2d
.
compositeState
==
sg2d
.
COMP_ISCOPY
)
{
if
(
compType
==
CompositeType
.
SrcOverNoEa
)
{
compType
=
CompositeType
.
OpaqueSrcOverNoEa
;
}
else
{
compType
=
CompositeType
.
SrcNoEa
;
}
}
return
compType
;
}
/**
* Returns a MaskFill object that can be used on this destination
* with the source (paint) and composite types determined by the given
...
...
@@ -802,9 +836,10 @@ public abstract class SurfaceData
* surface) before returning a specific MaskFill object.
*/
protected
MaskFill
getMaskFill
(
SunGraphics2D
sg2d
)
{
return
MaskFill
.
getFromCache
(
getPaintSurfaceType
(
sg2d
),
sg2d
.
imageComp
,
getSurfaceType
());
SurfaceType
src
=
getPaintSurfaceType
(
sg2d
);
CompositeType
comp
=
getFillCompositeType
(
sg2d
);
SurfaceType
dst
=
getSurfaceType
();
return
MaskFill
.
getFromCache
(
src
,
comp
,
dst
);
}
private
static
RenderCache
loopcache
=
new
RenderCache
(
30
);
...
...
@@ -816,9 +851,7 @@ public abstract class SurfaceData
*/
public
RenderLoops
getRenderLoops
(
SunGraphics2D
sg2d
)
{
SurfaceType
src
=
getPaintSurfaceType
(
sg2d
);
CompositeType
comp
=
(
sg2d
.
compositeState
==
sg2d
.
COMP_ISCOPY
?
CompositeType
.
SrcNoEa
:
sg2d
.
imageComp
);
CompositeType
comp
=
getFillCompositeType
(
sg2d
);
SurfaceType
dst
=
sg2d
.
getSurfaceData
().
getSurfaceType
();
Object
o
=
loopcache
.
get
(
src
,
comp
,
dst
);
...
...
src/share/classes/sun/java2d/loops/CompositeType.java
浏览文件 @
beff7858
...
...
@@ -27,6 +27,7 @@ package sun.java2d.loops;
import
java.awt.image.BufferedImage
;
import
java.awt.AlphaComposite
;
import
java.util.HashMap
;
/**
* A CompositeType object provides a chained description of a type of
...
...
@@ -51,6 +52,11 @@ import java.awt.AlphaComposite;
* the indicated algorithm if all of the more specific searches fail.
*/
public
final
class
CompositeType
{
private
static
int
unusedUID
=
1
;
private
static
final
HashMap
<
String
,
Integer
>
compositeUIDMap
=
new
HashMap
<
String
,
Integer
>(
100
);
/*
* CONSTANTS USED BY ALL PRIMITIVES TO DESCRIBE THE COMPOSITING
* ALGORITHMS THEY CAN PERFORM
...
...
@@ -152,6 +158,22 @@ public final class CompositeType {
public
static
final
CompositeType
SrcOverNoEa
=
SrcOver
.
deriveSubType
(
DESC_SRC_OVER_NO_EA
);
/*
* A special CompositeType for the case where we are filling in
* SrcOverNoEa mode with an opaque color. In that case then the
* best loop for us to use would be a SrcNoEa loop, but what if
* there is no such loop? In that case then we would end up
* backing off to a Src loop (which should still be fine) or an
* AnyAlpha loop which would be slower than a SrcOver loop in
* most cases.
* The fix is to use the following chain which looks for loops
* in the following order:
* SrcNoEa, Src, SrcOverNoEa, SrcOver, AnyAlpha
*/
public
static
final
CompositeType
OpaqueSrcOverNoEa
=
SrcOverNoEa
.
deriveSubType
(
DESC_SRC
)
.
deriveSubType
(
DESC_SRC_NO_EA
);
/*
* END OF CompositeType OBJECTS FOR THE VARIOUS CONSTANTS
*/
...
...
@@ -210,7 +232,6 @@ public final class CompositeType {
}
}
private
static
int
unusedUID
=
1
;
private
int
uniqueID
;
private
String
desc
;
private
CompositeType
next
;
...
...
@@ -218,14 +239,20 @@ public final class CompositeType {
private
CompositeType
(
CompositeType
parent
,
String
desc
)
{
next
=
parent
;
this
.
desc
=
desc
;
this
.
uniqueID
=
makeUniqueID
();
this
.
uniqueID
=
makeUniqueID
(
desc
);
}
private
synchronized
static
final
int
makeUniqueID
()
{
if
(
unusedUID
>
255
)
{
throw
new
InternalError
(
"composite type id overflow"
);
public
synchronized
static
final
int
makeUniqueID
(
String
desc
)
{
Integer
i
=
compositeUIDMap
.
get
(
desc
);
if
(
i
==
null
)
{
if
(
unusedUID
>
255
)
{
throw
new
InternalError
(
"composite type id overflow"
);
}
i
=
unusedUID
++;
compositeUIDMap
.
put
(
desc
,
i
);
}
return
unusedUID
++
;
return
i
;
}
public
int
getUniqueID
()
{
...
...
src/share/classes/sun/java2d/loops/MaskFill.java
浏览文件 @
beff7858
...
...
@@ -50,6 +50,10 @@ import sun.java2d.SurfaceData;
public
class
MaskFill
extends
GraphicsPrimitive
{
public
static
final
String
methodSignature
=
"MaskFill(...)"
.
toString
();
public
static
final
String
fillPgramSignature
=
"FillAAPgram(...)"
.
toString
();
public
static
final
String
drawPgramSignature
=
"DrawAAPgram(...)"
.
toString
();
public
static
final
int
primTypeID
=
makePrimTypeID
();
...
...
@@ -92,6 +96,14 @@ public class MaskFill extends GraphicsPrimitive
return
fill
;
}
protected
MaskFill
(
String
alternateSignature
,
SurfaceType
srctype
,
CompositeType
comptype
,
SurfaceType
dsttype
)
{
super
(
alternateSignature
,
primTypeID
,
srctype
,
comptype
,
dsttype
);
}
protected
MaskFill
(
SurfaceType
srctype
,
CompositeType
comptype
,
SurfaceType
dsttype
)
...
...
@@ -115,6 +127,23 @@ public class MaskFill extends GraphicsPrimitive
int
x
,
int
y
,
int
w
,
int
h
,
byte
[]
mask
,
int
maskoff
,
int
maskscan
);
public
native
void
FillAAPgram
(
SunGraphics2D
sg2d
,
SurfaceData
sData
,
Composite
comp
,
double
x
,
double
y
,
double
dx1
,
double
dy1
,
double
dx2
,
double
dy2
);
public
native
void
DrawAAPgram
(
SunGraphics2D
sg2d
,
SurfaceData
sData
,
Composite
comp
,
double
x
,
double
y
,
double
dx1
,
double
dy1
,
double
dx2
,
double
dy2
,
double
lw1
,
double
lw2
);
public
boolean
canDoParallelograms
()
{
return
(
getNativePrim
()
!=
0
);
}
static
{
GraphicsPrimitiveMgr
.
registerGeneral
(
new
MaskFill
(
null
,
null
,
null
));
}
...
...
@@ -182,12 +211,22 @@ public class MaskFill extends GraphicsPrimitive
private
static
class
TraceMaskFill
extends
MaskFill
{
MaskFill
target
;
MaskFill
fillPgramTarget
;
MaskFill
drawPgramTarget
;
public
TraceMaskFill
(
MaskFill
target
)
{
super
(
target
.
getSourceType
(),
target
.
getCompositeType
(),
target
.
getDestType
());
this
.
target
=
target
;
this
.
fillPgramTarget
=
new
MaskFill
(
fillPgramSignature
,
target
.
getSourceType
(),
target
.
getCompositeType
(),
target
.
getDestType
());
this
.
drawPgramTarget
=
new
MaskFill
(
drawPgramSignature
,
target
.
getSourceType
(),
target
.
getCompositeType
(),
target
.
getDestType
());
}
public
GraphicsPrimitive
traceWrap
()
{
...
...
@@ -203,5 +242,32 @@ public class MaskFill extends GraphicsPrimitive
target
.
MaskFill
(
sg2d
,
sData
,
comp
,
x
,
y
,
w
,
h
,
mask
,
maskoff
,
maskscan
);
}
public
void
FillAAPgram
(
SunGraphics2D
sg2d
,
SurfaceData
sData
,
Composite
comp
,
double
x
,
double
y
,
double
dx1
,
double
dy1
,
double
dx2
,
double
dy2
)
{
tracePrimitive
(
fillPgramTarget
);
target
.
FillAAPgram
(
sg2d
,
sData
,
comp
,
x
,
y
,
dx1
,
dy1
,
dx2
,
dy2
);
}
public
void
DrawAAPgram
(
SunGraphics2D
sg2d
,
SurfaceData
sData
,
Composite
comp
,
double
x
,
double
y
,
double
dx1
,
double
dy1
,
double
dx2
,
double
dy2
,
double
lw1
,
double
lw2
)
{
tracePrimitive
(
drawPgramTarget
);
target
.
DrawAAPgram
(
sg2d
,
sData
,
comp
,
x
,
y
,
dx1
,
dy1
,
dx2
,
dy2
,
lw1
,
lw2
);
}
public
boolean
canDoParallelograms
()
{
return
target
.
canDoParallelograms
();
}
}
}
src/share/classes/sun/java2d/pipe/AAShapePipe.java
浏览文件 @
beff7858
...
...
@@ -28,6 +28,7 @@ package sun.java2d.pipe;
import
java.awt.BasicStroke
;
import
java.awt.Rectangle
;
import
java.awt.Shape
;
import
java.awt.geom.Rectangle2D
;
import
java.awt.geom.PathIterator
;
import
sun.awt.SunHints
;
import
sun.java2d.SunGraphics2D
;
...
...
@@ -39,7 +40,9 @@ import sun.java2d.SunGraphics2D;
* This class sets up the Generator and computes the alpha tiles
* and then passes them on to a CompositePipe object for painting.
*/
public
class
AAShapePipe
implements
ShapeDrawPipe
{
public
class
AAShapePipe
implements
ShapeDrawPipe
,
ParallelogramPipe
{
static
RenderingEngine
renderengine
=
RenderingEngine
.
getInstance
();
CompositePipe
outpipe
;
...
...
@@ -65,6 +68,59 @@ public class AAShapePipe implements ShapeDrawPipe {
renderPath
(
sg
,
s
,
null
);
}
private
static
Rectangle2D
computeBBox
(
double
x
,
double
y
,
double
dx1
,
double
dy1
,
double
dx2
,
double
dy2
)
{
double
lox
,
loy
,
hix
,
hiy
;
lox
=
hix
=
x
;
loy
=
hiy
=
y
;
if
(
dx1
<
0
)
{
lox
+=
dx1
;
}
else
{
hix
+=
dx1
;
}
if
(
dy1
<
0
)
{
loy
+=
dy1
;
}
else
{
hiy
+=
dy1
;
}
if
(
dx2
<
0
)
{
lox
+=
dx2
;
}
else
{
hix
+=
dx2
;
}
if
(
dy2
<
0
)
{
loy
+=
dy2
;
}
else
{
hiy
+=
dy2
;
}
return
new
Rectangle2D
.
Double
(
lox
,
loy
,
hix
-
lox
,
hiy
-
loy
);
}
public
void
fillParallelogram
(
SunGraphics2D
sg
,
double
x
,
double
y
,
double
dx1
,
double
dy1
,
double
dx2
,
double
dy2
)
{
Region
clip
=
sg
.
getCompClip
();
int
abox
[]
=
new
int
[
4
];
AATileGenerator
aatg
=
renderengine
.
getAATileGenerator
(
x
,
y
,
dx1
,
dy1
,
dx2
,
dy2
,
0
,
0
,
clip
,
abox
);
if
(
aatg
==
null
)
{
// Nothing to render
return
;
}
renderTiles
(
sg
,
computeBBox
(
x
,
y
,
dx1
,
dy1
,
dx2
,
dy2
),
aatg
,
abox
);
}
public
void
drawParallelogram
(
SunGraphics2D
sg
,
double
x
,
double
y
,
double
dx1
,
double
dy1
,
double
dx2
,
double
dy2
,
double
lw1
,
double
lw2
)
{
Region
clip
=
sg
.
getCompClip
();
int
abox
[]
=
new
int
[
4
];
AATileGenerator
aatg
=
renderengine
.
getAATileGenerator
(
x
,
y
,
dx1
,
dy1
,
dx2
,
dy2
,
0
,
0
,
clip
,
abox
);
if
(
aatg
==
null
)
{
// Nothing to render
return
;
}
// Note that bbox is of the original shape, not the wide path.
// This is appropriate for handing to Paint methods...
renderTiles
(
sg
,
computeBBox
(
x
,
y
,
dx1
,
dy1
,
dx2
,
dy2
),
aatg
,
abox
);
}
private
static
byte
[]
theTile
;
public
synchronized
static
byte
[]
getAlphaTile
(
int
len
)
{
...
...
@@ -85,8 +141,6 @@ public class AAShapePipe implements ShapeDrawPipe {
boolean
adjust
=
(
bs
!=
null
&&
sg
.
strokeHint
!=
SunHints
.
INTVAL_STROKE_PURE
);
boolean
thin
=
(
sg
.
strokeState
<=
sg
.
STROKE_THINDASHED
);
Object
context
=
null
;
byte
alpha
[]
=
null
;
Region
clip
=
sg
.
getCompClip
();
int
abox
[]
=
new
int
[
4
];
...
...
@@ -98,6 +152,14 @@ public class AAShapePipe implements ShapeDrawPipe {
return
;
}
renderTiles
(
sg
,
s
,
aatg
,
abox
);
}
public
void
renderTiles
(
SunGraphics2D
sg
,
Shape
s
,
AATileGenerator
aatg
,
int
abox
[])
{
Object
context
=
null
;
byte
alpha
[]
=
null
;
try
{
context
=
outpipe
.
startSequence
(
sg
,
s
,
new
Rectangle
(
abox
[
0
],
abox
[
1
],
...
...
src/share/classes/sun/java2d/pipe/AlphaColorPipe.java
浏览文件 @
beff7858
...
...
@@ -34,7 +34,7 @@ import sun.java2d.SunGraphics2D;
* into a destination that supports direct alpha compositing of a solid
* color, according to one of the rules in the AlphaComposite class.
*/
public
class
AlphaColorPipe
implements
CompositePipe
{
public
class
AlphaColorPipe
implements
CompositePipe
,
ParallelogramPipe
{
public
AlphaColorPipe
()
{
}
...
...
@@ -64,4 +64,23 @@ public class AlphaColorPipe implements CompositePipe {
public
void
endSequence
(
Object
context
)
{
return
;
}
public
void
fillParallelogram
(
SunGraphics2D
sg
,
double
x
,
double
y
,
double
dx1
,
double
dy1
,
double
dx2
,
double
dy2
)
{
sg
.
alphafill
.
FillAAPgram
(
sg
,
sg
.
getSurfaceData
(),
sg
.
composite
,
x
,
y
,
dx1
,
dy1
,
dx2
,
dy2
);
}
public
void
drawParallelogram
(
SunGraphics2D
sg
,
double
x
,
double
y
,
double
dx1
,
double
dy1
,
double
dx2
,
double
dy2
,
double
lw1
,
double
lw2
)
{
sg
.
alphafill
.
DrawAAPgram
(
sg
,
sg
.
getSurfaceData
(),
sg
.
composite
,
x
,
y
,
dx1
,
dy1
,
dx2
,
dy2
,
lw1
,
lw2
);
}
}
src/share/classes/sun/java2d/pipe/RenderingEngine.java
浏览文件 @
beff7858
...
...
@@ -280,6 +280,72 @@ public abstract class RenderingEngine {
boolean
normalize
,
int
bbox
[]);
/**
* Construct an antialiased tile generator for the given parallelogram
* store the bounds of the tile iteration in the bbox parameter.
* The parallelogram is specified as a starting point and 2 delta
* vectors that indicate the slopes of the 2 pairs of sides of the
* parallelogram.
* The 4 corners of the parallelogram are defined by the 4 points:
* <ul>
* <li> {@code x}, {@code y}
* <li> {@code x+dx1}, {@code y+dy1}
* <li> {@code x+dx1+dx2}, {@code y+dy1+dy2}
* <li> {@code x+dx2}, {@code y+dy2}
* </ul>
* The {@code lw1} and {@code lw2} parameters provide a specification
* for an optionally stroked parallelogram if they are positive numbers.
* The {@code lw1} parameter is the ratio of the length of the {@code dx1},
* {@code dx2} delta vector to half of the line width in that same
* direction.
* The {@code lw2} parameter provides the same ratio for the other delta
* vector.
* If {@code lw1} and {@code lw2} are both greater than zero, then
* the parallelogram figure is doubled by both expanding and contracting
* each delta vector by its corresponding {@code lw} value.
* If either (@code lw1) or {@code lw2} are also greater than 1, then
* the inner (contracted) parallelogram disappears and the figure is
* simply a single expanded parallelogram.
* The {@code clip} parameter specifies the current clip in effect
* in device coordinates and can be used to prune the data for the
* operation, but the renderer is not required to perform any
* clipping.
* <p>
* Upon returning, this method will fill the {@code bbox} parameter
* with 4 values indicating the bounds of the iteration of the
* tile generator.
* The iteration order of the tiles will be as specified by the
* pseudo-code:
* <pre>
* for (y = bbox[1]; y < bbox[3]; y += tileheight) {
* for (x = bbox[0]; x < bbox[2]; x += tilewidth) {
* }
* }
* </pre>
* If there is no output to be rendered, this method may return
* null.
*
* @param x the X coordinate of the first corner of the parallelogram
* @param y the Y coordinate of the first corner of the parallelogram
* @param dx1 the X coordinate delta of the first leg of the parallelogram
* @param dy1 the Y coordinate delta of the first leg of the parallelogram
* @param dx2 the X coordinate delta of the second leg of the parallelogram
* @param dy2 the Y coordinate delta of the second leg of the parallelogram
* @param lw1 the line width ratio for the first leg of the parallelogram
* @param lw2 the line width ratio for the second leg of the parallelogram
* @param clip the current clip in effect in device coordinates
* @param bbox returns the bounds of the iteration
* @return the {@code AATileGenerator} instance to be consulted
* for tile coverages, or null if there is no output to render
* @since 1.7
*/
public
abstract
AATileGenerator
getAATileGenerator
(
double
x
,
double
y
,
double
dx1
,
double
dy1
,
double
dx2
,
double
dy2
,
double
lw1
,
double
lw2
,
Region
clip
,
int
bbox
[]);
/**
* Returns the minimum pen width that the antialiasing rasterizer
* can represent without dropouts occuring.
...
...
@@ -393,5 +459,24 @@ public abstract class RenderingEngine {
bs
,
thin
,
normalize
,
bbox
);
}
public
AATileGenerator
getAATileGenerator
(
double
x
,
double
y
,
double
dx1
,
double
dy1
,
double
dx2
,
double
dy2
,
double
lw1
,
double
lw2
,
Region
clip
,
int
bbox
[])
{
System
.
out
.
println
(
name
+
".getAATileGenerator("
+
x
+
", "
+
y
+
", "
+
dx1
+
", "
+
dy1
+
", "
+
dx2
+
", "
+
dy2
+
", "
+
lw1
+
", "
+
lw2
+
", "
+
clip
+
")"
);
return
target
.
getAATileGenerator
(
x
,
y
,
dx1
,
dy1
,
dx2
,
dy2
,
lw1
,
lw2
,
clip
,
bbox
);
}
}
}
src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java
浏览文件 @
beff7858
...
...
@@ -557,6 +557,69 @@ public class PiscesRenderingEngine extends RenderingEngine {
return
ptg
;
}
public
AATileGenerator
getAATileGenerator
(
double
x
,
double
y
,
double
dx1
,
double
dy1
,
double
dx2
,
double
dy2
,
double
lw1
,
double
lw2
,
Region
clip
,
int
bbox
[])
{
// REMIND: Deal with large coordinates!
double
ldx1
,
ldy1
,
ldx2
,
ldy2
;
boolean
innerpgram
=
(
lw1
>
0
&&
lw2
>
0
);
if
(
innerpgram
)
{
ldx1
=
dx1
*
lw1
;
ldy1
=
dy1
*
lw1
;
ldx2
=
dx2
*
lw2
;
ldy2
=
dy2
*
lw2
;
x
-=
(
ldx1
+
ldx2
)
/
2.0
;
y
-=
(
ldy1
+
ldy2
)
/
2.0
;
dx1
+=
ldx1
;
dy1
+=
ldy1
;
dx2
+=
ldx2
;
dy2
+=
ldy2
;
if
(
lw1
>
1
&&
lw2
>
1
)
{
// Inner parallelogram was entirely consumed by stroke...
innerpgram
=
false
;
}
}
else
{
ldx1
=
ldy1
=
ldx2
=
ldy2
=
0
;
}
Renderer
r
=
new
Renderer
(
3
,
3
,
clip
.
getLoX
(),
clip
.
getLoY
(),
clip
.
getWidth
(),
clip
.
getHeight
(),
PathIterator
.
WIND_EVEN_ODD
);
r
.
moveTo
((
float
)
x
,
(
float
)
y
);
r
.
lineTo
((
float
)
(
x
+
dx1
),
(
float
)
(
y
+
dy1
));
r
.
lineTo
((
float
)
(
x
+
dx1
+
dx2
),
(
float
)
(
y
+
dy1
+
dy2
));
r
.
lineTo
((
float
)
(
x
+
dx2
),
(
float
)
(
y
+
dy2
));
r
.
closePath
();
if
(
innerpgram
)
{
x
+=
ldx1
+
ldx2
;
y
+=
ldy1
+
ldy2
;
dx1
-=
2.0
*
ldx1
;
dy1
-=
2.0
*
ldy1
;
dx2
-=
2.0
*
ldx2
;
dy2
-=
2.0
*
ldy2
;
r
.
moveTo
((
float
)
x
,
(
float
)
y
);
r
.
lineTo
((
float
)
(
x
+
dx1
),
(
float
)
(
y
+
dy1
));
r
.
lineTo
((
float
)
(
x
+
dx1
+
dx2
),
(
float
)
(
y
+
dy1
+
dy2
));
r
.
lineTo
((
float
)
(
x
+
dx2
),
(
float
)
(
y
+
dy2
));
r
.
closePath
();
}
r
.
pathDone
();
r
.
endRendering
();
PiscesTileGenerator
ptg
=
new
PiscesTileGenerator
(
r
,
r
.
MAX_AA_ALPHA
);
ptg
.
getBbox
(
bbox
);
return
ptg
;
}
/**
* Returns the minimum pen width that the antialiasing rasterizer
* can represent without dropouts occuring.
...
...
src/share/native/sun/java2d/loops/DrawParallelogram.c
浏览文件 @
beff7858
...
...
@@ -26,14 +26,11 @@
#include "math.h"
#include "GraphicsPrimitiveMgr.h"
#include "LineUtils.h"
#include "LoopMacros.h"
#include "Trace.h"
#include "ParallelogramUtils.h"
#include "sun_java2d_loops_FillParallelogram.h"
#include "sun_java2d_loops_DrawParallelogram.h"
DECLARE_SOLID_DRAWLINE
(
AnyInt
);
#define HANDLE_PGRAM_EDGE(X1, Y1, X2, Y2, \
pRasInfo, pixel, pPrim, pFunc, pCompInfo) \
do { \
...
...
@@ -46,28 +43,6 @@ DECLARE_SOLID_DRAWLINE(AnyInt);
ix1, iy1, ix2, iy2, JNI_TRUE); \
} while (0)
#define PGRAM_MIN_MAX(bmin, bmax, v0, dv1, dv2) \
do { \
double vmin, vmax; \
if (dv1 < 0) { \
vmin = v0+dv1; \
vmax = v0; \
} else { \
vmin = v0; \
vmax = v0+dv1; \
} \
if (dv2 < 0) { \
vmin -= dv2; \
} else { \
vmax += dv2; \
} \
bmin = (jint) floor(vmin + 0.5); \
bmax = (jint) floor(vmax + 0.5); \
} while(0)
#define PGRAM_INIT_X(starty, x, y, slope) \
(DblToLong((x) + (slope) * ((starty)+0.5 - (y))) + LongOneHalf - 1)
typedef
struct
{
jdouble
x0
;
jdouble
y0
;
...
...
@@ -136,20 +111,8 @@ Java_sun_java2d_loops_DrawParallelogram_DrawParallelogram
* Sort parallelogram by y values, ensure that each delta vector
* has a non-negative y delta.
*/
if
(
dy1
<
0
)
{
x0
+=
dx1
;
y0
+=
dy1
;
dx1
=
-
dx1
;
dy1
=
-
dy1
;
}
if
(
dy2
<
0
)
{
x0
+=
dx2
;
y0
+=
dy2
;
dx2
=
-
dx2
;
dy2
=
-
dy2
;
}
/* Sort delta vectors so dxy1 is left of dxy2. */
if
(
dx1
*
dy2
>
dx2
*
dy1
)
{
double
v
=
dx1
;
dx1
=
dx2
;
dx2
=
v
;
v
=
dy1
;
dy1
=
dy2
;
dy2
=
v
;
v
=
lw1
;
lw1
=
lw2
;
lw2
=
v
;
}
SORT_PGRAM
(
x0
,
y0
,
dx1
,
dy1
,
dx2
,
dy2
,
v
=
lw1
;
lw1
=
lw2
;
lw2
=
v
;);
// dx,dy for line width in the "1" and "2" directions.
ldx1
=
dx1
*
lw1
;
...
...
@@ -161,7 +124,7 @@ Java_sun_java2d_loops_DrawParallelogram_DrawParallelogram
ox0
=
x0
-
(
ldx1
+
ldx2
)
/
2
.
0
;
oy0
=
y0
-
(
ldy1
+
ldy2
)
/
2
.
0
;
PGRAM_MIN_MAX
(
ix1
,
ix2
,
ox0
,
dx1
+
ldx1
,
dx2
+
ldx2
);
PGRAM_MIN_MAX
(
ix1
,
ix2
,
ox0
,
dx1
+
ldx1
,
dx2
+
ldx2
,
JNI_FALSE
);
iy1
=
(
jint
)
floor
(
oy0
+
0
.
5
);
iy2
=
(
jint
)
floor
(
oy0
+
dy1
+
ldy1
+
dy2
+
ldy2
+
0
.
5
);
...
...
@@ -212,7 +175,7 @@ Java_sun_java2d_loops_DrawParallelogram_DrawParallelogram
// Only need to generate 4 quads if the interior still
// has a hole in it (i.e. if the line width ratios were
// both less than 1.0)
if
(
lw1
<
1
.
0
f
&&
lw2
<
1
.
0
f
)
{
if
(
lw1
<
1
.
0
&&
lw2
<
1
.
0
)
{
// If the line widths are both less than a pixel wide
// then we can use a drawline function instead for even
// more performance.
...
...
src/share/native/sun/java2d/loops/FillParallelogram.c
浏览文件 @
beff7858
...
...
@@ -25,31 +25,10 @@
#include "math.h"
#include "GraphicsPrimitiveMgr.h"
#include "ParallelogramUtils.h"
#include "sun_java2d_loops_FillParallelogram.h"
#define PGRAM_MIN_MAX(bmin, bmax, v0, dv1, dv2) \
do { \
double vmin, vmax; \
if (dv1 < 0) { \
vmin = v0+dv1; \
vmax = v0; \
} else { \
vmin = v0; \
vmax = v0+dv1; \
} \
if (dv2 < 0) { \
vmin -= dv2; \
} else { \
vmax += dv2; \
} \
bmin = (jint) floor(vmin + 0.5); \
bmax = (jint) floor(vmax + 0.5); \
} while(0)
#define PGRAM_INIT_X(starty, x, y, slope) \
(DblToLong((x) + (slope) * ((starty)+0.5 - (y))) + LongOneHalf - 1)
/*
* Class: sun_java2d_loops_FillParallelogram
* Method: FillParallelogram
...
...
@@ -76,22 +55,11 @@ Java_sun_java2d_loops_FillParallelogram_FillParallelogram
/*
* Sort parallelogram by y values, ensure that each delta vector
* has a non-negative y delta
, and eliminate degenerate parallelograms
.
* has a non-negative y delta.
*/
if
(
dy1
<
0
)
{
x0
+=
dx1
;
y0
+=
dy1
;
dx1
=
-
dx1
;
dy1
=
-
dy1
;
}
if
(
dy2
<
0
)
{
x0
+=
dx2
;
y0
+=
dy2
;
dx2
=
-
dx2
;
dy2
=
-
dy2
;
}
/* Sort delta vectors so dxy1 is left of dxy2. */
if
(
dx1
*
dy2
>
dx2
*
dy1
)
{
double
v
=
dx1
;
dx1
=
dx2
;
dx2
=
v
;
v
=
dy1
;
dy1
=
dy2
;
dy2
=
v
;
}
PGRAM_MIN_MAX
(
ix1
,
ix2
,
x0
,
dx1
,
dx2
);
SORT_PGRAM
(
x0
,
y0
,
dx1
,
dy1
,
dx2
,
dy2
,
);
PGRAM_MIN_MAX
(
ix1
,
ix2
,
x0
,
dx1
,
dx2
,
JNI_FALSE
);
iy1
=
(
jint
)
floor
(
y0
+
0
.
5
);
iy2
=
(
jint
)
floor
(
y0
+
dy1
+
dy2
+
0
.
5
);
...
...
src/share/native/sun/java2d/loops/MaskFill.c
浏览文件 @
beff7858
...
...
@@ -23,7 +23,11 @@
* questions.
*/
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "GraphicsPrimitiveMgr.h"
#include "ParallelogramUtils.h"
#include "sun_java2d_loops_MaskFill.h"
...
...
@@ -93,6 +97,967 @@ Java_sun_java2d_loops_MaskFill_MaskFill
}
}
SurfaceData_InvokeRelease
(
env
,
sdOps
,
&
rasInfo
);
}
SurfaceData_InvokeUnlock
(
env
,
sdOps
,
&
rasInfo
);
}
#define MASK_BUF_LEN 1024
#define DblToMask(v) ((unsigned char) ((v)*255.9999))
/* Fills an aligned rectangle with potentially translucent edges. */
static
void
fillAARect
(
NativePrimitive
*
pPrim
,
SurfaceDataRasInfo
*
pRasInfo
,
CompositeInfo
*
pCompInfo
,
jint
color
,
unsigned
char
*
pMask
,
void
*
pDst
,
jdouble
x1
,
jdouble
y1
,
jdouble
x2
,
jdouble
y2
)
{
jint
cx1
=
pRasInfo
->
bounds
.
x1
;
jint
cy1
=
pRasInfo
->
bounds
.
y1
;
jint
cx2
=
pRasInfo
->
bounds
.
x2
;
jint
cy2
=
pRasInfo
->
bounds
.
y2
;
jint
rx1
=
(
jint
)
ceil
(
x1
);
jint
ry1
=
(
jint
)
ceil
(
y1
);
jint
rx2
=
(
jint
)
floor
(
x2
);
jint
ry2
=
(
jint
)
floor
(
y2
);
jint
width
=
cx2
-
cx1
;
jint
scan
=
pRasInfo
->
scanStride
;
/* Convert xy12 into the edge coverage fractions for those edges. */
x1
=
rx1
-
x1
;
y1
=
ry1
-
y1
;
x2
=
x2
-
rx2
;
y2
=
y2
-
ry2
;
if
(
ry2
<
ry1
)
{
/* Accumulate bottom coverage into top coverage. */
y1
=
y1
+
y2
-
1
.
0
;
/* prevent processing of "bottom fractional row" */
ry2
=
cy2
;
}
if
(
rx2
<
rx1
)
{
/* Accumulate right coverage into left coverage. */
x1
=
x1
+
x2
-
1
.
0
;
/* prevent processing of "right fractional column" */
rx2
=
cx2
;
}
/* Check for a visible "top fractional row" and process it */
if
(
cy1
<
ry1
)
{
unsigned
char
midcov
=
DblToMask
(
y1
);
jint
x
;
for
(
x
=
0
;
x
<
width
;
x
++
)
{
pMask
[
x
]
=
midcov
;
}
if
(
cx1
<
rx1
)
{
pMask
[
0
]
=
DblToMask
(
y1
*
x1
);
}
if
(
cx2
>
rx2
)
{
pMask
[
width
-
1
]
=
DblToMask
(
y1
*
x2
);
}
(
*
pPrim
->
funcs
.
maskfill
)(
pDst
,
pMask
,
0
,
0
,
width
,
1
,
color
,
pRasInfo
,
pPrim
,
pCompInfo
);
pDst
=
PtrAddBytes
(
pDst
,
scan
);
cy1
++
;
}
/* Check for a visible "left fract, solid middle, right fract" section. */
if
(
cy1
<
ry2
&&
cy1
<
cy2
)
{
jint
midh
=
((
ry2
<
cy2
)
?
ry2
:
cy2
)
-
cy1
;
jint
midx
=
cx1
;
void
*
pMid
=
pDst
;
/* First process the left "fractional column" if it is visible. */
if
(
midx
<
rx1
)
{
pMask
[
0
]
=
DblToMask
(
x1
);
/* Note: maskscan == 0 means we reuse this value for every row. */
(
*
pPrim
->
funcs
.
maskfill
)(
pMid
,
pMask
,
0
,
0
,
1
,
midh
,
color
,
pRasInfo
,
pPrim
,
pCompInfo
);
pMid
=
PtrAddBytes
(
pMid
,
pRasInfo
->
pixelStride
);
midx
++
;
}
/* Process the central solid section if it is visible. */
if
(
midx
<
rx2
&&
midx
<
cx2
)
{
jint
midw
=
((
rx2
<
cx2
)
?
rx2
:
cx2
)
-
midx
;
/* A NULL mask buffer means "all coverages are 0xff" */
(
*
pPrim
->
funcs
.
maskfill
)(
pMid
,
NULL
,
0
,
0
,
midw
,
midh
,
color
,
pRasInfo
,
pPrim
,
pCompInfo
);
pMid
=
PtrCoord
(
pMid
,
midw
,
pRasInfo
->
pixelStride
,
0
,
0
);
midx
+=
midw
;
}
/* Finally process the right "fractional column" if it is visible. */
if
(
midx
<
cx2
)
{
pMask
[
0
]
=
DblToMask
(
x2
);
/* Note: maskscan == 0 means we reuse this value for every row. */
(
*
pPrim
->
funcs
.
maskfill
)(
pMid
,
pMask
,
0
,
0
,
1
,
midh
,
color
,
pRasInfo
,
pPrim
,
pCompInfo
);
}
cy1
+=
midh
;
pDst
=
PtrCoord
(
pDst
,
0
,
0
,
midh
,
scan
);
}
/* Check for a visible "bottom fractional row" and process it */
if
(
cy1
<
cy2
)
{
unsigned
char
midcov
=
DblToMask
(
y2
);
jint
x
;
for
(
x
=
0
;
x
<
width
;
x
++
)
{
pMask
[
x
]
=
midcov
;
}
if
(
cx1
<
rx1
)
{
pMask
[
0
]
=
DblToMask
(
y2
*
x1
);
}
if
(
cx2
>
rx2
)
{
pMask
[
width
-
1
]
=
DblToMask
(
y2
*
x2
);
}
(
*
pPrim
->
funcs
.
maskfill
)(
pDst
,
pMask
,
0
,
0
,
width
,
1
,
color
,
pRasInfo
,
pPrim
,
pCompInfo
);
}
}
/*
* Support code for arbitrary tracing and MaskFill filling of
* non-rectilinear (diagonal) parallelograms.
*
* This code is based upon the following model of AA coverage.
*
* Each edge of a parallelogram (for fillPgram) or a double
* parallelogram (inner and outer parallelograms for drawPgram)
* can be rasterized independently because the geometry is well
* defined in such a way that none of the sides will ever cross
* each other and they have a fixed ordering that is fairly
* well predetermined.
*
* So, for each edge we will look at the diagonal line that
* the edge makes as it passes through a row of pixels. Some
* such diagonal lines may pass entirely through the row of
* pixels in a single pixel column. Some may cut across the
* row and pass through several pixel columns before they pass
* on to the next row.
*
* As the edge passes through the row of pixels it will affect
* the coverage of the pixels it passes through as well as all
* of the pixels to the right of the edge. The coverage will
* either be increased (by a left edge of a parallelogram) or
* decreased (by a right edge) for all pixels to the right, until
* another edge passing the opposite direction is encountered.
*
* The coverage added or subtracted by an edge as it crosses a
* given pixel is calculated using a trapezoid formula in the
* following manner:
*
* /
* +-----+---/-+-----+
* | | / | |
* | | / | |
* +-----+/----+-----+
* /
*
* The area to the right of that edge for the pixel where it
* crosses is given as:
*
* trapheight * (topedge + bottomedge)/2
*
* Another thing to note is that the above formula gives the
* contribution of that edge to the given pixel where it crossed,
* but in so crossing the pixel row, it also created 100% coverage
* for all of the pixels to the right.
*
* This example was simplified in that the edge depicted crossed
* the complete pixel row and it did so entirely within the bounds
* of a single pixel column. In practice, many edges may start or
* end in a given row and thus provide only partial row coverage
* (i.e. the total "trapheight" in the formula never reaches 1.0).
* And in other cases, edges may travel sideways through several
* pixel columns on a given pixel row from where they enter it to
* where the leave it (which also mans that the trapheight for a
* given pixel will be less than 1.0, but by the time the edge
* completes its journey through the pixel row the "coverage shadow"
* that it casts on all pixels to the right eventually reaches 100%).
*
* In order to simplify the calculations so that we don't have to
* keep propagating coverages we calculate for one edge "until we
* reach another edge" we will process one edge at a time and
* simply record in a buffer the amount that an edge added to
* or subtracted from the coverage for a given pixel and its
* following right-side neighbors. Thus, the true total coverage
* of a given pixel is only determined by summing the deltas for
* that pixel and all of the pixels to its left. Since we already
* have to scan the buffer to change floating point coverages into
* mask values for a MaskFill loop, it is simple enough to sum the
* values as we perform that scan from left to right.
*
* In the above example, note that 2 deltas need to be recorded even
* though the edge only intersected a single pixel. The delta recorded
* for the pixel where the edge crossed will be approximately 55%
* (guesstimating by examining the poor ascii art) which is fine for
* determining how to render that pixel, but the rest of the pixels
* to its right should have their coverage modified by a full 100%
* and the 55% delta value we recorded for the pixel that the edge
* crossed will not get them there. We adjust for this by adding
* the "remainder" of the coverage implied by the shadow to the
* pixel immediately to the right of where we record a trapezoidal
* contribution. In this case a delta of 45% will be recorded in
* the pixel immediately to the right to raise the total to 100%.
*
* As we sum these delta values as we process the line from left
* to right, these delta values will typically drive the sum from
* 0% up to 100% and back down to 0% over the course of a single
* pixel row. In the case of a drawn (double) parallelogram the
* sum will go to 100% and back to 0% twice on most scanlines.
*
* The fillAAPgram and drawAAPgram functions drive the main flow
* of the algorithm with help from the following structures,
* macros, and functions. It is probably best to start with
* those 2 functions to gain an understanding of the algorithm.
*/
typedef
struct
{
jdouble
x
;
jdouble
y
;
jdouble
xbot
;
jdouble
ybot
;
jdouble
xnexty
;
jdouble
ynextx
;
jdouble
xnextx
;
jdouble
linedx
;
jdouble
celldx
;
jdouble
celldy
;
jboolean
isTrailing
;
}
EdgeInfo
;
#define MIN_DELTA (1.0/256.0)
/*
* Calculates slopes and deltas for an edge and stores results in an EdgeInfo.
* Returns true if the edge was valid (i.e. not ignored for some reason).
*/
static
jboolean
storeEdge
(
EdgeInfo
*
pEdge
,
jdouble
x
,
jdouble
y
,
jdouble
dx
,
jdouble
dy
,
jint
cx1
,
jint
cy1
,
jint
cx2
,
jint
cy2
,
jboolean
isTrailing
)
{
jdouble
xbot
=
x
+
dx
;
jdouble
ybot
=
y
+
dy
;
jboolean
ret
;
pEdge
->
x
=
x
;
pEdge
->
y
=
y
;
pEdge
->
xbot
=
xbot
;
pEdge
->
ybot
=
ybot
;
/* Note that parallelograms are sorted so dy is always non-negative */
if
(
dy
>
MIN_DELTA
&&
/* NaN and horizontal protection */
ybot
>
cy1
&&
/* NaN and "OUT_ABOVE" protection */
y
<
cy2
&&
/* NaN and "OUT_BELOW" protection */
xbot
==
xbot
&&
/* NaN protection */
(
x
<
cx2
||
xbot
<
cx2
))
/* "OUT_RIGHT" protection */
/* Note: "OUT_LEFT" segments may still contribute coverage... */
{
/* no NaNs, dy is not horizontal, and segment contributes to clip */
if
(
dx
<
-
MIN_DELTA
||
dx
>
MIN_DELTA
)
{
/* dx is not vertical */
jdouble
linedx
;
jdouble
celldy
;
jdouble
nextx
;
linedx
=
dx
/
dy
;
celldy
=
dy
/
dx
;
if
(
y
<
cy1
)
{
pEdge
->
x
=
x
=
x
+
(
cy1
-
y
)
*
linedx
;
pEdge
->
y
=
y
=
cy1
;
}
pEdge
->
linedx
=
linedx
;
if
(
dx
<
0
)
{
pEdge
->
celldx
=
-
1
.
0
;
pEdge
->
celldy
=
-
celldy
;
pEdge
->
xnextx
=
nextx
=
ceil
(
x
)
-
1
.
0
;
}
else
{
pEdge
->
celldx
=
+
1
.
0
;
pEdge
->
celldy
=
celldy
;
pEdge
->
xnextx
=
nextx
=
floor
(
x
)
+
1
.
0
;
}
pEdge
->
ynextx
=
y
+
(
nextx
-
x
)
*
celldy
;
pEdge
->
xnexty
=
x
+
((
floor
(
y
)
+
1
)
-
y
)
*
linedx
;
}
else
{
/* dx is essentially vertical */
if
(
y
<
cy1
)
{
pEdge
->
y
=
y
=
cy1
;
}
pEdge
->
xbot
=
x
;
pEdge
->
linedx
=
0
.
0
;
pEdge
->
celldx
=
0
.
0
;
pEdge
->
celldy
=
1
.
0
;
pEdge
->
xnextx
=
x
;
pEdge
->
xnexty
=
x
;
pEdge
->
ynextx
=
ybot
;
}
ret
=
JNI_TRUE
;
}
else
{
/* There is some reason to ignore this segment, "celldy=0" omits it */
pEdge
->
ybot
=
y
;
pEdge
->
linedx
=
dx
;
pEdge
->
celldx
=
dx
;
pEdge
->
celldy
=
0
.
0
;
pEdge
->
xnextx
=
xbot
;
pEdge
->
xnexty
=
xbot
;
pEdge
->
ynextx
=
y
;
ret
=
JNI_FALSE
;
}
pEdge
->
isTrailing
=
isTrailing
;
return
ret
;
}
/*
* Calculates and stores slopes and deltas for all edges of a parallelogram.
* Returns true if at least 1 edge was valid (i.e. not ignored for some reason).
*
* The inverted flag is true for an outer parallelogram (left and right
* edges are leading and trailing) and false for an inner parallelogram
* (where the left edge is trailing and the right edge is leading).
*/
static
jboolean
storePgram
(
EdgeInfo
*
pLeftEdge
,
EdgeInfo
*
pRightEdge
,
jdouble
x
,
jdouble
y
,
jdouble
dx1
,
jdouble
dy1
,
jdouble
dx2
,
jdouble
dy2
,
jint
cx1
,
jint
cy1
,
jint
cx2
,
jint
cy2
,
jboolean
inverted
)
{
jboolean
ret
=
JNI_FALSE
;
ret
=
(
storeEdge
(
pLeftEdge
+
0
,
x
,
y
,
dx1
,
dy1
,
cx1
,
cy1
,
cx2
,
cy2
,
inverted
)
||
ret
);
ret
=
(
storeEdge
(
pLeftEdge
+
1
,
x
+
dx1
,
y
+
dy1
,
dx2
,
dy2
,
cx1
,
cy1
,
cx2
,
cy2
,
inverted
)
||
ret
);
ret
=
(
storeEdge
(
pRightEdge
+
0
,
x
,
y
,
dx2
,
dy2
,
cx1
,
cy1
,
cx2
,
cy2
,
!
inverted
)
||
ret
);
ret
=
(
storeEdge
(
pRightEdge
+
1
,
x
+
dx2
,
y
+
dy2
,
dx1
,
dy1
,
cx1
,
cy1
,
cx2
,
cy2
,
!
inverted
)
||
ret
);
return
ret
;
}
/*
* The X0,Y0,X1,Y1 values represent a trapezoidal fragment whose
* coverage must be accounted for in the accum buffer.
*
* All four values are assumed to fall within (or on the edge of)
* a single pixel.
*
* The trapezoid area is accumulated into the proper element of
* the accum buffer and the remainder of the "slice height" is
* accumulated into the element to its right.
*/
#define INSERT_ACCUM(pACCUM, IMIN, IMAX, X0, Y0, X1, Y1, CX1, CX2, MULT) \
do { \
jdouble xmid = ((X0) + (X1)) * 0.5; \
if (xmid <= (CX2)) { \
jdouble sliceh = ((Y1) - (Y0)); \
jdouble slicearea; \
jint i; \
if (xmid < (CX1)) { \
/* Accumulate the entire slice height into accum[0]. */
\
i = 0; \
slicearea = sliceh; \
} else { \
jdouble xpos = floor(xmid); \
i = ((jint) xpos) - (CX1); \
slicearea = (xpos+1-xmid) * sliceh; \
} \
if (IMIN > i) { \
IMIN = i; \
} \
(pACCUM)[i++] += (jfloat) ((MULT) * slicearea); \
(pACCUM)[i++] += (jfloat) ((MULT) * (sliceh - slicearea)); \
if (IMAX < i) { \
IMAX = i; \
} \
} \
} while (0)
/*
* Accumulate the contributions for a given edge crossing a given
* scan line into the corresponding entries of the accum buffer.
* CY1 is the Y coordinate of the top edge of the scanline and CY2
* is equal to (CY1 + 1) and is the Y coordinate of the bottom edge
* of the scanline. CX1 and CX2 are the left and right edges of the
* clip (or area of interest) being rendered.
*
* The edge is processed from the top edge to the bottom edge and
* a single pixel column at a time.
*/
#define ACCUM_EDGE(pEDGE, pACCUM, IMIN, IMAX, CX1, CY1, CX2, CY2) \
do { \
jdouble x, y, xnext, ynext, xlast, ylast, dx, dy, mult; \
y = (pEDGE)->y; \
dy = (pEDGE)->celldy; \
ylast = (pEDGE)->ybot; \
if (ylast <= (CY1) || y >= (CY2) || dy == 0.0) { \
break; \
} \
x = (pEDGE)->x; \
dx = (pEDGE)->celldx; \
if (ylast > (CY2)) { \
ylast = (CY2); \
xlast = (pEDGE)->xnexty; \
} else { \
xlast = (pEDGE)->xbot; \
} \
xnext = (pEDGE)->xnextx; \
ynext = (pEDGE)->ynextx; \
mult = ((pEDGE)->isTrailing) ? -1.0 : 1.0; \
while (ynext <= ylast) { \
INSERT_ACCUM(pACCUM, IMIN, IMAX, \
x, y, xnext, ynext, \
CX1, CX2, mult); \
x = xnext; \
y = ynext; \
xnext += dx; \
ynext += dy; \
} \
(pEDGE)->ynextx = ynext; \
(pEDGE)->xnextx = xnext; \
INSERT_ACCUM(pACCUM, IMIN, IMAX, \
x, y, xlast, ylast, \
CX1, CX2, mult); \
(pEDGE)->x = xlast; \
(pEDGE)->y = ylast; \
(pEDGE)->xnexty = xlast + (pEDGE)->linedx; \
} while(0)
/* Main function to fill a single Parallelogram */
static
void
fillAAPgram
(
NativePrimitive
*
pPrim
,
SurfaceDataRasInfo
*
pRasInfo
,
CompositeInfo
*
pCompInfo
,
jint
color
,
unsigned
char
*
pMask
,
void
*
pDst
,
jdouble
x1
,
jdouble
y1
,
jdouble
dx1
,
jdouble
dy1
,
jdouble
dx2
,
jdouble
dy2
)
{
jint
cx1
=
pRasInfo
->
bounds
.
x1
;
jint
cy1
=
pRasInfo
->
bounds
.
y1
;
jint
cx2
=
pRasInfo
->
bounds
.
x2
;
jint
cy2
=
pRasInfo
->
bounds
.
y2
;
jint
width
=
cx2
-
cx1
;
EdgeInfo
edges
[
4
];
jfloat
localaccum
[
MASK_BUF_LEN
+
1
];
jfloat
*
pAccum
;
if
(
!
storePgram
(
edges
+
0
,
edges
+
2
,
x1
,
y1
,
dx1
,
dy1
,
dx2
,
dy2
,
cx1
,
cy1
,
cx2
,
cy2
,
JNI_FALSE
))
{
return
;
}
pAccum
=
((
width
>
MASK_BUF_LEN
)
?
malloc
((
width
+
1
)
*
sizeof
(
jfloat
))
:
localaccum
);
if
(
pAccum
==
NULL
)
{
return
;
}
memset
(
pAccum
,
0
,
(
width
+
1
)
*
sizeof
(
jfloat
));
while
(
cy1
<
cy2
)
{
jint
lmin
,
lmax
,
rmin
,
rmax
;
jint
moff
,
x
;
jdouble
accum
;
unsigned
char
lastcov
;
lmin
=
rmin
=
width
+
2
;
lmax
=
rmax
=
0
;
ACCUM_EDGE
(
&
edges
[
0
],
pAccum
,
lmin
,
lmax
,
cx1
,
cy1
,
cx2
,
cy1
+
1
);
ACCUM_EDGE
(
&
edges
[
1
],
pAccum
,
lmin
,
lmax
,
cx1
,
cy1
,
cx2
,
cy1
+
1
);
ACCUM_EDGE
(
&
edges
[
2
],
pAccum
,
rmin
,
rmax
,
cx1
,
cy1
,
cx2
,
cy1
+
1
);
ACCUM_EDGE
(
&
edges
[
3
],
pAccum
,
rmin
,
rmax
,
cx1
,
cy1
,
cx2
,
cy1
+
1
);
if
(
lmax
>
width
)
{
lmax
=
width
;
/* Extra col has data we do not need. */
}
if
(
rmax
>
width
)
{
rmax
=
width
;
/* Extra col has data we do not need. */
}
/* If ranges overlap, handle both in the first pass. */
if
(
rmin
<=
lmax
)
{
lmax
=
rmax
;
}
x
=
lmin
;
accum
=
0
.
0
;
moff
=
0
;
lastcov
=
0
;
while
(
x
<
lmax
)
{
accum
+=
pAccum
[
x
];
pAccum
[
x
]
=
0
.
0
f
;
pMask
[
moff
++
]
=
lastcov
=
DblToMask
(
accum
);
x
++
;
}
/* Check for a solid center section. */
if
(
lastcov
==
0xFF
)
{
jint
endx
;
void
*
pRow
;
/* First process the existing partial coverage data. */
if
(
moff
>
0
)
{
pRow
=
PtrCoord
(
pDst
,
x
-
moff
,
pRasInfo
->
pixelStride
,
0
,
0
);
(
*
pPrim
->
funcs
.
maskfill
)(
pRow
,
pMask
,
0
,
0
,
moff
,
1
,
color
,
pRasInfo
,
pPrim
,
pCompInfo
);
moff
=
0
;
}
/* Where does the center section end? */
/* If there is no right AA edge in the accum buffer, then */
/* the right edge was beyond the clip, so fill out to width */
endx
=
(
rmin
<
rmax
)
?
rmin
:
width
;
if
(
x
<
endx
)
{
pRow
=
PtrCoord
(
pDst
,
x
,
pRasInfo
->
pixelStride
,
0
,
0
);
(
*
pPrim
->
funcs
.
maskfill
)(
pRow
,
NULL
,
0
,
0
,
endx
-
x
,
1
,
color
,
pRasInfo
,
pPrim
,
pCompInfo
);
x
=
endx
;
}
}
else
if
(
lastcov
>
0
&&
rmin
>=
rmax
)
{
/* We are not at 0 coverage, but there is no right edge, */
/* force a right edge so we process pixels out to width. */
rmax
=
width
;
}
/* The following loop will process the right AA edge and/or any */
/* partial coverage center section not processed above. */
while
(
x
<
rmax
)
{
accum
+=
pAccum
[
x
];
pAccum
[
x
]
=
0
.
0
f
;
pMask
[
moff
++
]
=
DblToMask
(
accum
);
x
++
;
}
if
(
moff
>
0
)
{
void
*
pRow
=
PtrCoord
(
pDst
,
x
-
moff
,
pRasInfo
->
pixelStride
,
0
,
0
);
(
*
pPrim
->
funcs
.
maskfill
)(
pRow
,
pMask
,
0
,
0
,
moff
,
1
,
color
,
pRasInfo
,
pPrim
,
pCompInfo
);
}
pDst
=
PtrAddBytes
(
pDst
,
pRasInfo
->
scanStride
);
cy1
++
;
}
if
(
pAccum
!=
localaccum
)
{
free
(
pAccum
);
}
}
/*
* Class: sun_java2d_loops_MaskFill
* Method: FillAAPgram
* Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;Ljava/awt/Composite;DDDDDD)V
*/
JNIEXPORT
void
JNICALL
Java_sun_java2d_loops_MaskFill_FillAAPgram
(
JNIEnv
*
env
,
jobject
self
,
jobject
sg2d
,
jobject
sData
,
jobject
comp
,
jdouble
x0
,
jdouble
y0
,
jdouble
dx1
,
jdouble
dy1
,
jdouble
dx2
,
jdouble
dy2
)
{
SurfaceDataOps
*
sdOps
;
SurfaceDataRasInfo
rasInfo
;
NativePrimitive
*
pPrim
;
CompositeInfo
compInfo
;
jint
ix1
,
iy1
,
ix2
,
iy2
;
if
((
dy1
==
0
&&
dx1
==
0
)
||
(
dy2
==
0
&&
dx2
==
0
))
{
return
;
}
/*
* Sort parallelogram by y values, ensure that each delta vector
* has a non-negative y delta.
*/
SORT_PGRAM
(
x0
,
y0
,
dx1
,
dy1
,
dx2
,
dy2
,
);
PGRAM_MIN_MAX
(
ix1
,
ix2
,
x0
,
dx1
,
dx2
,
JNI_TRUE
);
iy1
=
(
jint
)
floor
(
y0
);
iy2
=
(
jint
)
ceil
(
y0
+
dy1
+
dy2
);
pPrim
=
GetNativePrim
(
env
,
self
);
if
(
pPrim
==
NULL
)
{
return
;
}
if
(
pPrim
->
pCompType
->
getCompInfo
!=
NULL
)
{
(
*
pPrim
->
pCompType
->
getCompInfo
)(
env
,
&
compInfo
,
comp
);
}
sdOps
=
SurfaceData_GetOps
(
env
,
sData
);
if
(
sdOps
==
0
)
{
return
;
}
GrPrim_Sg2dGetClip
(
env
,
sg2d
,
&
rasInfo
.
bounds
);
SurfaceData_IntersectBoundsXYXY
(
&
rasInfo
.
bounds
,
ix1
,
iy1
,
ix2
,
iy2
);
if
(
rasInfo
.
bounds
.
y2
<=
rasInfo
.
bounds
.
y1
||
rasInfo
.
bounds
.
x2
<=
rasInfo
.
bounds
.
x1
)
{
return
;
}
if
(
sdOps
->
Lock
(
env
,
sdOps
,
&
rasInfo
,
pPrim
->
dstflags
)
!=
SD_SUCCESS
)
{
return
;
}
ix1
=
rasInfo
.
bounds
.
x1
;
iy1
=
rasInfo
.
bounds
.
y1
;
ix2
=
rasInfo
.
bounds
.
x2
;
iy2
=
rasInfo
.
bounds
.
y2
;
if
(
ix2
>
ix1
&&
iy2
>
iy1
)
{
jint
width
=
ix2
-
ix1
;
jint
color
=
GrPrim_Sg2dGetEaRGB
(
env
,
sg2d
);
unsigned
char
localmask
[
MASK_BUF_LEN
];
unsigned
char
*
pMask
=
((
width
>
MASK_BUF_LEN
)
?
malloc
(
width
)
:
localmask
);
sdOps
->
GetRasInfo
(
env
,
sdOps
,
&
rasInfo
);
if
(
rasInfo
.
rasBase
!=
NULL
&&
pMask
!=
NULL
)
{
void
*
pDst
=
PtrCoord
(
rasInfo
.
rasBase
,
ix1
,
rasInfo
.
pixelStride
,
iy1
,
rasInfo
.
scanStride
);
if
(
dy1
==
0
&&
dx2
==
0
)
{
if
(
dx1
<
0
)
{
// We sorted by Y above, but not by X
x0
+=
dx1
;
dx1
=
-
dx1
;
}
fillAARect
(
pPrim
,
&
rasInfo
,
&
compInfo
,
color
,
pMask
,
pDst
,
x0
,
y0
,
x0
+
dx1
,
y0
+
dy2
);
}
else
if
(
dx1
==
0
&&
dy2
==
0
)
{
if
(
dx2
<
0
)
{
// We sorted by Y above, but not by X
x0
+=
dx2
;
dx2
=
-
dx2
;
}
fillAARect
(
pPrim
,
&
rasInfo
,
&
compInfo
,
color
,
pMask
,
pDst
,
x0
,
y0
,
x0
+
dx2
,
y0
+
dy1
);
}
else
{
fillAAPgram
(
pPrim
,
&
rasInfo
,
&
compInfo
,
color
,
pMask
,
pDst
,
x0
,
y0
,
dx1
,
dy1
,
dx2
,
dy2
);
}
}
SurfaceData_InvokeRelease
(
env
,
sdOps
,
&
rasInfo
);
if
(
pMask
!=
NULL
&&
pMask
!=
localmask
)
{
free
(
pMask
);
}
}
SurfaceData_InvokeUnlock
(
env
,
sdOps
,
&
rasInfo
);
}
/* Main function to fill a double pair of (inner and outer) parallelograms */
static
void
drawAAPgram
(
NativePrimitive
*
pPrim
,
SurfaceDataRasInfo
*
pRasInfo
,
CompositeInfo
*
pCompInfo
,
jint
color
,
unsigned
char
*
pMask
,
void
*
pDst
,
jdouble
ox0
,
jdouble
oy0
,
jdouble
dx1
,
jdouble
dy1
,
jdouble
dx2
,
jdouble
dy2
,
jdouble
ldx1
,
jdouble
ldy1
,
jdouble
ldx2
,
jdouble
ldy2
)
{
jint
cx1
=
pRasInfo
->
bounds
.
x1
;
jint
cy1
=
pRasInfo
->
bounds
.
y1
;
jint
cx2
=
pRasInfo
->
bounds
.
x2
;
jint
cy2
=
pRasInfo
->
bounds
.
y2
;
jint
width
=
cx2
-
cx1
;
EdgeInfo
edges
[
8
];
jfloat
localaccum
[
MASK_BUF_LEN
+
1
];
jfloat
*
pAccum
;
if
(
!
storePgram
(
edges
+
0
,
edges
+
6
,
ox0
,
oy0
,
dx1
+
ldx1
,
dy1
+
ldy1
,
dx2
+
ldx2
,
dy2
+
ldy2
,
cx1
,
cy1
,
cx2
,
cy2
,
JNI_FALSE
))
{
/* If outer pgram does not contribute, then inner cannot either. */
return
;
}
storePgram
(
edges
+
2
,
edges
+
4
,
ox0
+
ldx1
+
ldx2
,
oy0
+
ldy1
+
ldy2
,
dx1
-
ldx1
,
dy1
-
ldy1
,
dx2
-
ldx2
,
dy2
-
ldy2
,
cx1
,
cy1
,
cx2
,
cy2
,
JNI_TRUE
);
pAccum
=
((
width
>
MASK_BUF_LEN
)
?
malloc
((
width
+
1
)
*
sizeof
(
jfloat
))
:
localaccum
);
if
(
pAccum
==
NULL
)
{
return
;
}
memset
(
pAccum
,
0
,
(
width
+
1
)
*
sizeof
(
jfloat
));
while
(
cy1
<
cy2
)
{
jint
lmin
,
lmax
,
rmin
,
rmax
;
jint
moff
,
x
;
jdouble
accum
;
unsigned
char
lastcov
;
lmin
=
rmin
=
width
+
2
;
lmax
=
rmax
=
0
;
ACCUM_EDGE
(
&
edges
[
0
],
pAccum
,
lmin
,
lmax
,
cx1
,
cy1
,
cx2
,
cy1
+
1
);
ACCUM_EDGE
(
&
edges
[
1
],
pAccum
,
lmin
,
lmax
,
cx1
,
cy1
,
cx2
,
cy1
+
1
);
ACCUM_EDGE
(
&
edges
[
2
],
pAccum
,
lmin
,
lmax
,
cx1
,
cy1
,
cx2
,
cy1
+
1
);
ACCUM_EDGE
(
&
edges
[
3
],
pAccum
,
lmin
,
lmax
,
cx1
,
cy1
,
cx2
,
cy1
+
1
);
ACCUM_EDGE
(
&
edges
[
4
],
pAccum
,
rmin
,
rmax
,
cx1
,
cy1
,
cx2
,
cy1
+
1
);
ACCUM_EDGE
(
&
edges
[
5
],
pAccum
,
rmin
,
rmax
,
cx1
,
cy1
,
cx2
,
cy1
+
1
);
ACCUM_EDGE
(
&
edges
[
6
],
pAccum
,
rmin
,
rmax
,
cx1
,
cy1
,
cx2
,
cy1
+
1
);
ACCUM_EDGE
(
&
edges
[
7
],
pAccum
,
rmin
,
rmax
,
cx1
,
cy1
,
cx2
,
cy1
+
1
);
if
(
lmax
>
width
)
{
lmax
=
width
;
/* Extra col has data we do not need. */
}
if
(
rmax
>
width
)
{
rmax
=
width
;
/* Extra col has data we do not need. */
}
/* If ranges overlap, handle both in the first pass. */
if
(
rmin
<=
lmax
)
{
lmax
=
rmax
;
}
x
=
lmin
;
accum
=
0
.
0
;
moff
=
0
;
lastcov
=
0
;
while
(
x
<
lmax
)
{
accum
+=
pAccum
[
x
];
pAccum
[
x
]
=
0
.
0
f
;
pMask
[
moff
++
]
=
lastcov
=
DblToMask
(
accum
);
x
++
;
}
/* Check for an empty or solidcenter section. */
if
(
lastcov
==
0
||
lastcov
==
0xFF
)
{
jint
endx
;
void
*
pRow
;
/* First process the existing partial coverage data. */
if
(
moff
>
0
)
{
pRow
=
PtrCoord
(
pDst
,
x
-
moff
,
pRasInfo
->
pixelStride
,
0
,
0
);
(
*
pPrim
->
funcs
.
maskfill
)(
pRow
,
pMask
,
0
,
0
,
moff
,
1
,
color
,
pRasInfo
,
pPrim
,
pCompInfo
);
moff
=
0
;
}
/* Where does the center section end? */
/* If there is no right AA edge in the accum buffer, then */
/* the right edge was beyond the clip, so fill out to width */
endx
=
(
rmin
<
rmax
)
?
rmin
:
width
;
if
(
x
<
endx
)
{
if
(
lastcov
==
0xFF
)
{
pRow
=
PtrCoord
(
pDst
,
x
,
pRasInfo
->
pixelStride
,
0
,
0
);
(
*
pPrim
->
funcs
.
maskfill
)(
pRow
,
NULL
,
0
,
0
,
endx
-
x
,
1
,
color
,
pRasInfo
,
pPrim
,
pCompInfo
);
}
x
=
endx
;
}
}
else
if
(
rmin
>=
rmax
)
{
/* We are not at 0 coverage, but there is no right edge, */
/* force a right edge so we process pixels out to width. */
rmax
=
width
;
}
/* The following loop will process the right AA edge and/or any */
/* partial coverage center section not processed above. */
while
(
x
<
rmax
)
{
accum
+=
pAccum
[
x
];
pAccum
[
x
]
=
0
.
0
f
;
pMask
[
moff
++
]
=
lastcov
=
DblToMask
(
accum
);
x
++
;
}
if
(
moff
>
0
)
{
void
*
pRow
=
PtrCoord
(
pDst
,
x
-
moff
,
pRasInfo
->
pixelStride
,
0
,
0
);
(
*
pPrim
->
funcs
.
maskfill
)(
pRow
,
pMask
,
0
,
0
,
moff
,
1
,
color
,
pRasInfo
,
pPrim
,
pCompInfo
);
}
if
(
lastcov
==
0xFF
&&
x
<
width
)
{
void
*
pRow
=
PtrCoord
(
pDst
,
x
,
pRasInfo
->
pixelStride
,
0
,
0
);
(
*
pPrim
->
funcs
.
maskfill
)(
pRow
,
NULL
,
0
,
0
,
width
-
x
,
1
,
color
,
pRasInfo
,
pPrim
,
pCompInfo
);
}
pDst
=
PtrAddBytes
(
pDst
,
pRasInfo
->
scanStride
);
cy1
++
;
}
if
(
pAccum
!=
localaccum
)
{
free
(
pAccum
);
}
}
/*
* Class: sun_java2d_loops_MaskFill
* Method: DrawAAPgram
* Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;Ljava/awt/Composite;DDDDDDDD)V
*/
JNIEXPORT
void
JNICALL
Java_sun_java2d_loops_MaskFill_DrawAAPgram
(
JNIEnv
*
env
,
jobject
self
,
jobject
sg2d
,
jobject
sData
,
jobject
comp
,
jdouble
x0
,
jdouble
y0
,
jdouble
dx1
,
jdouble
dy1
,
jdouble
dx2
,
jdouble
dy2
,
jdouble
lw1
,
jdouble
lw2
)
{
SurfaceDataOps
*
sdOps
;
SurfaceDataRasInfo
rasInfo
;
NativePrimitive
*
pPrim
;
CompositeInfo
compInfo
;
jint
ix1
,
iy1
,
ix2
,
iy2
;
jdouble
ldx1
,
ldy1
,
ldx2
,
ldy2
;
jdouble
ox0
,
oy0
;
if
((
dy1
==
0
&&
dx1
==
0
)
||
(
dy2
==
0
&&
dx2
==
0
))
{
return
;
}
/*
* Sort parallelogram by y values, ensure that each delta vector
* has a non-negative y delta.
*/
SORT_PGRAM
(
x0
,
y0
,
dx1
,
dy1
,
dx2
,
dy2
,
v
=
lw1
;
lw1
=
lw2
;
lw2
=
v
;);
// dx,dy for line width in the "1" and "2" directions.
ldx1
=
dx1
*
lw1
;
ldy1
=
dy1
*
lw1
;
ldx2
=
dx2
*
lw2
;
ldy2
=
dy2
*
lw2
;
// calculate origin of the outer parallelogram
ox0
=
x0
-
(
ldx1
+
ldx2
)
/
2
.
0
;
oy0
=
y0
-
(
ldy1
+
ldy2
)
/
2
.
0
;
if
(
lw1
>=
1
.
0
||
lw2
>=
1
.
0
)
{
/* Only need to fill an outer pgram if the interior no longer
* has a hole in it (i.e. if either of the line width ratios
* were greater than or equal to 1.0).
*/
Java_sun_java2d_loops_MaskFill_FillAAPgram
(
env
,
self
,
sg2d
,
sData
,
comp
,
ox0
,
oy0
,
dx1
+
ldx1
,
dy1
+
ldy1
,
dx2
+
ldx2
,
dy2
+
ldy2
);
return
;
}
PGRAM_MIN_MAX
(
ix1
,
ix2
,
ox0
,
dx1
+
ldx1
,
dx2
+
ldx2
,
JNI_TRUE
);
iy1
=
(
jint
)
floor
(
oy0
);
iy2
=
(
jint
)
ceil
(
oy0
+
dy1
+
ldy1
+
dy2
+
ldy2
);
pPrim
=
GetNativePrim
(
env
,
self
);
if
(
pPrim
==
NULL
)
{
return
;
}
if
(
pPrim
->
pCompType
->
getCompInfo
!=
NULL
)
{
(
*
pPrim
->
pCompType
->
getCompInfo
)(
env
,
&
compInfo
,
comp
);
}
sdOps
=
SurfaceData_GetOps
(
env
,
sData
);
if
(
sdOps
==
0
)
{
return
;
}
GrPrim_Sg2dGetClip
(
env
,
sg2d
,
&
rasInfo
.
bounds
);
SurfaceData_IntersectBoundsXYXY
(
&
rasInfo
.
bounds
,
ix1
,
iy1
,
ix2
,
iy2
);
if
(
rasInfo
.
bounds
.
y2
<=
rasInfo
.
bounds
.
y1
||
rasInfo
.
bounds
.
x2
<=
rasInfo
.
bounds
.
x1
)
{
return
;
}
if
(
sdOps
->
Lock
(
env
,
sdOps
,
&
rasInfo
,
pPrim
->
dstflags
)
!=
SD_SUCCESS
)
{
return
;
}
ix1
=
rasInfo
.
bounds
.
x1
;
iy1
=
rasInfo
.
bounds
.
y1
;
ix2
=
rasInfo
.
bounds
.
x2
;
iy2
=
rasInfo
.
bounds
.
y2
;
if
(
ix2
>
ix1
&&
iy2
>
iy1
)
{
jint
width
=
ix2
-
ix1
;
jint
color
=
GrPrim_Sg2dGetEaRGB
(
env
,
sg2d
);
unsigned
char
localmask
[
MASK_BUF_LEN
];
unsigned
char
*
pMask
=
((
width
>
MASK_BUF_LEN
)
?
malloc
(
width
)
:
localmask
);
sdOps
->
GetRasInfo
(
env
,
sdOps
,
&
rasInfo
);
if
(
rasInfo
.
rasBase
!=
NULL
&&
pMask
!=
NULL
)
{
void
*
pDst
=
PtrCoord
(
rasInfo
.
rasBase
,
ix1
,
rasInfo
.
pixelStride
,
iy1
,
rasInfo
.
scanStride
);
/*
* NOTE: aligned rects could probably be drawn
* even faster with a little work here.
* if (dy1 == 0 && dx2 == 0) {
* drawAARect(pPrim, &rasInfo, &compInfo,
* color, pMask, pDst,
* ox0, oy0, ox0+dx1+ldx1, oy0+dy2+ldy2, ldx1, ldy2);
* } else if (dx1 == 0 && dy2 == 0) {
* drawAARect(pPrim, &rasInfo, &compInfo,
* color, pMask, pDst,
* ox0, oy0, ox0+dx2+ldx2, oy0+dy1+ldy1, ldx2, ldy1);
* } else {
*/
drawAAPgram
(
pPrim
,
&
rasInfo
,
&
compInfo
,
color
,
pMask
,
pDst
,
ox0
,
oy0
,
dx1
,
dy1
,
dx2
,
dy2
,
ldx1
,
ldy1
,
ldx2
,
ldy2
);
/*
* }
*/
}
SurfaceData_InvokeRelease
(
env
,
sdOps
,
&
rasInfo
);
if
(
pMask
!=
NULL
&&
pMask
!=
localmask
)
{
free
(
pMask
);
}
}
SurfaceData_InvokeUnlock
(
env
,
sdOps
,
&
rasInfo
);
}
src/share/native/sun/java2d/loops/ParallelogramUtils.h
0 → 100644
浏览文件 @
beff7858
/*
* Copyright (c) 2008, 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.
*/
#ifndef ParallelogramUtils_h_Included
#define ParallelogramUtils_h_Included
#ifdef __cplusplus
extern
"C"
{
#endif
#define PGRAM_MIN_MAX(bmin, bmax, v0, dv1, dv2, AA) \
do { \
double vmin, vmax; \
if (dv1 < 0) { \
vmin = v0+dv1; \
vmax = v0; \
} else { \
vmin = v0; \
vmax = v0+dv1; \
} \
if (dv2 < 0) { \
vmin += dv2; \
} else { \
vmax += dv2; \
} \
if (AA) { \
bmin = (jint) floor(vmin); \
bmax = (jint) ceil(vmax); \
} else { \
bmin = (jint) floor(vmin + 0.5); \
bmax = (jint) floor(vmax + 0.5); \
} \
} while(0)
#define PGRAM_INIT_X(starty, x, y, slope) \
(DblToLong((x) + (slope) * ((starty)+0.5 - (y))) + LongOneHalf - 1)
/*
* Sort parallelogram by y values, ensure that each delta vector
* has a non-negative y delta.
*/
#define SORT_PGRAM(x0, y0, dx1, dy1, dx2, dy2, OTHER_SWAP_CODE) \
do { \
if (dy1 < 0) { \
x0 += dx1; y0 += dy1; \
dx1 = -dx1; dy1 = -dy1; \
} \
if (dy2 < 0) { \
x0 += dx2; y0 += dy2; \
dx2 = -dx2; dy2 = -dy2; \
} \
/* Sort delta vectors so dxy1 is left of dxy2. */
\
if (dx1 * dy2 > dx2 * dy1) { \
double v; \
v = dx1; dx1 = dx2; dx2 = v; \
v = dy1; dy1 = dy2; dy2 = v; \
OTHER_SWAP_CODE \
} \
} while(0)
#endif
/* ParallelogramUtils_h_Included */
src/solaris/native/sun/java2d/loops/vis_IntArgbPre_Mask.c
浏览文件 @
beff7858
...
...
@@ -517,13 +517,15 @@ void ADD_SUFF(IntArgbPreSrcMaskFill)(void *rasBase,
ADD_SUFF
(
AnyIntSetRect
)(
pRasInfo
,
0
,
0
,
width
,
height
,
fgColor
,
pPrim
,
pCompInfo
);
#else
void
*
pBase
=
pRasInfo
->
rasBase
;
pRasInfo
->
rasBase
=
rasBase
;
if
(
cnstA
!=
0xff
)
{
fgColor
=
(
cnstA
<<
24
)
|
(
cnstR
<<
16
)
|
(
cnstG
<<
8
)
|
cnstB
;
}
ADD_SUFF
(
AnyIntSetRect
)(
pRasInfo
,
pRasInfo
->
bounds
.
x1
,
pRasInfo
->
bounds
.
y1
,
pRasInfo
->
bounds
.
x2
,
pRasInfo
->
bounds
.
y2
,
0
,
0
,
width
,
height
,
fgColor
,
pPrim
,
pCompInfo
);
pRasInfo
->
rasBase
=
pBase
;
#endif
return
;
}
...
...
@@ -582,11 +584,13 @@ void ADD_SUFF(FourByteAbgrPreSrcMaskFill)(void *rasBase,
}
if
(
pMask
==
NULL
)
{
void
*
pBase
=
pRasInfo
->
rasBase
;
pRasInfo
->
rasBase
=
rasBase
;
fgColor
=
(
cnstR
<<
24
)
|
(
cnstG
<<
16
)
|
(
cnstB
<<
8
)
|
cnstA
;
ADD_SUFF
(
Any4ByteSetRect
)(
pRasInfo
,
pRasInfo
->
bounds
.
x1
,
pRasInfo
->
bounds
.
y1
,
pRasInfo
->
bounds
.
x2
,
pRasInfo
->
bounds
.
y2
,
0
,
0
,
width
,
height
,
fgColor
,
pPrim
,
pCompInfo
);
pRasInfo
->
rasBase
=
pBase
;
return
;
}
...
...
src/solaris/native/sun/java2d/loops/vis_SrcMaskFill.c
浏览文件 @
beff7858
...
...
@@ -150,10 +150,12 @@ void ADD_SUFF(IntArgbSrcMaskFill)(void *rasBase,
}
if
(
pMask
==
NULL
)
{
void
*
pBase
=
pRasInfo
->
rasBase
;
pRasInfo
->
rasBase
=
rasBase
;
ADD_SUFF
(
AnyIntSetRect
)(
pRasInfo
,
pRasInfo
->
bounds
.
x1
,
pRasInfo
->
bounds
.
y1
,
pRasInfo
->
bounds
.
x2
,
pRasInfo
->
bounds
.
y2
,
0
,
0
,
width
,
height
,
fgColor
,
pPrim
,
pCompInfo
);
pRasInfo
->
rasBase
=
pBase
;
return
;
}
...
...
@@ -214,15 +216,17 @@ void ADD_SUFF(FourByteAbgrSrcMaskFill)(void *rasBase,
cnstB
=
(
fgColor
)
&
0xff
;
if
(
pMask
==
NULL
)
{
void
*
pBase
=
pRasInfo
->
rasBase
;
pRasInfo
->
rasBase
=
rasBase
;
if
(
cnstA
==
0
)
{
fgColor
=
0
;
}
else
{
fgColor
=
(
fgColor
<<
8
)
|
cnstA
;
}
ADD_SUFF
(
Any4ByteSetRect
)(
pRasInfo
,
pRasInfo
->
bounds
.
x1
,
pRasInfo
->
bounds
.
y1
,
pRasInfo
->
bounds
.
x2
,
pRasInfo
->
bounds
.
y2
,
0
,
0
,
width
,
height
,
fgColor
,
pPrim
,
pCompInfo
);
pRasInfo
->
rasBase
=
pBase
;
return
;
}
...
...
@@ -390,10 +394,12 @@ void ADD_SUFF(IntRgbSrcMaskFill)(void *rasBase,
if
(
cnstA
==
0
)
fgColor
=
0
;
if
(
pMask
==
NULL
)
{
void
*
pBase
=
pRasInfo
->
rasBase
;
pRasInfo
->
rasBase
=
rasBase
;
ADD_SUFF
(
AnyIntSetRect
)(
pRasInfo
,
pRasInfo
->
bounds
.
x1
,
pRasInfo
->
bounds
.
y1
,
pRasInfo
->
bounds
.
x2
,
pRasInfo
->
bounds
.
y2
,
0
,
0
,
width
,
height
,
fgColor
,
pPrim
,
pCompInfo
);
pRasInfo
->
rasBase
=
pBase
;
return
;
}
...
...
@@ -458,10 +464,12 @@ void ADD_SUFF(IntBgrSrcMaskFill)(void *rasBase,
}
if
(
pMask
==
NULL
)
{
void
*
pBase
=
pRasInfo
->
rasBase
;
pRasInfo
->
rasBase
=
rasBase
;
ADD_SUFF
(
AnyIntSetRect
)(
pRasInfo
,
pRasInfo
->
bounds
.
x1
,
pRasInfo
->
bounds
.
y1
,
pRasInfo
->
bounds
.
x2
,
pRasInfo
->
bounds
.
y2
,
0
,
0
,
width
,
height
,
fgColor
,
pPrim
,
pCompInfo
);
pRasInfo
->
rasBase
=
pBase
;
return
;
}
...
...
@@ -526,10 +534,12 @@ void ADD_SUFF(ThreeByteBgrSrcMaskFill)(void *rasBase,
}
if
(
pMask
==
NULL
)
{
void
*
pBase
=
pRasInfo
->
rasBase
;
pRasInfo
->
rasBase
=
rasBase
;
ADD_SUFF
(
Any3ByteSetRect
)(
pRasInfo
,
pRasInfo
->
bounds
.
x1
,
pRasInfo
->
bounds
.
y1
,
pRasInfo
->
bounds
.
x2
,
pRasInfo
->
bounds
.
y2
,
0
,
0
,
width
,
height
,
fgColor
,
pPrim
,
pCompInfo
);
pRasInfo
->
rasBase
=
pBase
;
return
;
}
...
...
test/java/awt/Graphics2D/RenderClipTest/6766342.tests
0 → 100644
浏览文件 @
beff7858
Filled AA Pure Rect(5, 29.4, 10, 10)
Stroked AA Pure Rect(5, 4.4, 10, 10)
Stroked AA Line(20, 20, -10, 20)
test/java/awt/Graphics2D/RenderClipTest/RenderClipTest.java
0 → 100644
浏览文件 @
beff7858
/*
* Copyright (c) 2008, 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.
*/
/*
* @test
* @bug 6766342
* @summary Tests clipping invariance for AA rectangle and line primitives
* @run main RenderClipTest -strict -readfile 6766342.tests
* @run main RenderClipTest -rectsuite -count 10
*/
import
java.awt.*
;
import
java.awt.geom.*
;
import
java.awt.image.*
;
import
java.awt.event.*
;
import
java.util.Vector
;
import
java.io.*
;
public
class
RenderClipTest
{
public
static
double
randDblCoord
()
{
return
Math
.
random
()*
60
-
10
;
}
public
static
float
randFltCoord
()
{
return
(
float
)
randDblCoord
();
}
public
static
int
randIntCoord
()
{
return
(
int
)
Math
.
round
(
randDblCoord
());
}
public
static
int
randInt
(
int
n
)
{
return
((
int
)
(
Math
.
random
()
*
(
n
*
4
)))
>>
2
;
}
static
int
numtests
;
static
int
numerrors
;
static
int
numfillfailures
;
static
int
numstrokefailures
;
static
int
maxerr
;
static
boolean
useAA
;
static
boolean
strokePure
;
static
boolean
testFill
;
static
boolean
testDraw
;
static
boolean
silent
;
static
boolean
verbose
;
static
boolean
strict
;
static
boolean
showErrors
;
static
float
lw
;
static
double
rot
;
static
BufferedImage
imgref
;
static
BufferedImage
imgtst
;
static
Graphics2D
grefclear
;
static
Graphics2D
gtstclear
;
static
Graphics2D
grefrender
;
static
Graphics2D
gtstrender
;
public
static
abstract
class
AnnotatedRenderOp
{
public
static
AnnotatedRenderOp
parse
(
String
str
)
{
AnnotatedRenderOp
ar
;
if
(((
ar
=
Cubic
.
tryparse
(
str
))
!=
null
)
||
((
ar
=
Quad
.
tryparse
(
str
))
!=
null
)
||
((
ar
=
Poly
.
tryparse
(
str
))
!=
null
)
||
((
ar
=
Path
.
tryparse
(
str
))
!=
null
)
||
((
ar
=
Rect
.
tryparse
(
str
))
!=
null
)
||
((
ar
=
Line
.
tryparse
(
str
))
!=
null
)
||
((
ar
=
RectMethod
.
tryparse
(
str
))
!=
null
)
||
((
ar
=
LineMethod
.
tryparse
(
str
))
!=
null
))
{
return
ar
;
}
System
.
err
.
println
(
"Unable to parse shape: "
+
str
);
return
null
;
}
public
abstract
void
randomize
();
public
abstract
void
fill
(
Graphics2D
g2d
);
public
abstract
void
draw
(
Graphics2D
g2d
);
}
public
static
abstract
class
AnnotatedShapeOp
extends
AnnotatedRenderOp
{
public
abstract
Shape
getShape
();
public
void
fill
(
Graphics2D
g2d
)
{
g2d
.
fill
(
getShape
());
}
public
void
draw
(
Graphics2D
g2d
)
{
g2d
.
draw
(
getShape
());
}
}
public
static
void
usage
(
String
err
)
{
if
(
err
!=
null
)
{
System
.
err
.
println
(
err
);
}
System
.
err
.
println
(
"usage: java RenderClipTest "
+
"[-read[file F]] [-rectsuite] [-fill] [-draw]"
);
System
.
err
.
println
(
" "
+
"[-aa] [-pure] [-lw N] [-rot N]"
);
System
.
err
.
println
(
" "
+
"[-rectmethod] [-linemethod] [-rect] [-line]"
);
System
.
err
.
println
(
" "
+
"[-cubic] [-quad] [-poly] [-path]"
);
System
.
err
.
println
(
" "
+
"[-silent] [-verbose] [-showerr] [-count N]"
);
System
.
err
.
println
(
" "
+
"[-strict] [-usage]"
);
System
.
err
.
println
(
" -read Read test data from stdin"
);
System
.
err
.
println
(
" -readfile F Read test data from file F"
);
System
.
err
.
println
(
" -rectsuite Run a suite of rect/line tests"
);
System
.
err
.
println
(
" -fill Test g.fill*(...)"
);
System
.
err
.
println
(
" -draw Test g.draw*(...)"
);
System
.
err
.
println
(
" -aa Use antialiased rendering"
);
System
.
err
.
println
(
" -pure Use STROKE_PURE hint"
);
System
.
err
.
println
(
" -lw N Test line widths of N "
+
"(default 1.0)"
);
System
.
err
.
println
(
" -rot N Test rotation by N degrees "
+
"(default 0.0)"
);
System
.
err
.
println
(
" -rectmethod Test fillRect/drawRect methods"
);
System
.
err
.
println
(
" -linemethod Test drawLine method"
);
System
.
err
.
println
(
" -rect Test Rectangle2D shapes"
);
System
.
err
.
println
(
" -line Test Line2D shapes"
);
System
.
err
.
println
(
" -cubic Test CubicCurve2D shapes"
);
System
.
err
.
println
(
" -quad Test QuadCurve2D shapes"
);
System
.
err
.
println
(
" -poly Test Polygon shapes"
);
System
.
err
.
println
(
" -path Test GeneralPath shapes"
);
System
.
err
.
println
(
" -silent Do not print out error curves"
);
System
.
err
.
println
(
" -verbose Print out progress info"
);
System
.
err
.
println
(
" -showerr Display errors on screen"
);
System
.
err
.
println
(
" -count N N tests per shape, then exit "
+
"(default 1000)"
);
System
.
err
.
println
(
" -strict All failures are important"
);
System
.
err
.
println
(
" -usage Print this help, then exit"
);
System
.
exit
((
err
!=
null
)
?
-
1
:
0
);
}
public
static
void
main
(
String
argv
[])
{
boolean
readTests
=
false
;
String
readFile
=
null
;
boolean
rectsuite
=
false
;
int
count
=
1000
;
lw
=
1.0f
;
rot
=
0.0
;
Vector
<
AnnotatedRenderOp
>
testOps
=
new
Vector
<
AnnotatedRenderOp
>();
for
(
int
i
=
0
;
i
<
argv
.
length
;
i
++)
{
String
arg
=
argv
[
i
].
toLowerCase
();
if
(
arg
.
equals
(
"-aa"
))
{
useAA
=
true
;
}
else
if
(
arg
.
equals
(
"-pure"
))
{
strokePure
=
true
;
}
else
if
(
arg
.
equals
(
"-fill"
))
{
testFill
=
true
;
}
else
if
(
arg
.
equals
(
"-draw"
))
{
testDraw
=
true
;
}
else
if
(
arg
.
equals
(
"-lw"
))
{
if
(
i
+
1
>=
argv
.
length
)
{
usage
(
"Missing argument: "
+
argv
[
i
]);
}
lw
=
Float
.
parseFloat
(
argv
[++
i
]);
}
else
if
(
arg
.
equals
(
"-rot"
))
{
if
(
i
+
1
>=
argv
.
length
)
{
usage
(
"Missing argument: "
+
argv
[
i
]);
}
rot
=
Double
.
parseDouble
(
argv
[++
i
]);
}
else
if
(
arg
.
equals
(
"-cubic"
))
{
testOps
.
add
(
new
Cubic
());
}
else
if
(
arg
.
equals
(
"-quad"
))
{
testOps
.
add
(
new
Quad
());
}
else
if
(
arg
.
equals
(
"-poly"
))
{
testOps
.
add
(
new
Poly
());
}
else
if
(
arg
.
equals
(
"-path"
))
{
testOps
.
add
(
new
Path
());
}
else
if
(
arg
.
equals
(
"-rect"
))
{
testOps
.
add
(
new
Rect
());
}
else
if
(
arg
.
equals
(
"-line"
))
{
testOps
.
add
(
new
Line
());
}
else
if
(
arg
.
equals
(
"-rectmethod"
))
{
testOps
.
add
(
new
RectMethod
());
}
else
if
(
arg
.
equals
(
"-linemethod"
))
{
testOps
.
add
(
new
LineMethod
());
}
else
if
(
arg
.
equals
(
"-verbose"
))
{
verbose
=
true
;
}
else
if
(
arg
.
equals
(
"-strict"
))
{
strict
=
true
;
}
else
if
(
arg
.
equals
(
"-silent"
))
{
silent
=
true
;
}
else
if
(
arg
.
equals
(
"-showerr"
))
{
showErrors
=
true
;
}
else
if
(
arg
.
equals
(
"-readfile"
))
{
if
(
i
+
1
>=
argv
.
length
)
{
usage
(
"Missing argument: "
+
argv
[
i
]);
}
readTests
=
true
;
readFile
=
argv
[++
i
];
}
else
if
(
arg
.
equals
(
"-read"
))
{
readTests
=
true
;
readFile
=
null
;
}
else
if
(
arg
.
equals
(
"-rectsuite"
))
{
rectsuite
=
true
;
}
else
if
(
arg
.
equals
(
"-count"
))
{
if
(
i
+
1
>=
argv
.
length
)
{
usage
(
"Missing argument: "
+
argv
[
i
]);
}
count
=
Integer
.
parseInt
(
argv
[++
i
]);
}
else
if
(
arg
.
equals
(
"-usage"
))
{
usage
(
null
);
}
else
{
usage
(
"Unknown argument: "
+
argv
[
i
]);
}
}
if
(
readTests
)
{
if
(
rectsuite
||
testDraw
||
testFill
||
useAA
||
strokePure
||
lw
!=
1.0f
||
rot
!=
0.0
||
testOps
.
size
()
>
0
)
{
usage
(
"Should not specify test types with -read options"
);
}
}
else
if
(
rectsuite
)
{
if
(
testDraw
||
testFill
||
useAA
||
strokePure
||
lw
!=
1.0f
||
rot
!=
0.0
||
testOps
.
size
()
>
0
)
{
usage
(
"Should not specify test types with -rectsuite option"
);
}
}
else
{
if
(!
testDraw
&&
!
testFill
)
{
usage
(
"No work: Must specify one or both of "
+
"-fill or -draw"
);
}
if
(
testOps
.
size
()
==
0
)
{
usage
(
"No work: Must specify one or more of "
+
"-rect[method], -line[method], "
+
"-cubic, -quad, -poly, or -path"
);
}
}
initImages
();
if
(
readTests
)
{
try
{
InputStream
is
;
if
(
readFile
==
null
)
{
is
=
System
.
in
;
}
else
{
File
f
=
new
File
(
System
.
getProperty
(
"test.src"
,
"."
),
readFile
);
is
=
new
FileInputStream
(
f
);
}
parseAndRun
(
is
);
}
catch
(
IOException
e
)
{
throw
new
RuntimeException
(
e
);
}
}
else
if
(
rectsuite
)
{
runRectSuite
(
count
);
}
else
{
initGCs
();
for
(
int
k
=
0
;
k
<
testOps
.
size
();
k
++)
{
AnnotatedRenderOp
ar
=
testOps
.
get
(
k
);
runRandomTests
(
ar
,
count
);
}
disposeGCs
();
}
grefclear
.
dispose
();
gtstclear
.
dispose
();
grefclear
=
gtstclear
=
null
;
reportStatistics
();
}
public
static
int
reportStatistics
()
{
String
connector
=
""
;
if
(
numfillfailures
>
0
)
{
System
.
out
.
print
(
numfillfailures
+
" fills "
);
connector
=
"and "
;
}
if
(
numstrokefailures
>
0
)
{
System
.
out
.
print
(
connector
+
numstrokefailures
+
" strokes "
);
}
int
totalfailures
=
numfillfailures
+
numstrokefailures
;
if
(
totalfailures
==
0
)
{
System
.
out
.
print
(
"0 "
);
}
System
.
out
.
println
(
"out of "
+
numtests
+
" tests failed..."
);
int
critical
=
numerrors
;
if
(
strict
)
{
critical
+=
totalfailures
;
}
if
(
critical
>
0
)
{
throw
new
RuntimeException
(
critical
+
" tests had critical errors"
);
}
System
.
out
.
println
(
"No tests had critical errors"
);
return
(
numerrors
+
totalfailures
);
}
public
static
void
runRectSuite
(
int
count
)
{
AnnotatedRenderOp
ops
[]
=
{
new
Rect
(),
new
RectMethod
(),
new
Line
(),
new
LineMethod
(),
};
// Sometimes different fill algorithms are chosen for
// thin and wide line modes, make sure we test both...
float
filllinewidths
[]
=
{
0.0f
,
2.0f
};
float
drawlinewidths
[]
=
{
0.0f
,
0.5f
,
1.0f
,
2.0f
,
2.5f
,
5.0f
,
5.3f
};
double
rotations
[]
=
{
0.0
,
15.0
,
90.0
,
135.0
,
180.0
,
200.0
,
270.0
,
300.0
};
for
(
AnnotatedRenderOp
ar:
ops
)
{
for
(
double
r:
rotations
)
{
rot
=
r
;
for
(
int
i
=
0
;
i
<
8
;
i
++)
{
float
linewidths
[];
if
((
i
&
1
)
==
0
)
{
if
((
ar
instanceof
Line
)
||
(
ar
instanceof
LineMethod
))
{
continue
;
}
testFill
=
true
;
testDraw
=
false
;
linewidths
=
filllinewidths
;
}
else
{
testFill
=
false
;
testDraw
=
true
;
linewidths
=
drawlinewidths
;
}
useAA
=
((
i
&
2
)
!=
0
);
strokePure
=
((
i
&
4
)
!=
0
);
for
(
float
w
:
linewidths
)
{
lw
=
w
;
runSuiteTests
(
ar
,
count
);
}
}
}
}
}
public
static
void
runSuiteTests
(
AnnotatedRenderOp
ar
,
int
count
)
{
if
(
verbose
)
{
System
.
out
.
print
(
"Running "
);
System
.
out
.
print
(
testFill
?
"Fill "
:
"Draw "
);
System
.
out
.
print
(
BaseName
(
ar
));
if
(
useAA
)
{
System
.
out
.
print
(
" AA"
);
}
if
(
strokePure
)
{
System
.
out
.
print
(
" Pure"
);
}
if
(
lw
!=
1.0f
)
{
System
.
out
.
print
(
" lw="
+
lw
);
}
if
(
rot
!=
0.0f
)
{
System
.
out
.
print
(
" rot="
+
rot
);
}
System
.
out
.
println
();
}
initGCs
();
runRandomTests
(
ar
,
count
);
disposeGCs
();
}
public
static
String
BaseName
(
AnnotatedRenderOp
ar
)
{
String
s
=
ar
.
toString
();
int
leftparen
=
s
.
indexOf
(
'('
);
if
(
leftparen
>=
0
)
{
s
=
s
.
substring
(
0
,
leftparen
);
}
return
s
;
}
public
static
void
runRandomTests
(
AnnotatedRenderOp
ar
,
int
count
)
{
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
ar
.
randomize
();
if
(
testDraw
)
{
test
(
ar
,
false
);
}
if
(
testFill
)
{
test
(
ar
,
true
);
}
}
}
public
static
void
initImages
()
{
imgref
=
new
BufferedImage
(
40
,
40
,
BufferedImage
.
TYPE_INT_RGB
);
imgtst
=
new
BufferedImage
(
40
,
40
,
BufferedImage
.
TYPE_INT_RGB
);
grefclear
=
imgref
.
createGraphics
();
gtstclear
=
imgtst
.
createGraphics
();
grefclear
.
setColor
(
Color
.
white
);
gtstclear
.
setColor
(
Color
.
white
);
}
public
static
void
initGCs
()
{
grefrender
=
imgref
.
createGraphics
();
gtstrender
=
imgtst
.
createGraphics
();
gtstrender
.
clipRect
(
10
,
10
,
20
,
20
);
grefrender
.
setColor
(
Color
.
blue
);
gtstrender
.
setColor
(
Color
.
blue
);
if
(
lw
!=
1.0f
)
{
BasicStroke
bs
=
new
BasicStroke
(
lw
);
grefrender
.
setStroke
(
bs
);
gtstrender
.
setStroke
(
bs
);
}
if
(
rot
!=
0.0
)
{
double
rotrad
=
Math
.
toRadians
(
rot
);
grefrender
.
rotate
(
rotrad
,
20
,
20
);
gtstrender
.
rotate
(
rotrad
,
20
,
20
);
}
if
(
strokePure
)
{
grefrender
.
setRenderingHint
(
RenderingHints
.
KEY_STROKE_CONTROL
,
RenderingHints
.
VALUE_STROKE_PURE
);
gtstrender
.
setRenderingHint
(
RenderingHints
.
KEY_STROKE_CONTROL
,
RenderingHints
.
VALUE_STROKE_PURE
);
}
if
(
useAA
)
{
grefrender
.
setRenderingHint
(
RenderingHints
.
KEY_ANTIALIASING
,
RenderingHints
.
VALUE_ANTIALIAS_ON
);
gtstrender
.
setRenderingHint
(
RenderingHints
.
KEY_ANTIALIASING
,
RenderingHints
.
VALUE_ANTIALIAS_ON
);
maxerr
=
1
;
}
}
public
static
void
disposeGCs
()
{
grefrender
.
dispose
();
gtstrender
.
dispose
();
grefrender
=
gtstrender
=
null
;
}
public
static
void
parseAndRun
(
InputStream
in
)
throws
IOException
{
BufferedReader
br
=
new
BufferedReader
(
new
InputStreamReader
(
in
));
String
str
;
while
((
str
=
br
.
readLine
())
!=
null
)
{
if
(
str
.
startsWith
(
"Stroked "
)
||
str
.
startsWith
(
"Filled "
))
{
parseTest
(
str
);
continue
;
}
if
(
str
.
startsWith
(
"Running "
))
{
continue
;
}
if
(
str
.
startsWith
(
"Failed: "
))
{
continue
;
}
if
(
str
.
indexOf
(
" out of "
)
>
0
&&
str
.
indexOf
(
" tests failed..."
)
>
0
)
{
continue
;
}
if
(
str
.
indexOf
(
" tests had critical errors"
)
>
0
)
{
continue
;
}
System
.
err
.
println
(
"Unparseable line: "
+
str
);
}
}
public
static
void
parseTest
(
String
origstr
)
{
String
str
=
origstr
;
boolean
isfill
=
false
;
useAA
=
strokePure
=
false
;
lw
=
1.0f
;
rot
=
0.0
;
if
(
str
.
startsWith
(
"Stroked "
))
{
str
=
str
.
substring
(
8
);
isfill
=
false
;
}
else
if
(
str
.
startsWith
(
"Filled "
))
{
str
=
str
.
substring
(
7
);
isfill
=
true
;
}
else
{
System
.
err
.
println
(
"Unparseable test line: "
+
origstr
);
}
if
(
str
.
startsWith
(
"AA "
))
{
str
=
str
.
substring
(
3
);
useAA
=
true
;
}
if
(
str
.
startsWith
(
"Pure "
))
{
str
=
str
.
substring
(
5
);
strokePure
=
true
;
}
if
(
str
.
startsWith
(
"Lw="
))
{
int
index
=
str
.
indexOf
(
' '
,
3
);
if
(
index
>
0
)
{
lw
=
Float
.
parseFloat
(
str
.
substring
(
3
,
index
));
str
=
str
.
substring
(
index
+
1
);
}
}
if
(
str
.
startsWith
(
"Rot="
))
{
int
index
=
str
.
indexOf
(
' '
,
4
);
if
(
index
>
0
)
{
rot
=
Double
.
parseDouble
(
str
.
substring
(
4
,
index
));
str
=
str
.
substring
(
index
+
1
);
}
}
AnnotatedRenderOp
ar
=
AnnotatedRenderOp
.
parse
(
str
);
if
(
ar
!=
null
)
{
initGCs
();
test
(
ar
,
isfill
);
disposeGCs
();
}
else
{
System
.
err
.
println
(
"Unparseable test line: "
+
origstr
);
}
}
public
static
void
test
(
AnnotatedRenderOp
ar
,
boolean
isfill
)
{
grefclear
.
fillRect
(
0
,
0
,
40
,
40
);
gtstclear
.
fillRect
(
0
,
0
,
40
,
40
);
if
(
isfill
)
{
ar
.
fill
(
grefrender
);
ar
.
fill
(
gtstrender
);
}
else
{
ar
.
draw
(
grefrender
);
ar
.
draw
(
gtstrender
);
}
check
(
imgref
,
imgtst
,
ar
,
isfill
);
}
public
static
int
[]
getData
(
BufferedImage
img
)
{
Raster
r
=
img
.
getRaster
();
DataBufferInt
dbi
=
(
DataBufferInt
)
r
.
getDataBuffer
();
return
dbi
.
getData
();
}
public
static
int
getScan
(
BufferedImage
img
)
{
Raster
r
=
img
.
getRaster
();
SinglePixelPackedSampleModel
sppsm
=
(
SinglePixelPackedSampleModel
)
r
.
getSampleModel
();
return
sppsm
.
getScanlineStride
();
}
public
static
int
getOffset
(
BufferedImage
img
)
{
Raster
r
=
img
.
getRaster
();
SinglePixelPackedSampleModel
sppsm
=
(
SinglePixelPackedSampleModel
)
r
.
getSampleModel
();
return
sppsm
.
getOffset
(-
r
.
getSampleModelTranslateX
(),
-
r
.
getSampleModelTranslateY
());
}
final
static
int
opaque
=
0xff000000
;
final
static
int
whitergb
=
Color
.
white
.
getRGB
();
public
static
final
int
maxdiff
(
int
rgb1
,
int
rgb2
)
{
int
maxd
=
0
;
for
(
int
i
=
0
;
i
<
32
;
i
+=
8
)
{
int
c1
=
(
rgb1
>>
i
)
&
0xff
;
int
c2
=
(
rgb2
>>
i
)
&
0xff
;
int
d
=
Math
.
abs
(
c1
-
c2
);
if
(
maxd
<
d
)
{
maxd
=
d
;
}
}
return
maxd
;
}
public
static
void
check
(
BufferedImage
imgref
,
BufferedImage
imgtst
,
AnnotatedRenderOp
ar
,
boolean
wasfill
)
{
numtests
++;
int
dataref
[]
=
getData
(
imgref
);
int
datatst
[]
=
getData
(
imgtst
);
int
scanref
=
getScan
(
imgref
);
int
scantst
=
getScan
(
imgtst
);
int
offref
=
getOffset
(
imgref
);
int
offtst
=
getOffset
(
imgtst
);
// We want to check for errors outside the clip at a higher
// priority than errors involving different pixels touched
// inside the clip.
// Check above clip
if
(
check
(
ar
,
wasfill
,
null
,
0
,
0
,
datatst
,
scantst
,
offtst
,
0
,
0
,
40
,
10
))
{
return
;
}
// Check below clip
if
(
check
(
ar
,
wasfill
,
null
,
0
,
0
,
datatst
,
scantst
,
offtst
,
0
,
30
,
40
,
40
))
{
return
;
}
// Check left of clip
if
(
check
(
ar
,
wasfill
,
null
,
0
,
0
,
datatst
,
scantst
,
offtst
,
0
,
10
,
10
,
30
))
{
return
;
}
// Check right of clip
if
(
check
(
ar
,
wasfill
,
null
,
0
,
0
,
datatst
,
scantst
,
offtst
,
30
,
10
,
40
,
30
))
{
return
;
}
// Check inside clip
check
(
ar
,
wasfill
,
dataref
,
scanref
,
offref
,
datatst
,
scantst
,
offtst
,
10
,
10
,
30
,
30
);
}
public
static
boolean
check
(
AnnotatedRenderOp
ar
,
boolean
wasfill
,
int
dataref
[],
int
scanref
,
int
offref
,
int
datatst
[],
int
scantst
,
int
offtst
,
int
x0
,
int
y0
,
int
x1
,
int
y1
)
{
offref
+=
scanref
*
y0
;
offtst
+=
scantst
*
y0
;
for
(
int
y
=
y0
;
y
<
y1
;
y
++)
{
for
(
int
x
=
x0
;
x
<
x1
;
x
++)
{
boolean
failed
;
String
reason
;
int
rgbref
;
int
rgbtst
;
rgbtst
=
datatst
[
offtst
+
x
]
|
opaque
;
if
(
dataref
==
null
)
{
/* Outside of clip, must be white, no error tolerance */
rgbref
=
whitergb
;
failed
=
(
rgbtst
!=
rgbref
);
reason
=
"stray pixel rendered outside of clip"
;
}
else
{
/* Inside of clip, check for maxerr delta in components */
rgbref
=
dataref
[
offref
+
x
]
|
opaque
;
failed
=
(
rgbref
!=
rgbtst
&&
maxdiff
(
rgbref
,
rgbtst
)
>
maxerr
);
reason
=
"different pixel rendered inside clip"
;
}
if
(
failed
)
{
if
(
dataref
==
null
)
{
numerrors
++;
}
if
(
wasfill
)
{
numfillfailures
++;
}
else
{
numstrokefailures
++;
}
if
(!
silent
)
{
System
.
out
.
println
(
"Failed: "
+
reason
+
" at "
+
x
+
", "
+
y
+
" ["
+
Integer
.
toHexString
(
rgbref
)+
" != "
+
Integer
.
toHexString
(
rgbtst
)+
"]"
);
System
.
out
.
print
(
wasfill
?
"Filled "
:
"Stroked "
);
if
(
useAA
)
System
.
out
.
print
(
"AA "
);
if
(
strokePure
)
System
.
out
.
print
(
"Pure "
);
if
(
lw
!=
1
)
System
.
out
.
print
(
"Lw="
+
lw
+
" "
);
if
(
rot
!=
0
)
System
.
out
.
print
(
"Rot="
+
rot
+
" "
);
System
.
out
.
println
(
ar
);
}
if
(
showErrors
)
{
show
(
imgref
,
imgtst
);
}
return
true
;
}
}
offref
+=
scanref
;
offtst
+=
scantst
;
}
return
false
;
}
static
ErrorWindow
errw
;
public
static
void
show
(
BufferedImage
imgref
,
BufferedImage
imgtst
)
{
ErrorWindow
errw
=
new
ErrorWindow
();
errw
.
setImages
(
imgref
,
imgtst
);
errw
.
setVisible
(
true
);
errw
.
waitForHide
();
errw
.
dispose
();
}
public
static
class
Cubic
extends
AnnotatedShapeOp
{
public
static
Cubic
tryparse
(
String
str
)
{
str
=
str
.
trim
();
if
(!
str
.
startsWith
(
"Cubic("
))
{
return
null
;
}
str
=
str
.
substring
(
6
);
double
coords
[]
=
new
double
[
8
];
boolean
foundparen
=
false
;
for
(
int
i
=
0
;
i
<
coords
.
length
;
i
++)
{
int
index
=
str
.
indexOf
(
","
);
if
(
index
<
0
)
{
if
(
i
<
coords
.
length
-
1
)
{
return
null
;
}
index
=
str
.
indexOf
(
")"
);
if
(
index
<
0
)
{
return
null
;
}
foundparen
=
true
;
}
String
num
=
str
.
substring
(
0
,
index
);
try
{
coords
[
i
]
=
Double
.
parseDouble
(
num
);
}
catch
(
NumberFormatException
nfe
)
{
return
null
;
}
str
=
str
.
substring
(
index
+
1
);
}
if
(!
foundparen
||
str
.
length
()
>
0
)
{
return
null
;
}
Cubic
c
=
new
Cubic
();
c
.
cubic
.
setCurve
(
coords
[
0
],
coords
[
1
],
coords
[
2
],
coords
[
3
],
coords
[
4
],
coords
[
5
],
coords
[
6
],
coords
[
7
]);
return
c
;
}
private
CubicCurve2D
cubic
=
new
CubicCurve2D
.
Double
();
public
void
randomize
()
{
cubic
.
setCurve
(
randDblCoord
(),
randDblCoord
(),
randDblCoord
(),
randDblCoord
(),
randDblCoord
(),
randDblCoord
(),
randDblCoord
(),
randDblCoord
());
}
public
Shape
getShape
()
{
return
cubic
;
}
public
String
toString
()
{
return
(
"Cubic("
+
cubic
.
getX1
()+
", "
+
cubic
.
getY1
()+
", "
+
cubic
.
getCtrlX1
()+
", "
+
cubic
.
getCtrlY1
()+
", "
+
cubic
.
getCtrlX2
()+
", "
+
cubic
.
getCtrlY2
()+
", "
+
cubic
.
getX2
()+
", "
+
cubic
.
getY2
()
+
")"
);
}
}
public
static
class
Quad
extends
AnnotatedShapeOp
{
public
static
Quad
tryparse
(
String
str
)
{
str
=
str
.
trim
();
if
(!
str
.
startsWith
(
"Quad("
))
{
return
null
;
}
str
=
str
.
substring
(
5
);
double
coords
[]
=
new
double
[
6
];
boolean
foundparen
=
false
;
for
(
int
i
=
0
;
i
<
coords
.
length
;
i
++)
{
int
index
=
str
.
indexOf
(
","
);
if
(
index
<
0
)
{
if
(
i
<
coords
.
length
-
1
)
{
return
null
;
}
index
=
str
.
indexOf
(
")"
);
if
(
index
<
0
)
{
return
null
;
}
foundparen
=
true
;
}
String
num
=
str
.
substring
(
0
,
index
);
try
{
coords
[
i
]
=
Double
.
parseDouble
(
num
);
}
catch
(
NumberFormatException
nfe
)
{
return
null
;
}
str
=
str
.
substring
(
index
+
1
);
}
if
(!
foundparen
||
str
.
length
()
>
0
)
{
return
null
;
}
Quad
c
=
new
Quad
();
c
.
quad
.
setCurve
(
coords
[
0
],
coords
[
1
],
coords
[
2
],
coords
[
3
],
coords
[
4
],
coords
[
5
]);
return
c
;
}
private
QuadCurve2D
quad
=
new
QuadCurve2D
.
Double
();
public
void
randomize
()
{
quad
.
setCurve
(
randDblCoord
(),
randDblCoord
(),
randDblCoord
(),
randDblCoord
(),
randDblCoord
(),
randDblCoord
());
}
public
Shape
getShape
()
{
return
quad
;
}
public
String
toString
()
{
return
(
"Quad("
+
quad
.
getX1
()+
", "
+
quad
.
getY1
()+
", "
+
quad
.
getCtrlX
()+
", "
+
quad
.
getCtrlY
()+
", "
+
quad
.
getX2
()+
", "
+
quad
.
getY2
()
+
")"
);
}
}
public
static
class
Poly
extends
AnnotatedShapeOp
{
public
static
Poly
tryparse
(
String
str
)
{
str
=
str
.
trim
();
if
(!
str
.
startsWith
(
"Poly("
))
{
return
null
;
}
str
=
str
.
substring
(
5
);
Polygon
p
=
new
Polygon
();
while
(
true
)
{
int
x
,
y
;
str
=
str
.
trim
();
if
(
str
.
startsWith
(
")"
))
{
str
=
str
.
substring
(
1
);
break
;
}
if
(
p
.
npoints
>
0
)
{
if
(
str
.
startsWith
(
","
))
{
str
=
str
.
substring
(
2
).
trim
();
}
else
{
return
null
;
}
}
if
(
str
.
startsWith
(
"["
))
{
str
=
str
.
substring
(
1
);
}
else
{
return
null
;
}
int
index
=
str
.
indexOf
(
","
);
if
(
index
<
0
)
{
return
null
;
}
String
num
=
str
.
substring
(
0
,
index
);
try
{
x
=
Integer
.
parseInt
(
num
);
}
catch
(
NumberFormatException
nfe
)
{
return
null
;
}
str
=
str
.
substring
(
index
+
1
);
index
=
str
.
indexOf
(
"]"
);
if
(
index
<
0
)
{
return
null
;
}
num
=
str
.
substring
(
0
,
index
).
trim
();
try
{
y
=
Integer
.
parseInt
(
num
);
}
catch
(
NumberFormatException
nfe
)
{
return
null
;
}
str
=
str
.
substring
(
index
+
1
);
p
.
addPoint
(
x
,
y
);
}
if
(
str
.
length
()
>
0
)
{
return
null
;
}
if
(
p
.
npoints
<
3
)
{
return
null
;
}
return
new
Poly
(
p
);
}
private
Polygon
poly
;
public
Poly
()
{
this
.
poly
=
new
Polygon
();
}
private
Poly
(
Polygon
p
)
{
this
.
poly
=
p
;
}
public
void
randomize
()
{
poly
.
reset
();
poly
.
addPoint
(
randIntCoord
(),
randIntCoord
());
poly
.
addPoint
(
randIntCoord
(),
randIntCoord
());
poly
.
addPoint
(
randIntCoord
(),
randIntCoord
());
poly
.
addPoint
(
randIntCoord
(),
randIntCoord
());
poly
.
addPoint
(
randIntCoord
(),
randIntCoord
());
}
public
Shape
getShape
()
{
return
poly
;
}
public
String
toString
()
{
StringBuffer
sb
=
new
StringBuffer
(
100
);
sb
.
append
(
"Poly("
);
for
(
int
i
=
0
;
i
<
poly
.
npoints
;
i
++)
{
if
(
i
!=
0
)
{
sb
.
append
(
", "
);
}
sb
.
append
(
"["
);
sb
.
append
(
poly
.
xpoints
[
i
]);
sb
.
append
(
", "
);
sb
.
append
(
poly
.
ypoints
[
i
]);
sb
.
append
(
"]"
);
}
sb
.
append
(
")"
);
return
sb
.
toString
();
}
}
public
static
class
Path
extends
AnnotatedShapeOp
{
public
static
Path
tryparse
(
String
str
)
{
str
=
str
.
trim
();
if
(!
str
.
startsWith
(
"Path("
))
{
return
null
;
}
str
=
str
.
substring
(
5
);
GeneralPath
gp
=
new
GeneralPath
();
float
coords
[]
=
new
float
[
6
];
int
numsegs
=
0
;
while
(
true
)
{
int
type
;
int
n
;
str
=
str
.
trim
();
if
(
str
.
startsWith
(
")"
))
{
str
=
str
.
substring
(
1
);
break
;
}
if
(
str
.
startsWith
(
"M["
))
{
type
=
PathIterator
.
SEG_MOVETO
;
n
=
2
;
}
else
if
(
str
.
startsWith
(
"L["
))
{
type
=
PathIterator
.
SEG_LINETO
;
n
=
2
;
}
else
if
(
str
.
startsWith
(
"Q["
))
{
type
=
PathIterator
.
SEG_QUADTO
;
n
=
4
;
}
else
if
(
str
.
startsWith
(
"C["
))
{
type
=
PathIterator
.
SEG_CUBICTO
;
n
=
6
;
}
else
if
(
str
.
startsWith
(
"E["
))
{
type
=
PathIterator
.
SEG_CLOSE
;
n
=
0
;
}
else
{
return
null
;
}
str
=
str
.
substring
(
2
);
if
(
n
==
0
)
{
if
(
str
.
startsWith
(
"]"
))
{
str
=
str
.
substring
(
1
);
}
else
{
return
null
;
}
}
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
int
index
;
if
(
i
<
n
-
1
)
{
index
=
str
.
indexOf
(
","
);
}
else
{
index
=
str
.
indexOf
(
"]"
);
}
if
(
index
<
0
)
{
return
null
;
}
String
num
=
str
.
substring
(
0
,
index
);
try
{
coords
[
i
]
=
Float
.
parseFloat
(
num
);
}
catch
(
NumberFormatException
nfe
)
{
return
null
;
}
str
=
str
.
substring
(
index
+
1
).
trim
();
}
switch
(
type
)
{
case
PathIterator
.
SEG_MOVETO
:
gp
.
moveTo
(
coords
[
0
],
coords
[
1
]);
break
;
case
PathIterator
.
SEG_LINETO
:
gp
.
lineTo
(
coords
[
0
],
coords
[
1
]);
break
;
case
PathIterator
.
SEG_QUADTO
:
gp
.
quadTo
(
coords
[
0
],
coords
[
1
],
coords
[
2
],
coords
[
3
]);
break
;
case
PathIterator
.
SEG_CUBICTO
:
gp
.
curveTo
(
coords
[
0
],
coords
[
1
],
coords
[
2
],
coords
[
3
],
coords
[
4
],
coords
[
5
]);
break
;
case
PathIterator
.
SEG_CLOSE
:
gp
.
closePath
();
break
;
}
numsegs
++;
}
if
(
str
.
length
()
>
0
)
{
return
null
;
}
if
(
numsegs
<
2
)
{
return
null
;
}
return
new
Path
(
gp
);
}
private
GeneralPath
path
;
public
Path
()
{
this
.
path
=
new
GeneralPath
();
}
private
Path
(
GeneralPath
gp
)
{
this
.
path
=
gp
;
}
public
void
randomize
()
{
path
.
reset
();
path
.
moveTo
(
randFltCoord
(),
randFltCoord
());
for
(
int
i
=
randInt
(
5
)+
3
;
i
>
0
;
--
i
)
{
switch
(
randInt
(
5
))
{
case
0
:
path
.
moveTo
(
randFltCoord
(),
randFltCoord
());
break
;
case
1
:
path
.
lineTo
(
randFltCoord
(),
randFltCoord
());
break
;
case
2
:
path
.
quadTo
(
randFltCoord
(),
randFltCoord
(),
randFltCoord
(),
randFltCoord
());
break
;
case
3
:
path
.
curveTo
(
randFltCoord
(),
randFltCoord
(),
randFltCoord
(),
randFltCoord
(),
randFltCoord
(),
randFltCoord
());
break
;
case
4
:
path
.
closePath
();
break
;
}
}
}
public
Shape
getShape
()
{
return
path
;
}
public
String
toString
()
{
StringBuffer
sb
=
new
StringBuffer
(
100
);
sb
.
append
(
"Path("
);
PathIterator
pi
=
path
.
getPathIterator
(
null
);
float
coords
[]
=
new
float
[
6
];
boolean
first
=
true
;
while
(!
pi
.
isDone
())
{
int
n
;
char
c
;
switch
(
pi
.
currentSegment
(
coords
))
{
case
PathIterator
.
SEG_MOVETO
:
c
=
'M'
;
n
=
2
;
break
;
case
PathIterator
.
SEG_LINETO
:
c
=
'L'
;
n
=
2
;
break
;
case
PathIterator
.
SEG_QUADTO
:
c
=
'Q'
;
n
=
4
;
break
;
case
PathIterator
.
SEG_CUBICTO
:
c
=
'C'
;
n
=
6
;
break
;
case
PathIterator
.
SEG_CLOSE
:
c
=
'E'
;
n
=
0
;
break
;
default
:
throw
new
InternalError
(
"Unknown segment!"
);
}
sb
.
append
(
c
);
sb
.
append
(
"["
);
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
if
(
i
!=
0
)
{
sb
.
append
(
","
);
}
sb
.
append
(
coords
[
i
]);
}
sb
.
append
(
"]"
);
pi
.
next
();
}
sb
.
append
(
")"
);
return
sb
.
toString
();
}
}
public
static
class
Rect
extends
AnnotatedShapeOp
{
public
static
Rect
tryparse
(
String
str
)
{
str
=
str
.
trim
();
if
(!
str
.
startsWith
(
"Rect("
))
{
return
null
;
}
str
=
str
.
substring
(
5
);
double
coords
[]
=
new
double
[
4
];
boolean
foundparen
=
false
;
for
(
int
i
=
0
;
i
<
coords
.
length
;
i
++)
{
int
index
=
str
.
indexOf
(
","
);
if
(
index
<
0
)
{
if
(
i
<
coords
.
length
-
1
)
{
return
null
;
}
index
=
str
.
indexOf
(
")"
);
if
(
index
<
0
)
{
return
null
;
}
foundparen
=
true
;
}
String
num
=
str
.
substring
(
0
,
index
);
try
{
coords
[
i
]
=
Double
.
parseDouble
(
num
);
}
catch
(
NumberFormatException
nfe
)
{
return
null
;
}
str
=
str
.
substring
(
index
+
1
);
}
if
(!
foundparen
||
str
.
length
()
>
0
)
{
return
null
;
}
Rect
r
=
new
Rect
();
r
.
rect
.
setRect
(
coords
[
0
],
coords
[
1
],
coords
[
2
],
coords
[
3
]);
return
r
;
}
private
Rectangle2D
rect
=
new
Rectangle2D
.
Double
();
public
void
randomize
()
{
rect
.
setRect
(
randDblCoord
(),
randDblCoord
(),
randDblCoord
(),
randDblCoord
());
}
public
Shape
getShape
()
{
return
rect
;
}
public
String
toString
()
{
return
(
"Rect("
+
rect
.
getX
()+
", "
+
rect
.
getY
()+
", "
+
rect
.
getWidth
()+
", "
+
rect
.
getHeight
()
+
")"
);
}
}
public
static
class
Line
extends
AnnotatedShapeOp
{
public
static
Line
tryparse
(
String
str
)
{
str
=
str
.
trim
();
if
(!
str
.
startsWith
(
"Line("
))
{
return
null
;
}
str
=
str
.
substring
(
5
);
double
coords
[]
=
new
double
[
4
];
boolean
foundparen
=
false
;
for
(
int
i
=
0
;
i
<
coords
.
length
;
i
++)
{
int
index
=
str
.
indexOf
(
","
);
if
(
index
<
0
)
{
if
(
i
<
coords
.
length
-
1
)
{
return
null
;
}
index
=
str
.
indexOf
(
")"
);
if
(
index
<
0
)
{
return
null
;
}
foundparen
=
true
;
}
String
num
=
str
.
substring
(
0
,
index
);
try
{
coords
[
i
]
=
Double
.
parseDouble
(
num
);
}
catch
(
NumberFormatException
nfe
)
{
return
null
;
}
str
=
str
.
substring
(
index
+
1
);
}
if
(!
foundparen
||
str
.
length
()
>
0
)
{
return
null
;
}
Line
l
=
new
Line
();
l
.
line
.
setLine
(
coords
[
0
],
coords
[
1
],
coords
[
2
],
coords
[
3
]);
return
l
;
}
private
Line2D
line
=
new
Line2D
.
Double
();
public
void
randomize
()
{
line
.
setLine
(
randDblCoord
(),
randDblCoord
(),
randDblCoord
(),
randDblCoord
());
}
public
Shape
getShape
()
{
return
line
;
}
public
String
toString
()
{
return
(
"Line("
+
line
.
getX1
()+
", "
+
line
.
getY1
()+
", "
+
line
.
getX2
()+
", "
+
line
.
getY2
()
+
")"
);
}
}
public
static
class
RectMethod
extends
AnnotatedRenderOp
{
public
static
RectMethod
tryparse
(
String
str
)
{
str
=
str
.
trim
();
if
(!
str
.
startsWith
(
"RectMethod("
))
{
return
null
;
}
str
=
str
.
substring
(
11
);
int
coords
[]
=
new
int
[
4
];
boolean
foundparen
=
false
;
for
(
int
i
=
0
;
i
<
coords
.
length
;
i
++)
{
int
index
=
str
.
indexOf
(
","
);
if
(
index
<
0
)
{
if
(
i
<
coords
.
length
-
1
)
{
return
null
;
}
index
=
str
.
indexOf
(
")"
);
if
(
index
<
0
)
{
return
null
;
}
foundparen
=
true
;
}
String
num
=
str
.
substring
(
0
,
index
).
trim
();
try
{
coords
[
i
]
=
Integer
.
parseInt
(
num
);
}
catch
(
NumberFormatException
nfe
)
{
return
null
;
}
str
=
str
.
substring
(
index
+
1
);
}
if
(!
foundparen
||
str
.
length
()
>
0
)
{
return
null
;
}
RectMethod
rm
=
new
RectMethod
();
rm
.
rect
.
setBounds
(
coords
[
0
],
coords
[
1
],
coords
[
2
],
coords
[
3
]);
return
rm
;
}
private
Rectangle
rect
=
new
Rectangle
();
public
void
randomize
()
{
rect
.
setBounds
(
randIntCoord
(),
randIntCoord
(),
randIntCoord
(),
randIntCoord
());
}
public
void
fill
(
Graphics2D
g2d
)
{
g2d
.
fillRect
(
rect
.
x
,
rect
.
y
,
rect
.
width
,
rect
.
height
);
}
public
void
draw
(
Graphics2D
g2d
)
{
g2d
.
drawRect
(
rect
.
x
,
rect
.
y
,
rect
.
width
,
rect
.
height
);
}
public
String
toString
()
{
return
(
"RectMethod("
+
rect
.
x
+
", "
+
rect
.
y
+
", "
+
rect
.
width
+
", "
+
rect
.
height
+
")"
);
}
}
public
static
class
LineMethod
extends
AnnotatedRenderOp
{
public
static
LineMethod
tryparse
(
String
str
)
{
str
=
str
.
trim
();
if
(!
str
.
startsWith
(
"LineMethod("
))
{
return
null
;
}
str
=
str
.
substring
(
11
);
int
coords
[]
=
new
int
[
4
];
boolean
foundparen
=
false
;
for
(
int
i
=
0
;
i
<
coords
.
length
;
i
++)
{
int
index
=
str
.
indexOf
(
","
);
if
(
index
<
0
)
{
if
(
i
<
coords
.
length
-
1
)
{
return
null
;
}
index
=
str
.
indexOf
(
")"
);
if
(
index
<
0
)
{
return
null
;
}
foundparen
=
true
;
}
String
num
=
str
.
substring
(
0
,
index
).
trim
();
try
{
coords
[
i
]
=
Integer
.
parseInt
(
num
);
}
catch
(
NumberFormatException
nfe
)
{
return
null
;
}
str
=
str
.
substring
(
index
+
1
);
}
if
(!
foundparen
||
str
.
length
()
>
0
)
{
return
null
;
}
LineMethod
lm
=
new
LineMethod
();
lm
.
line
=
coords
;
return
lm
;
}
private
int
line
[]
=
new
int
[
4
];
public
void
randomize
()
{
line
[
0
]
=
randIntCoord
();
line
[
1
]
=
randIntCoord
();
line
[
2
]
=
randIntCoord
();
line
[
3
]
=
randIntCoord
();
}
public
void
fill
(
Graphics2D
g2d
)
{
}
public
void
draw
(
Graphics2D
g2d
)
{
g2d
.
drawLine
(
line
[
0
],
line
[
1
],
line
[
2
],
line
[
3
]);
}
public
String
toString
()
{
return
(
"LineMethod("
+
line
[
0
]+
", "
+
line
[
1
]+
", "
+
line
[
2
]+
", "
+
line
[
3
]
+
")"
);
}
}
public
static
class
ErrorWindow
extends
Frame
{
ImageCanvas
unclipped
;
ImageCanvas
reference
;
ImageCanvas
actual
;
ImageCanvas
diff
;
public
ErrorWindow
()
{
super
(
"Error Comparison Window"
);
unclipped
=
new
ImageCanvas
();
reference
=
new
ImageCanvas
();
actual
=
new
ImageCanvas
();
diff
=
new
ImageCanvas
();
setLayout
(
new
SmartGridLayout
(
0
,
2
,
5
,
5
));
addImagePanel
(
unclipped
,
"Unclipped rendering"
);
addImagePanel
(
reference
,
"Clipped reference"
);
addImagePanel
(
actual
,
"Actual clipped"
);
addImagePanel
(
diff
,
"Difference"
);
addWindowListener
(
new
WindowAdapter
()
{
public
void
windowClosing
(
WindowEvent
e
)
{
setVisible
(
false
);
}
});
}
public
void
addImagePanel
(
ImageCanvas
ic
,
String
label
)
{
add
(
ic
);
add
(
new
Label
(
label
));
}
public
void
setImages
(
BufferedImage
imgref
,
BufferedImage
imgtst
)
{
unclipped
.
setImage
(
imgref
);
reference
.
setReference
(
imgref
);
actual
.
setImage
(
imgtst
);
diff
.
setDiff
(
reference
.
getImage
(),
imgtst
);
invalidate
();
pack
();
repaint
();
}
public
void
setVisible
(
boolean
vis
)
{
super
.
setVisible
(
vis
);
synchronized
(
this
)
{
notifyAll
();
}
}
public
synchronized
void
waitForHide
()
{
while
(
isShowing
())
{
try
{
wait
();
}
catch
(
InterruptedException
e
)
{
System
.
exit
(
2
);
}
}
}
}
public
static
class
SmartGridLayout
implements
LayoutManager
{
int
rows
;
int
cols
;
int
hgap
;
int
vgap
;
public
SmartGridLayout
(
int
r
,
int
c
,
int
h
,
int
v
)
{
this
.
rows
=
r
;
this
.
cols
=
c
;
this
.
hgap
=
h
;
this
.
vgap
=
v
;
}
public
void
addLayoutComponent
(
String
name
,
Component
comp
)
{
}
public
void
removeLayoutComponent
(
Component
comp
)
{
}
public
int
[][]
getGridSizes
(
Container
parent
,
boolean
min
)
{
int
ncomponents
=
parent
.
getComponentCount
();
int
nrows
=
rows
;
int
ncols
=
cols
;
if
(
nrows
>
0
)
{
ncols
=
(
ncomponents
+
nrows
-
1
)
/
nrows
;
}
else
{
nrows
=
(
ncomponents
+
ncols
-
1
)
/
ncols
;
}
int
widths
[]
=
new
int
[
ncols
+
1
];
int
heights
[]
=
new
int
[
nrows
+
1
];
int
x
=
0
;
int
y
=
0
;
for
(
int
i
=
0
;
i
<
ncomponents
;
i
++)
{
Component
comp
=
parent
.
getComponent
(
i
);
Dimension
d
=
(
min
?
comp
.
getMinimumSize
()
:
comp
.
getPreferredSize
());
if
(
widths
[
x
]
<
d
.
width
)
{
widths
[
x
]
=
d
.
width
;
}
if
(
heights
[
y
]
<
d
.
height
)
{
heights
[
y
]
=
d
.
height
;
}
x
++;
if
(
x
>=
ncols
)
{
x
=
0
;
y
++;
}
}
for
(
int
i
=
0
;
i
<
ncols
;
i
++)
{
widths
[
ncols
]
+=
widths
[
i
];
}
for
(
int
i
=
0
;
i
<
nrows
;
i
++)
{
heights
[
nrows
]
+=
heights
[
i
];
}
return
new
int
[][]
{
widths
,
heights
};
}
public
Dimension
getSize
(
Container
parent
,
boolean
min
)
{
int
sizes
[][]
=
getGridSizes
(
parent
,
min
);
int
widths
[]
=
sizes
[
0
];
int
heights
[]
=
sizes
[
1
];
int
nrows
=
heights
.
length
-
1
;
int
ncols
=
widths
.
length
-
1
;
int
w
=
widths
[
ncols
];
int
h
=
heights
[
nrows
];
Insets
insets
=
parent
.
getInsets
();
return
new
Dimension
(
insets
.
left
+
insets
.
right
+
w
+(
ncols
+
1
)*
hgap
,
insets
.
top
+
insets
.
bottom
+
h
+(
nrows
+
1
)*
vgap
);
}
public
Dimension
preferredLayoutSize
(
Container
parent
)
{
return
getSize
(
parent
,
false
);
}
public
Dimension
minimumLayoutSize
(
Container
parent
)
{
return
getSize
(
parent
,
true
);
}
public
void
layoutContainer
(
Container
parent
)
{
int
pref
[][]
=
getGridSizes
(
parent
,
false
);
int
min
[][]
=
getGridSizes
(
parent
,
true
);
int
minwidths
[]
=
min
[
0
];
int
minheights
[]
=
min
[
1
];
int
prefwidths
[]
=
pref
[
0
];
int
prefheights
[]
=
pref
[
1
];
int
nrows
=
minheights
.
length
-
1
;
int
ncols
=
minwidths
.
length
-
1
;
Insets
insets
=
parent
.
getInsets
();
int
w
=
parent
.
getWidth
()
-
insets
.
left
-
insets
.
right
;
int
h
=
parent
.
getHeight
()
-
insets
.
top
-
insets
.
bottom
;
w
=
w
-
(
ncols
+
1
)*
hgap
;
h
=
h
-
(
nrows
+
1
)*
vgap
;
int
widths
[]
=
calculateSizes
(
w
,
ncols
,
minwidths
,
prefwidths
);
int
heights
[]
=
calculateSizes
(
h
,
nrows
,
minheights
,
prefheights
);
int
ncomponents
=
parent
.
getComponentCount
();
int
x
=
insets
.
left
+
hgap
;
int
y
=
insets
.
top
+
vgap
;
int
r
=
0
;
int
c
=
0
;
for
(
int
i
=
0
;
i
<
ncomponents
;
i
++)
{
parent
.
getComponent
(
i
).
setBounds
(
x
,
y
,
widths
[
c
],
heights
[
r
]);
x
+=
widths
[
c
++]
+
hgap
;
if
(
c
>=
ncols
)
{
c
=
0
;
x
=
insets
.
left
+
hgap
;
y
+=
heights
[
r
++]
+
vgap
;
if
(
r
>=
nrows
)
{
// just in case
break
;
}
}
}
}
public
static
int
[]
calculateSizes
(
int
total
,
int
num
,
int
minsizes
[],
int
prefsizes
[])
{
if
(
total
<=
minsizes
[
num
])
{
return
minsizes
;
}
if
(
total
>=
prefsizes
[
num
])
{
return
prefsizes
;
}
int
sizes
[]
=
new
int
[
total
];
int
prevhappy
=
0
;
int
nhappy
=
0
;
int
happysize
=
0
;
do
{
int
addsize
=
(
total
-
happysize
)
/
(
num
-
nhappy
);
happysize
=
0
;
for
(
int
i
=
0
;
i
<
num
;
i
++)
{
if
(
sizes
[
i
]
>=
prefsizes
[
i
]
||
minsizes
[
i
]
+
addsize
>
prefsizes
[
i
])
{
happysize
+=
(
sizes
[
i
]
=
prefsizes
[
i
]);
nhappy
++;
}
else
{
sizes
[
i
]
=
minsizes
[
i
]
+
addsize
;
}
}
}
while
(
nhappy
<
num
&&
nhappy
>
prevhappy
);
return
sizes
;
}
}
public
static
class
ImageCanvas
extends
Canvas
{
BufferedImage
image
;
public
void
setImage
(
BufferedImage
img
)
{
this
.
image
=
img
;
}
public
BufferedImage
getImage
()
{
return
image
;
}
public
void
checkImage
(
int
w
,
int
h
)
{
if
(
image
==
null
||
image
.
getWidth
()
<
w
||
image
.
getHeight
()
<
h
)
{
image
=
new
BufferedImage
(
w
,
h
,
BufferedImage
.
TYPE_INT_RGB
);
}
}
public
void
setReference
(
BufferedImage
img
)
{
checkImage
(
img
.
getWidth
(),
img
.
getHeight
());
Graphics
g
=
image
.
createGraphics
();
g
.
drawImage
(
img
,
0
,
0
,
null
);
g
.
setColor
(
Color
.
white
);
g
.
fillRect
(
0
,
0
,
30
,
10
);
g
.
fillRect
(
30
,
0
,
10
,
30
);
g
.
fillRect
(
10
,
30
,
30
,
10
);
g
.
fillRect
(
0
,
10
,
10
,
30
);
g
.
dispose
();
}
public
void
setDiff
(
BufferedImage
imgref
,
BufferedImage
imgtst
)
{
int
w
=
Math
.
max
(
imgref
.
getWidth
(),
imgtst
.
getWidth
());
int
h
=
Math
.
max
(
imgref
.
getHeight
(),
imgtst
.
getHeight
());
checkImage
(
w
,
h
);
Graphics
g
=
image
.
createGraphics
();
g
.
drawImage
(
imgref
,
0
,
0
,
null
);
g
.
setXORMode
(
Color
.
white
);
g
.
drawImage
(
imgtst
,
0
,
0
,
null
);
g
.
setPaintMode
();
g
.
setColor
(
new
Color
(
1
f
,
1
f
,
0
f
,
0.25f
));
g
.
fillRect
(
10
,
10
,
20
,
20
);
g
.
setColor
(
new
Color
(
1
f
,
0
f
,
0
f
,
0.25f
));
g
.
fillRect
(
0
,
0
,
30
,
10
);
g
.
fillRect
(
30
,
0
,
10
,
30
);
g
.
fillRect
(
10
,
30
,
30
,
10
);
g
.
fillRect
(
0
,
10
,
10
,
30
);
g
.
dispose
();
}
public
Dimension
getPreferredSize
()
{
if
(
image
==
null
)
{
return
new
Dimension
();
}
else
{
return
new
Dimension
(
image
.
getWidth
(),
image
.
getHeight
());
}
}
public
void
paint
(
Graphics
g
)
{
g
.
drawImage
(
image
,
0
,
0
,
null
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录