History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/java2d/pipe (114 of 18352 files). Show all

Unified · Split

114 files
  1. java/pkg/sun/java2d/pipe/AAShapePipe.class +0 −0
  2. java/pkg/sun/java2d/pipe/AAShapePipe.java +215 −0
  3. java/pkg/sun/java2d/pipe/AATextRenderer.class +0 −0
  4. java/pkg/sun/java2d/pipe/AATextRenderer.java +45 −0
  5. java/pkg/sun/java2d/pipe/AATileGenerator.class +0 −0
  6. java/pkg/sun/java2d/pipe/AATileGenerator.java +111 −0
  7. java/pkg/sun/java2d/pipe/AlphaColorPipe.class +0 −0
  8. java/pkg/sun/java2d/pipe/AlphaColorPipe.java +90 −0
  9. java/pkg/sun/java2d/pipe/AlphaPaintPipe$TileContext.class +0 −0
  10. java/pkg/sun/java2d/pipe/AlphaPaintPipe.class +0 −0
  11. java/pkg/sun/java2d/pipe/AlphaPaintPipe.java +206 −0
  12. java/pkg/sun/java2d/pipe/BufferedBufImgOps.java +393 −0
  13. java/pkg/sun/java2d/pipe/BufferedContext.class +0 −0
  14. java/pkg/sun/java2d/pipe/BufferedContext.java +470 −0
  15. java/pkg/sun/java2d/pipe/BufferedMaskBlit.java +163 −0
  16. java/pkg/sun/java2d/pipe/BufferedMaskFill.java +153 −0
  17. java/pkg/sun/java2d/pipe/BufferedOpCodes.class +0 −0
  18. java/pkg/sun/java2d/pipe/BufferedOpCodes.java +99 −0
  19. java/pkg/sun/java2d/pipe/BufferedPaints.class +0 −0
  20. java/pkg/sun/java2d/pipe/BufferedPaints.java +533 −0
  21. java/pkg/sun/java2d/pipe/BufferedRenderPipe$1.class +0 −0
  22. java/pkg/sun/java2d/pipe/BufferedRenderPipe$AAParallelogramPipe.class +0 −0
  23. java/pkg/sun/java2d/pipe/BufferedRenderPipe$BufferedDrawHandler.class +0 −0
  24. java/pkg/sun/java2d/pipe/BufferedRenderPipe.class +0 −0
  25. java/pkg/sun/java2d/pipe/BufferedRenderPipe.java +601 −0
  26. java/pkg/sun/java2d/pipe/BufferedTextPipe.java +168 −0
  27. java/pkg/sun/java2d/pipe/CompositePipe.class +0 −0
  28. java/pkg/sun/java2d/pipe/CompositePipe.java +50 −0
  29. java/pkg/sun/java2d/pipe/DrawImage.class +0 −0
  30. java/pkg/sun/java2d/pipe/DrawImage.java +1110 −0
  31. java/pkg/sun/java2d/pipe/DrawImagePipe.class +0 −0
  32. java/pkg/sun/java2d/pipe/DrawImagePipe.java +86 −0
  33. java/pkg/sun/java2d/pipe/GeneralCompositePipe$TileContext.class +0 −0
  34. java/pkg/sun/java2d/pipe/GeneralCompositePipe.class +0 −0
  35. java/pkg/sun/java2d/pipe/GeneralCompositePipe.java +154 −0
  36. java/pkg/sun/java2d/pipe/GlyphListLoopPipe.class +0 −0
  37. java/pkg/sun/java2d/pipe/GlyphListLoopPipe.java +60 −0
  38. java/pkg/sun/java2d/pipe/GlyphListPipe.class +0 −0
  39. java/pkg/sun/java2d/pipe/GlyphListPipe.java +147 −0
  40. java/pkg/sun/java2d/pipe/LCDTextRenderer.class +0 −0
  41. java/pkg/sun/java2d/pipe/LCDTextRenderer.java +44 −0
  42. java/pkg/sun/java2d/pipe/LoopBasedPipe.class +0 −0
  43. java/pkg/sun/java2d/pipe/LoopBasedPipe.java +37 −0
  44. java/pkg/sun/java2d/pipe/LoopPipe.class +0 −0
  45. java/pkg/sun/java2d/pipe/LoopPipe.java +378 −0
  46. java/pkg/sun/java2d/pipe/NullPipe.class +0 −0
  47. java/pkg/sun/java2d/pipe/NullPipe.java +155 −0
  48. java/pkg/sun/java2d/pipe/OutlineTextRenderer.class +0 −0
  49. java/pkg/sun/java2d/pipe/OutlineTextRenderer.java +145 −0
  50. java/pkg/sun/java2d/pipe/ParallelogramPipe.class +0 −0
  51. java/pkg/sun/java2d/pipe/ParallelogramPipe.java +76 −0
  52. java/pkg/sun/java2d/pipe/PixelDrawPipe.class +0 −0
  53. java/pkg/sun/java2d/pipe/PixelDrawPipe.java +67 −0
  54. java/pkg/sun/java2d/pipe/PixelFillPipe.class +0 −0
  55. java/pkg/sun/java2d/pipe/PixelFillPipe.java +61 −0
  56. java/pkg/sun/java2d/pipe/PixelToParallelogramConverter.class +0 −0
  57. java/pkg/sun/java2d/pipe/PixelToParallelogramConverter.java +429 −0
  58. java/pkg/sun/java2d/pipe/PixelToShapeConverter.class +0 −0
  59. java/pkg/sun/java2d/pipe/PixelToShapeConverter.java +133 −0
  60. java/pkg/sun/java2d/pipe/Region$ImmutableRegion.class +0 −0
  61. java/pkg/sun/java2d/pipe/Region.class +0 −0
  62. java/pkg/sun/java2d/pipe/Region.java +1255 −0
  63. java/pkg/sun/java2d/pipe/RegionClipSpanIterator.class +0 −0
  64. java/pkg/sun/java2d/pipe/RegionClipSpanIterator.java +392 −0
  65. java/pkg/sun/java2d/pipe/RegionIterator.class +0 −0
  66. java/pkg/sun/java2d/pipe/RegionIterator.java +101 −0
  67. java/pkg/sun/java2d/pipe/RegionSpanIterator.class +0 −0
  68. java/pkg/sun/java2d/pipe/RegionSpanIterator.java +210 −0
  69. java/pkg/sun/java2d/pipe/RenderBuffer.class +0 −0
  70. java/pkg/sun/java2d/pipe/RenderBuffer.java +294 −0
  71. java/pkg/sun/java2d/pipe/RenderQueue.class +0 −0
  72. java/pkg/sun/java2d/pipe/RenderQueue.java +223 −0
  73. java/pkg/sun/java2d/pipe/RenderingEngine$1.class +0 −0
  74. java/pkg/sun/java2d/pipe/RenderingEngine$Tracer.class +0 −0
  75. java/pkg/sun/java2d/pipe/RenderingEngine.class +0 −0
  76. java/pkg/sun/java2d/pipe/RenderingEngine.java +482 −0
  77. java/pkg/sun/java2d/pipe/ShapeDrawPipe.class +0 −0
  78. java/pkg/sun/java2d/pipe/ShapeDrawPipe.java +40 −0
  79. java/pkg/sun/java2d/pipe/ShapeSpanIterator.class +0 −0
  80. java/pkg/sun/java2d/pipe/ShapeSpanIterator.java +201 −0
  81. java/pkg/sun/java2d/pipe/SolidTextRenderer.class +0 −0
  82. java/pkg/sun/java2d/pipe/SolidTextRenderer.java +44 −0
  83. java/pkg/sun/java2d/pipe/SpanClipRenderer$SCRcontext.class +0 −0
  84. java/pkg/sun/java2d/pipe/SpanClipRenderer.class +0 −0
  85. java/pkg/sun/java2d/pipe/SpanClipRenderer.java +141 −0
  86. java/pkg/sun/java2d/pipe/SpanIterator.class +0 −0
  87. java/pkg/sun/java2d/pipe/SpanIterator.java +95 −0
  88. java/pkg/sun/java2d/pipe/SpanShapeRenderer$Composite.class +0 −0
  89. java/pkg/sun/java2d/pipe/SpanShapeRenderer$Simple.class +0 −0
  90. java/pkg/sun/java2d/pipe/SpanShapeRenderer.class +0 −0
  91. java/pkg/sun/java2d/pipe/SpanShapeRenderer.java +216 −0
  92. java/pkg/sun/java2d/pipe/TextPipe.class +0 −0
  93. java/pkg/sun/java2d/pipe/TextPipe.java +49 −0
  94. java/pkg/sun/java2d/pipe/TextRenderer.class +0 −0
  95. java/pkg/sun/java2d/pipe/TextRenderer.java +98 −0
  96. java/pkg/sun/java2d/pipe/ValidatePipe.class +0 −0
  97. java/pkg/sun/java2d/pipe/ValidatePipe.java +241 −0
  98. java/pkg/sun/java2d/pipe/hw/AccelDeviceEventListener.class +0 −0
  99. java/pkg/sun/java2d/pipe/hw/AccelDeviceEventListener.java +59 −0
  100. java/pkg/sun/java2d/pipe/hw/AccelDeviceEventNotifier.java +167 −0
  101. java/pkg/sun/java2d/pipe/hw/AccelGraphicsConfig.class +0 −0
  102. java/pkg/sun/java2d/pipe/hw/AccelGraphicsConfig.java +95 −0
  103. java/pkg/sun/java2d/pipe/hw/AccelSurface.class +0 −0
  104. java/pkg/sun/java2d/pipe/hw/AccelSurface.java +136 −0
  105. java/pkg/sun/java2d/pipe/hw/AccelTypedVolatileImage.java +74 −0
  106. java/pkg/sun/java2d/pipe/hw/BufferedContextProvider.class +0 −0
  107. java/pkg/sun/java2d/pipe/hw/BufferedContextProvider.java +45 −0
  108. java/pkg/sun/java2d/pipe/hw/ContextCapabilities.class +0 −0
  109. java/pkg/sun/java2d/pipe/hw/ContextCapabilities.java +128 −0
  110. java/pkg/sun/java2d/pipe/hw/ExtendedBufferCapabilities$VSyncType.class +0 −0
  111. java/pkg/sun/java2d/pipe/hw/ExtendedBufferCapabilities.class +0 −0
  112. java/pkg/sun/java2d/pipe/hw/ExtendedBufferCapabilities.java +154 −0
  113. java/pkg/sun/java2d/pipe/hw/mkfile +15 −0
  114. java/pkg/sun/java2d/pipe/mkfile +56 −0
java/pkg/sun/java2d/pipe/AAShapePipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/AAShapePipe.java+215−0
@@ -0,0 +1,215 @@
1+/*
2+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.BasicStroke;
29+import java.awt.Rectangle;
30+import java.awt.Shape;
31+import java.awt.geom.Rectangle2D;
32+import java.awt.geom.PathIterator;
33+import sun.awt.SunHints;
34+import sun.java2d.SunGraphics2D;
35+
36+/**
37+ * This class is used to convert raw geometry into 8-bit alpha tiles
38+ * using an AATileGenerator for application by the next stage of
39+ * the pipeline.
40+ * This class sets up the Generator and computes the alpha tiles
41+ * and then passes them on to a CompositePipe object for painting.
42+ */
43+public class AAShapePipe
44+ implements ShapeDrawPipe, ParallelogramPipe
45+{
46+ static RenderingEngine renderengine = RenderingEngine.getInstance();
47+
48+ CompositePipe outpipe;
49+
50+ public AAShapePipe(CompositePipe pipe) {
51+ outpipe = pipe;
52+ }
53+
54+ public void draw(SunGraphics2D sg, Shape s) {
55+ BasicStroke bs;
56+
57+ if (sg.stroke instanceof BasicStroke) {
58+ bs = (BasicStroke) sg.stroke;
59+ } else {
60+ s = sg.stroke.createStrokedShape(s);
61+ bs = null;
62+ }
63+
64+ renderPath(sg, s, bs);
65+ }
66+
67+ public void fill(SunGraphics2D sg, Shape s) {
68+ renderPath(sg, s, null);
69+ }
70+
71+ private static Rectangle2D computeBBox(double ux1, double uy1,
72+ double ux2, double uy2)
73+ {
74+ if ((ux2 -= ux1) < 0) {
75+ ux1 += ux2;
76+ ux2 = -ux2;
77+ }
78+ if ((uy2 -= uy1) < 0) {
79+ uy1 += uy2;
80+ uy2 = -uy2;
81+ }
82+ return new Rectangle2D.Double(ux1, uy1, ux2, uy2);
83+ }
84+
85+ public void fillParallelogram(SunGraphics2D sg,
86+ double ux1, double uy1,
87+ double ux2, double uy2,
88+ double x, double y,
89+ double dx1, double dy1,
90+ double dx2, double dy2)
91+ {
92+ Region clip = sg.getCompClip();
93+ int abox[] = new int[4];
94+ AATileGenerator aatg =
95+ renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0,
96+ clip, abox);
97+ if (aatg == null) {
98+ // Nothing to render
99+ return;
100+ }
101+
102+ renderTiles(sg, computeBBox(ux1, uy1, ux2, uy2), aatg, abox);
103+ }
104+
105+ public void drawParallelogram(SunGraphics2D sg,
106+ double ux1, double uy1,
107+ double ux2, double uy2,
108+ double x, double y,
109+ double dx1, double dy1,
110+ double dx2, double dy2,
111+ double lw1, double lw2)
112+ {
113+ Region clip = sg.getCompClip();
114+ int abox[] = new int[4];
115+ AATileGenerator aatg =
116+ renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1, lw2,
117+ clip, abox);
118+ if (aatg == null) {
119+ // Nothing to render
120+ return;
121+ }
122+
123+ // Note that bbox is of the original shape, not the wide path.
124+ // This is appropriate for handing to Paint methods...
125+ renderTiles(sg, computeBBox(ux1, uy1, ux2, uy2), aatg, abox);
126+ }
127+
128+ private static byte[] theTile;
129+
130+ public synchronized static byte[] getAlphaTile(int len) {
131+ byte[] t = theTile;
132+ if (t == null || t.length < len) {
133+ t = new byte[len];
134+ } else {
135+ theTile = null;
136+ }
137+ return t;
138+ }
139+
140+ public synchronized static void dropAlphaTile(byte[] t) {
141+ theTile = t;
142+ }
143+
144+ public void renderPath(SunGraphics2D sg, Shape s, BasicStroke bs) {
145+ boolean adjust = (bs != null &&
146+ sg.strokeHint != SunHints.INTVAL_STROKE_PURE);
147+ boolean thin = (sg.strokeState <= sg.STROKE_THINDASHED);
148+
149+ Region clip = sg.getCompClip();
150+ int abox[] = new int[4];
151+ AATileGenerator aatg =
152+ renderengine.getAATileGenerator(s, sg.transform, clip,
153+ bs, thin, adjust, abox);
154+ if (aatg == null) {
155+ // Nothing to render
156+ return;
157+ }
158+
159+ renderTiles(sg, s, aatg, abox);
160+ }
161+
162+ public void renderTiles(SunGraphics2D sg, Shape s,
163+ AATileGenerator aatg, int abox[])
164+ {
165+ Object context = null;
166+ byte alpha[] = null;
167+ try {
168+ context = outpipe.startSequence(sg, s,
169+ new Rectangle(abox[0], abox[1],
170+ abox[2] - abox[0],
171+ abox[3] - abox[1]),
172+ abox);
173+
174+ int tw = aatg.getTileWidth();
175+ int th = aatg.getTileHeight();
176+ alpha = getAlphaTile(tw * th);
177+
178+ byte[] atile;
179+
180+ for (int y = abox[1]; y < abox[3]; y += th) {
181+ for (int x = abox[0]; x < abox[2]; x += tw) {
182+ int w = Math.min(tw, abox[2] - x);
183+ int h = Math.min(th, abox[3] - y);
184+
185+ int a = aatg.getTypicalAlpha();
186+ if (a == 0x00 ||
187+ outpipe.needTile(context, x, y, w, h) == false)
188+ {
189+ aatg.nextTile();
190+ outpipe.skipTile(context, x, y);
191+ continue;
192+ }
193+ if (a == 0xff) {
194+ atile = null;
195+ aatg.nextTile();
196+ } else {
197+ atile = alpha;
198+ aatg.getAlpha(alpha, 0, tw);
199+ }
200+
201+ outpipe.renderPathTile(context, atile, 0, tw,
202+ x, y, w, h);
203+ }
204+ }
205+ } finally {
206+ aatg.dispose();
207+ if (context != null) {
208+ outpipe.endSequence(context);
209+ }
210+ if (alpha != null) {
211+ dropAlphaTile(alpha);
212+ }
213+ }
214+ }
215+}
java/pkg/sun/java2d/pipe/AATextRenderer.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/AATextRenderer.java+45−0
@@ -0,0 +1,45 @@
1+/*
2+ * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.font.GlyphVector;
29+import sun.java2d.SunGraphics2D;
30+import sun.font.GlyphList;
31+
32+/**
33+ * A delegate pipe of SG2D for drawing anti-aliased text with
34+ * a solid source colour to an opaque destination.
35+ */
36+
37+public class AATextRenderer extends GlyphListLoopPipe
38+ implements LoopBasedPipe
39+{
40+ protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
41+ sg2d.loops.drawGlyphListAALoop.DrawGlyphListAA(sg2d, sg2d.surfaceData,
42+ gl);
43+ }
44+
45+}
java/pkg/sun/java2d/pipe/AATileGenerator.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/AATileGenerator.java+111−0
@@ -0,0 +1,111 @@
1+/*
2+ * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+/**
29+ * The API for an object that generates alpha coverage tiles for a given
30+ * path.
31+ * The {@link RenderingEngine} will be consulted as a factory to return
32+ * one of these objects for a given Shape and a given set of rendering
33+ * attributes.
34+ * This object will iterate through the bounds of the rendering primitive
35+ * and return tiles of a constant size as specified by the getTileWidth()
36+ * and getTileHeight() parameters.
37+ * The iteration order of the tiles will be as specified by the pseudo-code:
38+ * <pre>
39+ * int bbox[] = {left, top, right, bottom};
40+ * AATileGenerator aatg = renderengine.getAATileGenerator(..., bbox);
41+ * int tw = aatg.getTileWidth();
42+ * int th = aatg.getTileHeight();
43+ * byte tile[] = new byte[tw * th];
44+ * for (y = top; y < bottom; y += th) {
45+ * for (x = left; x < right; x += tw) {
46+ * int a = aatg.getTypicalAlpha();
47+ * int w = Math.min(tw, right-x);
48+ * int h = Math.min(th, bottom-y);
49+ * if (a == 0x00) {
50+ * // can skip this tile...
51+ * aatg.nextTile();
52+ * } else if (a == 0xff) {
53+ * // can treat this tile like a fillRect
54+ * aatg.nextTile();
55+ * doFill(x, y, w, h);
56+ * } else {
57+ * aatg.getAlpha(tile, 0, tw);
58+ * handleAlpha(tile, x, y, w, h);
59+ * }
60+ * }
61+ * }
62+ * aatg.dispose();
63+ * </pre>
64+ * The bounding box for the iteration will be returned by the
65+ * {@code RenderingEngine} via an argument to the getAATileGenerator() method.
66+ */
67+public interface AATileGenerator {
68+ /**
69+ * Gets the width of the tiles that the generator batches output into.
70+ * @return the width of the standard alpha tile
71+ */
72+ public int getTileWidth();
73+
74+ /**
75+ * Gets the height of the tiles that the generator batches output into.
76+ * @return the height of the standard alpha tile
77+ */
78+ public int getTileHeight();
79+
80+ /**
81+ * Gets the typical alpha value that will characterize the current
82+ * tile.
83+ * The answer may be 0x00 to indicate that the current tile has
84+ * no coverage in any of its pixels, or it may be 0xff to indicate
85+ * that the current tile is completely covered by the path, or any
86+ * other value to indicate non-trivial coverage cases.
87+ * @return 0x00 for no coverage, 0xff for total coverage, or any other
88+ * value for partial coverage of the tile
89+ */
90+ public int getTypicalAlpha();
91+
92+ /**
93+ * Skips the current tile and moves on to the next tile.
94+ * Either this method, or the getAlpha() method should be called
95+ * once per tile, but not both.
96+ */
97+ public void nextTile();
98+
99+ /**
100+ * Gets the alpha coverage values for the current tile.
101+ * Either this method, or the nextTile() method should be called
102+ * once per tile, but not both.
103+ */
104+ public void getAlpha(byte tile[], int offset, int rowstride);
105+
106+ /**
107+ * Disposes this tile generator.
108+ * No further calls will be made on this instance.
109+ */
110+ public void dispose();
111+}
java/pkg/sun/java2d/pipe/AlphaColorPipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/AlphaColorPipe.java+90−0
@@ -0,0 +1,90 @@
1+/*
2+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Rectangle;
29+import java.awt.Shape;
30+import sun.java2d.SunGraphics2D;
31+
32+/**
33+ * This class implements a CompositePipe that renders path alpha tiles
34+ * into a destination that supports direct alpha compositing of a solid
35+ * color, according to one of the rules in the AlphaComposite class.
36+ */
37+public class AlphaColorPipe implements CompositePipe, ParallelogramPipe {
38+ public AlphaColorPipe() {
39+ }
40+
41+ public Object startSequence(SunGraphics2D sg, Shape s, Rectangle dev,
42+ int[] abox) {
43+ return sg;
44+ }
45+
46+ public boolean needTile(Object context, int x, int y, int w, int h) {
47+ return true;
48+ }
49+
50+ public void renderPathTile(Object context,
51+ byte[] atile, int offset, int tilesize,
52+ int x, int y, int w, int h) {
53+ SunGraphics2D sg = (SunGraphics2D) context;
54+
55+ sg.alphafill.MaskFill(sg, sg.getSurfaceData(), sg.composite,
56+ x, y, w, h,
57+ atile, offset, tilesize);
58+ }
59+
60+ public void skipTile(Object context, int x, int y) {
61+ return;
62+ }
63+
64+ public void endSequence(Object context) {
65+ return;
66+ }
67+
68+ public void fillParallelogram(SunGraphics2D sg,
69+ double ux1, double uy1,
70+ double ux2, double uy2,
71+ double x, double y,
72+ double dx1, double dy1,
73+ double dx2, double dy2)
74+ {
75+ sg.alphafill.FillAAPgram(sg, sg.getSurfaceData(), sg.composite,
76+ x, y, dx1, dy1, dx2, dy2);
77+ }
78+
79+ public void drawParallelogram(SunGraphics2D sg,
80+ double ux1, double uy1,
81+ double ux2, double uy2,
82+ double x, double y,
83+ double dx1, double dy1,
84+ double dx2, double dy2,
85+ double lw1, double lw2)
86+ {
87+ sg.alphafill.DrawAAPgram(sg, sg.getSurfaceData(), sg.composite,
88+ x, y, dx1, dy1, dx2, dy2, lw1, lw2);
89+ }
90+}
java/pkg/sun/java2d/pipe/AlphaPaintPipe$TileContext.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/AlphaPaintPipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/AlphaPaintPipe.java+206−0
@@ -0,0 +1,206 @@
1+/*
2+ * Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.lang.ref.WeakReference;
29+import java.awt.Rectangle;
30+import java.awt.Shape;
31+import java.awt.PaintContext;
32+import java.awt.Transparency;
33+import java.awt.image.ColorModel;
34+import java.awt.image.Raster;
35+import java.awt.image.WritableRaster;
36+import java.awt.image.BufferedImage;
37+import sun.awt.image.BufImgSurfaceData;
38+import sun.java2d.SunGraphics2D;
39+import sun.java2d.SurfaceData;
40+import sun.java2d.loops.Blit;
41+import sun.java2d.loops.MaskBlit;
42+import sun.java2d.loops.CompositeType;
43+import sun.java2d.loops.GraphicsPrimitiveMgr;
44+
45+/**
46+ * This class implements a CompositePipe that renders path alpha tiles
47+ * into a destination according to the Composite attribute of a
48+ * SunGraphics2D.
49+ */
50+public class AlphaPaintPipe implements CompositePipe {
51+ static WeakReference cachedLastRaster;
52+ static WeakReference cachedLastColorModel;
53+ static WeakReference cachedLastData;
54+
55+ static class TileContext {
56+ SunGraphics2D sunG2D;
57+ PaintContext paintCtxt;
58+ ColorModel paintModel;
59+ WeakReference lastRaster;
60+ WeakReference lastData;
61+ MaskBlit lastMask;
62+ Blit lastBlit;
63+ SurfaceData dstData;
64+
65+ public TileContext(SunGraphics2D sg, PaintContext pc) {
66+ sunG2D = sg;
67+ paintCtxt = pc;
68+ paintModel = pc.getColorModel();
69+ dstData = sg.getSurfaceData();
70+ synchronized (AlphaPaintPipe.class) {
71+ if (cachedLastColorModel != null &&
72+ cachedLastColorModel.get() == paintModel)
73+ {
74+ this.lastRaster = cachedLastRaster;
75+ this.lastData = cachedLastData;
76+ }
77+ }
78+ }
79+ }
80+
81+ public Object startSequence(SunGraphics2D sg, Shape s, Rectangle devR,
82+ int[] abox) {
83+ PaintContext paintContext =
84+ sg.paint.createContext(sg.getDeviceColorModel(),
85+ devR,
86+ s.getBounds2D(),
87+ sg.cloneTransform(),
88+ sg.getRenderingHints());
89+ return new TileContext(sg, paintContext);
90+ }
91+
92+ public boolean needTile(Object context, int x, int y, int w, int h) {
93+ return true;
94+ }
95+
96+ private static final int TILE_SIZE = 32;
97+
98+ public void renderPathTile(Object ctx,
99+ byte[] atile, int offset, int tilesize,
100+ int x, int y, int w, int h) {
101+ TileContext context = (TileContext) ctx;
102+ PaintContext paintCtxt = context.paintCtxt;
103+ SunGraphics2D sg = context.sunG2D;
104+ SurfaceData dstData = context.dstData;
105+ SurfaceData srcData = null;
106+ Raster lastRas = null;
107+ if (context.lastData != null && context.lastRaster != null) {
108+ srcData = (SurfaceData) context.lastData.get();
109+ lastRas = (Raster) context.lastRaster.get();
110+ if (srcData == null || lastRas == null) {
111+ srcData = null;
112+ lastRas = null;
113+ }
114+ }
115+ ColorModel paintModel = context.paintModel;
116+
117+ for (int rely = 0; rely < h; rely += TILE_SIZE) {
118+ int ty = y + rely;
119+ int th = Math.min(h-rely, TILE_SIZE);
120+ for (int relx = 0; relx < w; relx += TILE_SIZE) {
121+ int tx = x + relx;
122+ int tw = Math.min(w-relx, TILE_SIZE);
123+
124+ Raster srcRaster = paintCtxt.getRaster(tx, ty, tw, th);
125+ if ((srcRaster.getMinX() != 0) || (srcRaster.getMinY() != 0)) {
126+ srcRaster = srcRaster.createTranslatedChild(0, 0);
127+ }
128+ if (lastRas != srcRaster) {
129+ lastRas = srcRaster;
130+ context.lastRaster = new WeakReference(lastRas);
131+ // REMIND: This will fail for a non-Writable raster!
132+ BufferedImage bImg =
133+ new BufferedImage(paintModel,
134+ (WritableRaster) srcRaster,
135+ paintModel.isAlphaPremultiplied(),
136+ null);
137+ srcData = BufImgSurfaceData.createData(bImg);
138+ context.lastData = new WeakReference(srcData);
139+ context.lastMask = null;
140+ context.lastBlit = null;
141+ }
142+
143+ if (atile == null) {
144+ if (context.lastBlit == null) {
145+ CompositeType comptype = sg.imageComp;
146+ if (CompositeType.SrcOverNoEa.equals(comptype) &&
147+ paintModel.getTransparency() == Transparency.OPAQUE)
148+ {
149+ comptype = CompositeType.SrcNoEa;
150+ }
151+ context.lastBlit =
152+ Blit.getFromCache(srcData.getSurfaceType(),
153+ comptype,
154+ dstData.getSurfaceType());
155+ }
156+ context.lastBlit.Blit(srcData, dstData,
157+ sg.composite, null,
158+ 0, 0, tx, ty, tw, th);
159+ } else {
160+ if (context.lastMask == null) {
161+ CompositeType comptype = sg.imageComp;
162+ if (CompositeType.SrcOverNoEa.equals(comptype) &&
163+ paintModel.getTransparency() == Transparency.OPAQUE)
164+ {
165+ comptype = CompositeType.SrcNoEa;
166+ }
167+ context.lastMask =
168+ MaskBlit.getFromCache(srcData.getSurfaceType(),
169+ comptype,
170+ dstData.getSurfaceType());
171+ }
172+
173+ int toff = offset + rely * tilesize + relx;
174+ context.lastMask.MaskBlit(srcData, dstData,
175+ sg.composite, null,
176+ 0, 0, tx, ty, tw, th,
177+ atile, toff, tilesize);
178+ }
179+ }
180+ }
181+ }
182+
183+ public void skipTile(Object context, int x, int y) {
184+ return;
185+ }
186+
187+ public void endSequence(Object ctx) {
188+ TileContext context = (TileContext) ctx;
189+ if (context.paintCtxt != null) {
190+ context.paintCtxt.dispose();
191+ }
192+ synchronized (AlphaPaintPipe.class) {
193+ if (context.lastData != null) {
194+ cachedLastRaster = context.lastRaster;
195+ if (cachedLastColorModel == null ||
196+ cachedLastColorModel.get() != context.paintModel)
197+ {
198+ // Avoid creating new WeakReference if possible
199+ cachedLastColorModel =
200+ new WeakReference(context.paintModel);
201+ }
202+ cachedLastData = context.lastData;
203+ }
204+ }
205+ }
206+}
java/pkg/sun/java2d/pipe/BufferedBufImgOps.java+393−0
@@ -0,0 +1,393 @@
1+/*
2+ * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.color.ColorSpace;
29+import java.awt.image.AffineTransformOp;
30+import java.awt.image.BufferedImage;
31+import java.awt.image.BufferedImageOp;
32+import java.awt.image.BufferedImageOp;
33+import java.awt.image.ByteLookupTable;
34+import java.awt.image.ColorModel;
35+import java.awt.image.ConvolveOp;
36+import java.awt.image.IndexColorModel;
37+import java.awt.image.Kernel;
38+import java.awt.image.LookupOp;
39+import java.awt.image.LookupTable;
40+import java.awt.image.RescaleOp;
41+import java.awt.image.ShortLookupTable;
42+import sun.java2d.SurfaceData;
43+import sun.java2d.loops.CompositeType;
44+import static sun.java2d.pipe.BufferedOpCodes.*;
45+
46+public class BufferedBufImgOps {
47+
48+ public static void enableBufImgOp(RenderQueue rq, SurfaceData srcData,
49+ BufferedImage srcImg,
50+ BufferedImageOp biop)
51+ {
52+ if (biop instanceof ConvolveOp) {
53+ enableConvolveOp(rq, srcData, (ConvolveOp)biop);
54+ } else if (biop instanceof RescaleOp) {
55+ enableRescaleOp(rq, srcData, srcImg, (RescaleOp)biop);
56+ } else if (biop instanceof LookupOp) {
57+ enableLookupOp(rq, srcData, srcImg, (LookupOp)biop);
58+ } else {
59+ throw new InternalError("Unknown BufferedImageOp");
60+ }
61+ }
62+
63+ public static void disableBufImgOp(RenderQueue rq, BufferedImageOp biop) {
64+ if (biop instanceof ConvolveOp) {
65+ disableConvolveOp(rq);
66+ } else if (biop instanceof RescaleOp) {
67+ disableRescaleOp(rq);
68+ } else if (biop instanceof LookupOp) {
69+ disableLookupOp(rq);
70+ } else {
71+ throw new InternalError("Unknown BufferedImageOp");
72+ }
73+ }
74+
75+/**************************** ConvolveOp support ****************************/
76+
77+ public static boolean isConvolveOpValid(ConvolveOp cop) {
78+ Kernel kernel = cop.getKernel();
79+ int kw = kernel.getWidth();
80+ int kh = kernel.getHeight();
81+ // REMIND: we currently can only handle 3x3 and 5x5 kernels,
82+ // but hopefully this is just a temporary restriction;
83+ // see native shader comments for more details
84+ if (!(kw == 3 && kh == 3) && !(kw == 5 && kh == 5)) {
85+ return false;
86+ }
87+ return true;
88+ }
89+
90+ private static void enableConvolveOp(RenderQueue rq,
91+ SurfaceData srcData,
92+ ConvolveOp cop)
93+ {
94+ // assert rq.lock.isHeldByCurrentThread();
95+ boolean edgeZero =
96+ cop.getEdgeCondition() == ConvolveOp.EDGE_ZERO_FILL;
97+ Kernel kernel = cop.getKernel();
98+ int kernelWidth = kernel.getWidth();
99+ int kernelHeight = kernel.getHeight();
100+ int kernelSize = kernelWidth * kernelHeight;
101+ int sizeofFloat = 4;
102+ int totalBytesRequired = 4 + 8 + 12 + (kernelSize * sizeofFloat);
103+
104+ RenderBuffer buf = rq.getBuffer();
105+ rq.ensureCapacityAndAlignment(totalBytesRequired, 4);
106+ buf.putInt(ENABLE_CONVOLVE_OP);
107+ buf.putLong(srcData.getNativeOps());
108+ buf.putInt(edgeZero ? 1 : 0);
109+ buf.putInt(kernelWidth);
110+ buf.putInt(kernelHeight);
111+ buf.put(kernel.getKernelData(null));
112+ }
113+
114+ private static void disableConvolveOp(RenderQueue rq) {
115+ // assert rq.lock.isHeldByCurrentThread();
116+ RenderBuffer buf = rq.getBuffer();
117+ rq.ensureCapacity(4);
118+ buf.putInt(DISABLE_CONVOLVE_OP);
119+ }
120+
121+/**************************** RescaleOp support *****************************/
122+
123+ public static boolean isRescaleOpValid(RescaleOp rop,
124+ BufferedImage srcImg)
125+ {
126+ int numFactors = rop.getNumFactors();
127+ ColorModel srcCM = srcImg.getColorModel();
128+
129+ if (srcCM instanceof IndexColorModel) {
130+ throw new
131+ IllegalArgumentException("Rescaling cannot be "+
132+ "performed on an indexed image");
133+ }
134+ if (numFactors != 1 &&
135+ numFactors != srcCM.getNumColorComponents() &&
136+ numFactors != srcCM.getNumComponents())
137+ {
138+ throw new IllegalArgumentException("Number of scaling constants "+
139+ "does not equal the number of"+
140+ " of color or color/alpha "+
141+ " components");
142+ }
143+
144+ int csType = srcCM.getColorSpace().getType();
145+ if (csType != ColorSpace.TYPE_RGB &&
146+ csType != ColorSpace.TYPE_GRAY)
147+ {
148+ // Not prepared to deal with other color spaces
149+ return false;
150+ }
151+
152+ if (numFactors == 2 || numFactors > 4) {
153+ // Not really prepared to handle this at the native level, so...
154+ return false;
155+ }
156+
157+ return true;
158+ }
159+
160+ private static void enableRescaleOp(RenderQueue rq,
161+ SurfaceData srcData,
162+ BufferedImage srcImg,
163+ RescaleOp rop)
164+ {
165+ // assert rq.lock.isHeldByCurrentThread();
166+ ColorModel srcCM = srcImg.getColorModel();
167+ boolean nonPremult =
168+ srcCM.hasAlpha() &&
169+ srcCM.isAlphaPremultiplied();
170+
171+ /*
172+ * Note: The user-provided scale factors and offsets are arranged
173+ * in R/G/B/A order, regardless of the raw data order of the
174+ * underlying Raster/DataBuffer. The source image data is ultimately
175+ * converted into RGBA data when uploaded to an OpenGL texture
176+ * (even for TYPE_GRAY), so the scale factors and offsets are already
177+ * in the order expected by the native OpenGL code.
178+ *
179+ * However, the offsets provided by the user are in a range dictated
180+ * by the size of each color/alpha band in the source image. For
181+ * example, for 8/8/8 data each offset is in the range [0,255],
182+ * for 5/5/5 data each offset is in the range [0,31], and so on.
183+ * The OpenGL shader only thinks in terms of [0,1], so below we need
184+ * to normalize the user-provided offset values into the range [0,1].
185+ */
186+ int numFactors = rop.getNumFactors();
187+ float[] origScaleFactors = rop.getScaleFactors(null);
188+ float[] origOffsets = rop.getOffsets(null);
189+
190+ // To make things easier, we will always pass all four bands
191+ // down to native code...
192+ float[] normScaleFactors;
193+ float[] normOffsets;
194+
195+ if (numFactors == 1) {
196+ normScaleFactors = new float[4];
197+ normOffsets = new float[4];
198+ for (int i = 0; i < 3; i++) {
199+ normScaleFactors[i] = origScaleFactors[0];
200+ normOffsets[i] = origOffsets[0];
201+ }
202+ // Leave alpha untouched...
203+ normScaleFactors[3] = 1.0f;
204+ normOffsets[3] = 0.0f;
205+ } else if (numFactors == 3) {
206+ normScaleFactors = new float[4];
207+ normOffsets = new float[4];
208+ for (int i = 0; i < 3; i++) {
209+ normScaleFactors[i] = origScaleFactors[i];
210+ normOffsets[i] = origOffsets[i];
211+ }
212+ // Leave alpha untouched...
213+ normScaleFactors[3] = 1.0f;
214+ normOffsets[3] = 0.0f;
215+ } else { // (numFactors == 4)
216+ normScaleFactors = origScaleFactors;
217+ normOffsets = origOffsets;
218+ }
219+
220+ // The user-provided offsets are specified in the range
221+ // of each source color band, but the OpenGL shader only wants
222+ // to deal with data in the range [0,1], so we need to normalize
223+ // each offset value to the range [0,1] here.
224+ if (srcCM.getNumComponents() == 1) {
225+ // Gray data
226+ int nBits = srcCM.getComponentSize(0);
227+ int maxValue = (1 << nBits) - 1;
228+ for (int i = 0; i < 3; i++) {
229+ normOffsets[i] /= maxValue;
230+ }
231+ } else {
232+ // RGB(A) data
233+ for (int i = 0; i < srcCM.getNumComponents(); i++) {
234+ int nBits = srcCM.getComponentSize(i);
235+ int maxValue = (1 << nBits) - 1;
236+ normOffsets[i] /= maxValue;
237+ }
238+ }
239+
240+ int sizeofFloat = 4;
241+ int totalBytesRequired = 4 + 8 + 4 + (4 * sizeofFloat * 2);
242+
243+ RenderBuffer buf = rq.getBuffer();
244+ rq.ensureCapacityAndAlignment(totalBytesRequired, 4);
245+ buf.putInt(ENABLE_RESCALE_OP);
246+ buf.putLong(srcData.getNativeOps());
247+ buf.putInt(nonPremult ? 1 : 0);
248+ buf.put(normScaleFactors);
249+ buf.put(normOffsets);
250+ }
251+
252+ private static void disableRescaleOp(RenderQueue rq) {
253+ // assert rq.lock.isHeldByCurrentThread();
254+ RenderBuffer buf = rq.getBuffer();
255+ rq.ensureCapacity(4);
256+ buf.putInt(DISABLE_RESCALE_OP);
257+ }
258+
259+/**************************** LookupOp support ******************************/
260+
261+ public static boolean isLookupOpValid(LookupOp lop,
262+ BufferedImage srcImg)
263+ {
264+ LookupTable table = lop.getTable();
265+ int numComps = table.getNumComponents();
266+ ColorModel srcCM = srcImg.getColorModel();
267+
268+ if (srcCM instanceof IndexColorModel) {
269+ throw new
270+ IllegalArgumentException("LookupOp cannot be "+
271+ "performed on an indexed image");
272+ }
273+ if (numComps != 1 &&
274+ numComps != srcCM.getNumComponents() &&
275+ numComps != srcCM.getNumColorComponents())
276+ {
277+ throw new IllegalArgumentException("Number of arrays in the "+
278+ " lookup table ("+
279+ numComps+
280+ ") is not compatible with"+
281+ " the src image: "+srcImg);
282+ }
283+
284+ int csType = srcCM.getColorSpace().getType();
285+ if (csType != ColorSpace.TYPE_RGB &&
286+ csType != ColorSpace.TYPE_GRAY)
287+ {
288+ // Not prepared to deal with other color spaces
289+ return false;
290+ }
291+
292+ if (numComps == 2 || numComps > 4) {
293+ // Not really prepared to handle this at the native level, so...
294+ return false;
295+ }
296+
297+ // The LookupTable spec says that "all arrays must be the
298+ // same size" but unfortunately the constructors do not
299+ // enforce that. Also, our native code only works with
300+ // arrays no larger than 256 elements, so check both of
301+ // these restrictions here.
302+ if (table instanceof ByteLookupTable) {
303+ byte[][] data = ((ByteLookupTable)table).getTable();
304+ for (int i = 1; i < data.length; i++) {
305+ if (data[i].length > 256 ||
306+ data[i].length != data[i-1].length)
307+ {
308+ return false;
309+ }
310+ }
311+ } else if (table instanceof ShortLookupTable) {
312+ short[][] data = ((ShortLookupTable)table).getTable();
313+ for (int i = 1; i < data.length; i++) {
314+ if (data[i].length > 256 ||
315+ data[i].length != data[i-1].length)
316+ {
317+ return false;
318+ }
319+ }
320+ } else {
321+ return false;
322+ }
323+
324+ return true;
325+ }
326+
327+ private static void enableLookupOp(RenderQueue rq,
328+ SurfaceData srcData,
329+ BufferedImage srcImg,
330+ LookupOp lop)
331+ {
332+ // assert rq.lock.isHeldByCurrentThread();
333+ boolean nonPremult =
334+ srcImg.getColorModel().hasAlpha() &&
335+ srcImg.isAlphaPremultiplied();
336+
337+ LookupTable table = lop.getTable();
338+ int numBands = table.getNumComponents();
339+ int offset = table.getOffset();
340+ int bandLength;
341+ int bytesPerElem;
342+ boolean shortData;
343+
344+ if (table instanceof ShortLookupTable) {
345+ short[][] data = ((ShortLookupTable)table).getTable();
346+ bandLength = data[0].length;
347+ bytesPerElem = 2;
348+ shortData = true;
349+ } else { // (table instanceof ByteLookupTable)
350+ byte[][] data = ((ByteLookupTable)table).getTable();
351+ bandLength = data[0].length;
352+ bytesPerElem = 1;
353+ shortData = false;
354+ }
355+
356+ // Adjust the LUT length so that it ends on a 4-byte boundary
357+ int totalLutBytes = numBands * bandLength * bytesPerElem;
358+ int paddedLutBytes = (totalLutBytes + 3) & (~3);
359+ int padding = paddedLutBytes - totalLutBytes;
360+ int totalBytesRequired = 4 + 8 + 20 + paddedLutBytes;
361+
362+ RenderBuffer buf = rq.getBuffer();
363+ rq.ensureCapacityAndAlignment(totalBytesRequired, 4);
364+ buf.putInt(ENABLE_LOOKUP_OP);
365+ buf.putLong(srcData.getNativeOps());
366+ buf.putInt(nonPremult ? 1 : 0);
367+ buf.putInt(shortData ? 1 : 0);
368+ buf.putInt(numBands);
369+ buf.putInt(bandLength);
370+ buf.putInt(offset);
371+ if (shortData) {
372+ short[][] data = ((ShortLookupTable)table).getTable();
373+ for (int i = 0; i < numBands; i++) {
374+ buf.put(data[i]);
375+ }
376+ } else {
377+ byte[][] data = ((ByteLookupTable)table).getTable();
378+ for (int i = 0; i < numBands; i++) {
379+ buf.put(data[i]);
380+ }
381+ }
382+ if (padding != 0) {
383+ buf.position(buf.position() + padding);
384+ }
385+ }
386+
387+ private static void disableLookupOp(RenderQueue rq) {
388+ // assert rq.lock.isHeldByCurrentThread();
389+ RenderBuffer buf = rq.getBuffer();
390+ rq.ensureCapacity(4);
391+ buf.putInt(DISABLE_LOOKUP_OP);
392+ }
393+}
java/pkg/sun/java2d/pipe/BufferedContext.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/BufferedContext.java+470−0
@@ -0,0 +1,470 @@
1+/*
2+ * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.AlphaComposite;
29+import java.awt.Color;
30+import java.awt.Composite;
31+import java.awt.Paint;
32+import java.awt.geom.AffineTransform;
33+import sun.java2d.pipe.hw.AccelSurface;
34+import sun.java2d.InvalidPipeException;
35+import sun.java2d.SunGraphics2D;
36+import sun.java2d.loops.XORComposite;
37+import static sun.java2d.pipe.BufferedOpCodes.*;
38+import static sun.java2d.pipe.BufferedRenderPipe.BYTES_PER_SPAN;
39+
40+/**
41+ * Base context class for managing state in a single-threaded rendering
42+ * environment. Each state-setting operation (e.g. SET_COLOR) is added to
43+ * the provided RenderQueue, which will be processed at a later time by a
44+ * single thread. Note that the RenderQueue lock must be acquired before
45+ * calling the validate() method (or any other method in this class). See
46+ * the RenderQueue class comments for a sample usage scenario.
47+ *
48+ * @see RenderQueue
49+ */
50+public abstract class BufferedContext {
51+
52+ /*
53+ * The following flags help the internals of validate() determine
54+ * the appropriate (meaning correct, or optimal) code path when
55+ * setting up the current context. The flags can be bitwise OR'd
56+ * together as needed.
57+ */
58+
59+ /**
60+ * Indicates that no flags are needed; take all default code paths.
61+ */
62+ public static final int NO_CONTEXT_FLAGS = (0 << 0);
63+ /**
64+ * Indicates that the source surface (or color value, if it is a simple
65+ * rendering operation) is opaque (has an alpha value of 1.0). If this
66+ * flag is present, it allows us to disable blending in certain
67+ * situations in order to improve performance.
68+ */
69+ public static final int SRC_IS_OPAQUE = (1 << 0);
70+ /**
71+ * Indicates that the operation uses an alpha mask, which may determine
72+ * the code path that is used when setting up the current paint state.
73+ */
74+ public static final int USE_MASK = (1 << 1);
75+
76+ protected RenderQueue rq;
77+ protected RenderBuffer buf;
78+
79+ /**
80+ * This is a reference to the most recently validated BufferedContext. If
81+ * this value is null, it means that there is no current context. It is
82+ * provided here so that validate() only needs to do a quick reference
83+ * check to see if the BufferedContext passed to that method is the same
84+ * as the one we've cached here.
85+ */
86+ protected static BufferedContext currentContext;
87+
88+ private AccelSurface validatedSrcData;
89+ private AccelSurface validatedDstData;
90+ private Region validatedClip;
91+ private Composite validatedComp;
92+ private Paint validatedPaint;
93+ // renamed from isValidatedPaintAColor as part of a work around for 6764257
94+ private boolean isValidatedPaintJustAColor;
95+ private int validatedRGB;
96+ private int validatedFlags;
97+ private boolean xformInUse;
98+ private int transX;
99+ private int transY;
100+
101+ protected BufferedContext(RenderQueue rq) {
102+ this.rq = rq;
103+ this.buf = rq.getBuffer();
104+ }
105+
106+ /**
107+ * Fetches the BufferedContextContext associated with the dst. surface
108+ * and validates the context using the given parameters. Most rendering
109+ * operations will call this method first in order to set the necessary
110+ * state before issuing rendering commands.
111+ *
112+ * Note: must be called while the RenderQueue lock is held.
113+ *
114+ * @throws InvalidPipeException if either src or dest surface is not valid
115+ * or lost
116+ * @see RenderQueue#lock
117+ * @see RenderQueue#unlock
118+ */
119+ public static void validateContext(AccelSurface srcData,
120+ AccelSurface dstData,
121+ Region clip, Composite comp,
122+ AffineTransform xform,
123+ Paint paint, SunGraphics2D sg2d,
124+ int flags)
125+ {
126+ // assert rq.lock.isHeldByCurrentThread();
127+ BufferedContext d3dc = dstData.getContext();
128+ d3dc.validate(srcData, dstData,
129+ clip, comp, xform, paint, sg2d, flags);
130+ }
131+
132+ /**
133+ * Fetches the BufferedContextassociated with the surface
134+ * and disables all context state settings.
135+ *
136+ * Note: must be called while the RenderQueue lock is held.
137+ *
138+ * @throws InvalidPipeException if the surface is not valid
139+ * or lost
140+ * @see RenderQueue#lock
141+ * @see RenderQueue#unlock
142+ */
143+ public static void validateContext(AccelSurface surface) {
144+ // assert rt.lock.isHeldByCurrentThread();
145+ validateContext(surface, surface,
146+ null, null, null, null, null, NO_CONTEXT_FLAGS);
147+ }
148+
149+ /**
150+ * Validates the given parameters against the current state for this
151+ * context. If this context is not current, it will be made current
152+ * for the given source and destination surfaces, and the viewport will
153+ * be updated. Then each part of the context state (clip, composite,
154+ * etc.) is checked against the previous value. If the value has changed
155+ * since the last call to validate(), it will be updated accordingly.
156+ *
157+ * Note that the SunGraphics2D parameter is only used for the purposes
158+ * of validating a (non-null) Paint parameter. In all other cases it
159+ * is safe to pass a null SunGraphics2D and it will be ignored.
160+ *
161+ * Note: must be called while the RenderQueue lock is held.
162+ *
163+ * @throws InvalidPipeException if either src or dest surface is not valid
164+ * or lost
165+ */
166+ public void validate(AccelSurface srcData, AccelSurface dstData,
167+ Region clip, Composite comp,
168+ AffineTransform xform,
169+ Paint paint, SunGraphics2D sg2d, int flags)
170+ {
171+ // assert rq.lock.isHeldByCurrentThread();
172+
173+ boolean updateClip = false;
174+ boolean updatePaint = false;
175+
176+ if (!dstData.isValid() ||
177+ dstData.isSurfaceLost() || srcData.isSurfaceLost())
178+ {
179+ invalidateContext();
180+ throw new InvalidPipeException("bounds changed or surface lost");
181+ }
182+
183+ if (paint instanceof Color) {
184+ // REMIND: not 30-bit friendly
185+ int newRGB = ((Color)paint).getRGB();
186+ if (isValidatedPaintJustAColor) {
187+ if (newRGB != validatedRGB) {
188+ validatedRGB = newRGB;
189+ updatePaint = true;
190+ }
191+ } else {
192+ validatedRGB = newRGB;
193+ updatePaint = true;
194+ isValidatedPaintJustAColor = true;
195+ }
196+ } else if (validatedPaint != paint) {
197+ updatePaint = true;
198+ // this should be set when we are switching from paint to color
199+ // in which case this condition will be true
200+ isValidatedPaintJustAColor = false;
201+ }
202+
203+ if ((currentContext != this) ||
204+ (srcData != validatedSrcData) ||
205+ (dstData != validatedDstData))
206+ {
207+ if (dstData != validatedDstData) {
208+ // the clip is dependent on the destination surface, so we
209+ // need to update it if we have a new destination surface
210+ updateClip = true;
211+ }
212+
213+ if (paint == null) {
214+ // make sure we update the color state (otherwise, it might
215+ // not be updated if this is the first time the context
216+ // is being validated)
217+ updatePaint = true;
218+ }
219+
220+ // update the current source and destination surfaces
221+ setSurfaces(srcData, dstData);
222+
223+ currentContext = this;
224+ validatedSrcData = srcData;
225+ validatedDstData = dstData;
226+ }
227+
228+ // validate clip
229+ if ((clip != validatedClip) || updateClip) {
230+ if (clip != null) {
231+ if (updateClip ||
232+ validatedClip == null ||
233+ !(validatedClip.isRectangular() && clip.isRectangular()) ||
234+ ((clip.getLoX() != validatedClip.getLoX() ||
235+ clip.getLoY() != validatedClip.getLoY() ||
236+ clip.getHiX() != validatedClip.getHiX() ||
237+ clip.getHiY() != validatedClip.getHiY())))
238+ {
239+ setClip(clip);
240+ }
241+ } else {
242+ resetClip();
243+ }
244+ validatedClip = clip;
245+ }
246+
247+ // validate composite (note that a change in the context flags
248+ // may require us to update the composite state, even if the
249+ // composite has not changed)
250+ if ((comp != validatedComp) || (flags != validatedFlags)) {
251+ if (comp != null) {
252+ setComposite(comp, flags);
253+ } else {
254+ resetComposite();
255+ }
256+ // the paint state is dependent on the composite state, so make
257+ // sure we update the color below
258+ updatePaint = true;
259+ validatedComp = comp;
260+ validatedFlags = flags;
261+ }
262+
263+ // validate transform
264+ boolean txChanged = false;
265+ if (xform == null) {
266+ if (xformInUse) {
267+ resetTransform();
268+ xformInUse = false;
269+ txChanged = true;
270+ } else if (sg2d != null) {
271+ if (transX != sg2d.transX || transY != sg2d.transY) {
272+ txChanged = true;
273+ }
274+ }
275+ if (sg2d != null) {
276+ transX = sg2d.transX;
277+ transY = sg2d.transY;
278+ }
279+ } else {
280+ setTransform(xform);
281+ xformInUse = true;
282+ txChanged = true;
283+ }
284+ // non-Color paints may require paint revalidation
285+ if (!isValidatedPaintJustAColor && txChanged) {
286+ updatePaint = true;
287+ }
288+
289+ // validate paint
290+ if (updatePaint) {
291+ if (paint != null) {
292+ BufferedPaints.setPaint(rq, sg2d, paint, flags);
293+ } else {
294+ BufferedPaints.resetPaint(rq);
295+ }
296+ validatedPaint = paint;
297+ }
298+
299+ // mark dstData dirty
300+ // REMIND: is this really needed now? we do it in SunGraphics2D..
301+ dstData.markDirty();
302+ }
303+
304+ /**
305+ * Invalidates the surfaces associated with this context. This is
306+ * useful when the context is no longer needed, and we want to break
307+ * the chain caused by these surface references.
308+ *
309+ * Note: must be called while the RenderQueue lock is held.
310+ *
311+ * @see RenderQueue#lock
312+ * @see RenderQueue#unlock
313+ */
314+ public void invalidateSurfaces() {
315+ validatedSrcData = null;
316+ validatedDstData = null;
317+ }
318+
319+ private void setSurfaces(AccelSurface srcData,
320+ AccelSurface dstData)
321+ {
322+ // assert rq.lock.isHeldByCurrentThread();
323+ rq.ensureCapacityAndAlignment(20, 4);
324+ buf.putInt(SET_SURFACES);
325+ buf.putLong(srcData.getNativeOps());
326+ buf.putLong(dstData.getNativeOps());
327+ }
328+
329+ private void resetClip() {
330+ // assert rq.lock.isHeldByCurrentThread();
331+ rq.ensureCapacity(4);
332+ buf.putInt(RESET_CLIP);
333+ }
334+
335+ private void setClip(Region clip) {
336+ // assert rq.lock.isHeldByCurrentThread();
337+ if (clip.isRectangular()) {
338+ rq.ensureCapacity(20);
339+ buf.putInt(SET_RECT_CLIP);
340+ buf.putInt(clip.getLoX()).putInt(clip.getLoY());
341+ buf.putInt(clip.getHiX()).putInt(clip.getHiY());
342+ } else {
343+ rq.ensureCapacity(28); // so that we have room for at least a span
344+ buf.putInt(BEGIN_SHAPE_CLIP);
345+ buf.putInt(SET_SHAPE_CLIP_SPANS);
346+ // include a placeholder for the span count
347+ int countIndex = buf.position();
348+ buf.putInt(0);
349+ int spanCount = 0;
350+ int remainingSpans = buf.remaining() / BYTES_PER_SPAN;
351+ int span[] = new int[4];
352+ SpanIterator si = clip.getSpanIterator();
353+ while (si.nextSpan(span)) {
354+ if (remainingSpans == 0) {
355+ buf.putInt(countIndex, spanCount);
356+ rq.flushNow();
357+ buf.putInt(SET_SHAPE_CLIP_SPANS);
358+ countIndex = buf.position();
359+ buf.putInt(0);
360+ spanCount = 0;
361+ remainingSpans = buf.remaining() / BYTES_PER_SPAN;
362+ }
363+ buf.putInt(span[0]); // x1
364+ buf.putInt(span[1]); // y1
365+ buf.putInt(span[2]); // x2
366+ buf.putInt(span[3]); // y2
367+ spanCount++;
368+ remainingSpans--;
369+ }
370+ buf.putInt(countIndex, spanCount);
371+ rq.ensureCapacity(4);
372+ buf.putInt(END_SHAPE_CLIP);
373+ }
374+ }
375+
376+ private void resetComposite() {
377+ // assert rq.lock.isHeldByCurrentThread();
378+ rq.ensureCapacity(4);
379+ buf.putInt(RESET_COMPOSITE);
380+ }
381+
382+ private void setComposite(Composite comp, int flags) {
383+ // assert rq.lock.isHeldByCurrentThread();
384+ if (comp instanceof AlphaComposite) {
385+ AlphaComposite ac = (AlphaComposite)comp;
386+ rq.ensureCapacity(16);
387+ buf.putInt(SET_ALPHA_COMPOSITE);
388+ buf.putInt(ac.getRule());
389+ buf.putFloat(ac.getAlpha());
390+ buf.putInt(flags);
391+ } else if (comp instanceof XORComposite) {
392+ int xorPixel = ((XORComposite)comp).getXorPixel();
393+ rq.ensureCapacity(8);
394+ buf.putInt(SET_XOR_COMPOSITE);
395+ buf.putInt(xorPixel);
396+ } else {
397+ throw new InternalError("not yet implemented");
398+ }
399+ }
400+
401+ private void resetTransform() {
402+ // assert rq.lock.isHeldByCurrentThread();
403+ rq.ensureCapacity(4);
404+ buf.putInt(RESET_TRANSFORM);
405+ }
406+
407+ private void setTransform(AffineTransform xform) {
408+ // assert rq.lock.isHeldByCurrentThread();
409+ rq.ensureCapacityAndAlignment(52, 4);
410+ buf.putInt(SET_TRANSFORM);
411+ buf.putDouble(xform.getScaleX());
412+ buf.putDouble(xform.getShearY());
413+ buf.putDouble(xform.getShearX());
414+ buf.putDouble(xform.getScaleY());
415+ buf.putDouble(xform.getTranslateX());
416+ buf.putDouble(xform.getTranslateY());
417+ }
418+
419+ /**
420+ * Resets this context's surfaces and all attributes.
421+ *
422+ * Note: must be called while the RenderQueue lock is held.
423+ *
424+ * @see RenderQueue#lock
425+ * @see RenderQueue#unlock
426+ */
427+ public void invalidateContext() {
428+ resetTransform();
429+ resetComposite();
430+ resetClip();
431+ BufferedPaints.resetPaint(rq);
432+ invalidateSurfaces();
433+ validatedComp = null;
434+ validatedClip = null;
435+ validatedPaint = null;
436+ isValidatedPaintJustAColor = false;
437+ xformInUse = false;
438+ }
439+
440+ /**
441+ * Returns a singleton {@code RenderQueue} object used by the rendering
442+ * pipeline.
443+ *
444+ * @return a render queue
445+ * @see RenderQueue
446+ */
447+ public abstract RenderQueue getRenderQueue();
448+
449+ /**
450+ * Saves the the state of this context.
451+ * It may reset the current context.
452+ *
453+ * Note: must be called while the RenderQueue lock is held.
454+ *
455+ * @see RenderQueue#lock
456+ * @see RenderQueue#unlock
457+ */
458+ public abstract void saveState();
459+
460+ /**
461+ * Restores the native state of this context.
462+ * It may reset the current context.
463+ *
464+ * Note: must be called while the RenderQueue lock is held.
465+ *
466+ * @see RenderQueue#lock
467+ * @see RenderQueue#unlock
468+ */
469+ public abstract void restoreState();
470+}
java/pkg/sun/java2d/pipe/BufferedMaskBlit.java+163−0
@@ -0,0 +1,163 @@
1+/*
2+ * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.AlphaComposite;
29+import java.awt.Composite;
30+import sun.java2d.SurfaceData;
31+import sun.java2d.loops.Blit;
32+import sun.java2d.loops.CompositeType;
33+import sun.java2d.loops.MaskBlit;
34+import sun.java2d.loops.SurfaceType;
35+import static sun.java2d.pipe.BufferedOpCodes.*;
36+
37+/**
38+ * The MaskBlit operation is expressed as:
39+ * dst = ((src <MODE> dst) * pathA) + (dst * (1 - pathA))
40+ *
41+ * The OGL/D3D implementation of the MaskBlit operation differs from the above
42+ * equation because it is not possible to perform such a complex operation in
43+ * OpenGL/Direct3D (without the use of advanced techniques like fragment
44+ * shaders and multitexturing). Therefore, the BufferedMaskBlit operation
45+ * is expressed as:
46+ * dst = (src * pathA) <SrcOver> dst
47+ *
48+ * This simplified formula is only equivalent to the "true" MaskBlit equation
49+ * in the following situations:
50+ * - <MODE> is SrcOver
51+ * - <MODE> is Src, extra alpha == 1.0, and the source surface is opaque
52+ *
53+ * Therefore, we register BufferedMaskBlit primitives for only the SurfaceType
54+ * and CompositeType restrictions mentioned above. In addition for the Src
55+ * case, we must override the composite with a SrcOver (no extra alpha)
56+ * instance, so that we set up the OpenGL/Direct3D blending mode to match the
57+ * BufferedMaskBlit equation.
58+ */
59+public abstract class BufferedMaskBlit extends MaskBlit {
60+
61+ private static final int ST_INT_ARGB = 0;
62+ private static final int ST_INT_ARGB_PRE = 1;
63+ private static final int ST_INT_RGB = 2;
64+ private static final int ST_INT_BGR = 3;
65+
66+ private final RenderQueue rq;
67+ private final int srcTypeVal;
68+ private Blit blitop;
69+
70+ protected BufferedMaskBlit(RenderQueue rq,
71+ SurfaceType srcType,
72+ CompositeType compType,
73+ SurfaceType dstType)
74+ {
75+ super(srcType, compType, dstType);
76+ this.rq = rq;
77+ if (srcType == SurfaceType.IntArgb) {
78+ this.srcTypeVal = ST_INT_ARGB;
79+ } else if (srcType == SurfaceType.IntArgbPre) {
80+ this.srcTypeVal = ST_INT_ARGB_PRE;
81+ } else if (srcType == SurfaceType.IntRgb) {
82+ this.srcTypeVal = ST_INT_RGB;
83+ } else if (srcType == SurfaceType.IntBgr) {
84+ this.srcTypeVal = ST_INT_BGR;
85+ } else {
86+ throw new InternalError("unrecognized source surface type");
87+ }
88+ }
89+
90+ @Override
91+ public void MaskBlit(SurfaceData src, SurfaceData dst,
92+ Composite comp, Region clip,
93+ int srcx, int srcy,
94+ int dstx, int dsty,
95+ int width, int height,
96+ byte[] mask, int maskoff, int maskscan)
97+ {
98+ if (width <= 0 || height <= 0) {
99+ return;
100+ }
101+
102+ if (mask == null) {
103+ // no mask involved; delegate to regular blit loop
104+ if (blitop == null) {
105+ blitop = Blit.getFromCache(src.getSurfaceType(),
106+ CompositeType.AnyAlpha,
107+ this.getDestType());
108+ }
109+ blitop.Blit(src, dst,
110+ comp, clip,
111+ srcx, srcy, dstx, dsty,
112+ width, height);
113+ return;
114+ }
115+
116+ AlphaComposite acomp = (AlphaComposite)comp;
117+ if (acomp.getRule() != AlphaComposite.SRC_OVER) {
118+ comp = AlphaComposite.SrcOver;
119+ }
120+
121+ rq.lock();
122+ try {
123+ validateContext(dst, comp, clip);
124+
125+ RenderBuffer buf = rq.getBuffer();
126+ int totalBytesRequired = 20 + (width * height * 4);
127+
128+ /*
129+ * REMIND: we should fix this so that it works with tiles that
130+ * are larger than the entire buffer, but the native
131+ * OGL/D3DMaskBlit isn't even prepared for tiles larger
132+ * than 32x32 pixels, so there's no urgency here...
133+ */
134+ rq.ensureCapacity(totalBytesRequired);
135+
136+ // enqueue parameters and tile pixels
137+ int newpos = enqueueTile(buf.getAddress(), buf.position(),
138+ src, src.getNativeOps(), srcTypeVal,
139+ mask, mask.length, maskoff, maskscan,
140+ srcx, srcy, dstx, dsty,
141+ width, height);
142+
143+ buf.position(newpos);
144+ } finally {
145+ rq.unlock();
146+ }
147+ }
148+
149+ private native int enqueueTile(long buf, int bpos,
150+ SurfaceData srcData,
151+ long pSrcOps, int srcType,
152+ byte[] mask, int masklen,
153+ int maskoff, int maskscan,
154+ int srcx, int srcy, int dstx, int dsty,
155+ int width, int height);
156+
157+ /**
158+ * Validates the context state using the given destination surface
159+ * and composite/clip values.
160+ */
161+ protected abstract void validateContext(SurfaceData dstData,
162+ Composite comp, Region clip);
163+}
java/pkg/sun/java2d/pipe/BufferedMaskFill.java+153−0
@@ -0,0 +1,153 @@
1+/*
2+ * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.AlphaComposite;
29+import java.awt.Composite;
30+import sun.java2d.SunGraphics2D;
31+import sun.java2d.SurfaceData;
32+import sun.java2d.loops.CompositeType;
33+import sun.java2d.loops.MaskFill;
34+import sun.java2d.loops.SurfaceType;
35+import static sun.java2d.pipe.BufferedOpCodes.*;
36+
37+/**
38+ * The MaskFill operation is expressed as:
39+ * dst = ((src <MODE> dst) * pathA) + (dst * (1 - pathA))
40+ *
41+ * The OGL/D3D implementation of the MaskFill operation differs from the above
42+ * equation because it is not possible to perform such a complex operation in
43+ * OpenGL/Direct3D (without the use of advanced techniques like fragment
44+ * shaders and multitexturing). Therefore, the BufferedMaskFill operation
45+ * is expressed as:
46+ * dst = (src * pathA) <SrcOver> dst
47+ *
48+ * This simplified formula is only equivalent to the "true" MaskFill equation
49+ * in the following situations:
50+ * - <MODE> is SrcOver
51+ * - <MODE> is Src, extra alpha == 1.0, and the source paint is opaque
52+ *
53+ * Therefore, we register BufferedMaskFill primitives for only the SurfaceType
54+ * and CompositeType restrictions mentioned above. In addition, for the
55+ * SrcNoEa case we must override the incoming composite with a SrcOver (no
56+ * extra alpha) instance, so that we set up the OpenGL/Direct3D blending
57+ * mode to match the BufferedMaskFill equation.
58+ */
59+public abstract class BufferedMaskFill extends MaskFill {
60+
61+ protected final RenderQueue rq;
62+
63+ protected BufferedMaskFill(RenderQueue rq,
64+ SurfaceType srcType,
65+ CompositeType compType,
66+ SurfaceType dstType)
67+ {
68+ super(srcType, compType, dstType);
69+ this.rq = rq;
70+ }
71+
72+ @Override
73+ public void MaskFill(SunGraphics2D sg2d, SurfaceData sData,
74+ Composite comp,
75+ final int x, final int y, final int w, final int h,
76+ final byte[] mask,
77+ final int maskoff, final int maskscan)
78+ {
79+ AlphaComposite acomp = (AlphaComposite)comp;
80+ if (acomp.getRule() != AlphaComposite.SRC_OVER) {
81+ comp = AlphaComposite.SrcOver;
82+ }
83+
84+ rq.lock();
85+ try {
86+ validateContext(sg2d, comp, BufferedContext.USE_MASK);
87+
88+ // we adjust the mask length so that the mask ends on a
89+ // 4-byte boundary
90+ int maskBytesRequired;
91+ if (mask != null) {
92+ // we adjust the mask length so that the mask ends on a
93+ // 4-byte boundary
94+ maskBytesRequired = (mask.length + 3) & (~3);
95+ } else {
96+ // mask not needed
97+ maskBytesRequired = 0;
98+ }
99+ int totalBytesRequired = 32 + maskBytesRequired;
100+
101+ RenderBuffer buf = rq.getBuffer();
102+ if (totalBytesRequired <= buf.capacity()) {
103+ if (totalBytesRequired > buf.remaining()) {
104+ // process the queue first and then enqueue the mask
105+ rq.flushNow();
106+ }
107+
108+ buf.putInt(MASK_FILL);
109+ // enqueue parameters
110+ buf.putInt(x).putInt(y).putInt(w).putInt(h);
111+ buf.putInt(maskoff);
112+ buf.putInt(maskscan);
113+ buf.putInt(maskBytesRequired);
114+ if (mask != null) {
115+ // enqueue the mask
116+ int padding = maskBytesRequired - mask.length;
117+ buf.put(mask);
118+ if (padding != 0) {
119+ buf.position(buf.position() + padding);
120+ }
121+ }
122+ } else {
123+ // queue is too small to accomodate entire mask; perform
124+ // the operation directly on the queue flushing thread
125+ rq.flushAndInvokeNow(new Runnable() {
126+ public void run() {
127+ maskFill(x, y, w, h,
128+ maskoff, maskscan, mask.length, mask);
129+ }
130+ });
131+ }
132+ } finally {
133+ rq.unlock();
134+ }
135+ }
136+
137+ /**
138+ * Called as a separate Runnable when the operation is too large to fit
139+ * on the RenderQueue. The OGL/D3D pipelines each have their own (small)
140+ * native implementation of this method.
141+ */
142+ protected abstract void maskFill(int x, int y, int w, int h,
143+ int maskoff, int maskscan, int masklen,
144+ byte[] mask);
145+
146+ /**
147+ * Validates the state in the provided SunGraphics2D object and sets up
148+ * any special resources for this operation (e.g. enabling gradient
149+ * shading).
150+ */
151+ protected abstract void validateContext(SunGraphics2D sg2d,
152+ Composite comp, int ctxflags);
153+}
java/pkg/sun/java2d/pipe/BufferedOpCodes.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/BufferedOpCodes.java+99−0
@@ -0,0 +1,99 @@
1+/*
2+ * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+public class BufferedOpCodes {
29+ // draw ops
30+ public static final int DRAW_LINE = 10;
31+ public static final int DRAW_RECT = 11;
32+ public static final int DRAW_POLY = 12;
33+ public static final int DRAW_PIXEL = 13;
34+ public static final int DRAW_SCANLINES = 14;
35+ public static final int DRAW_PARALLELOGRAM = 15;
36+ public static final int DRAW_AAPARALLELOGRAM = 16;
37+
38+ // fill ops
39+ public static final int FILL_RECT = 20;
40+ public static final int FILL_SPANS = 21;
41+ public static final int FILL_PARALLELOGRAM = 22;
42+ public static final int FILL_AAPARALLELOGRAM = 23;
43+
44+ // copy-related ops
45+ public static final int COPY_AREA = 30;
46+ public static final int BLIT = 31;
47+ public static final int MASK_FILL = 32;
48+ public static final int MASK_BLIT = 33;
49+ public static final int SURFACE_TO_SW_BLIT = 34;
50+
51+ // text-related ops
52+ public static final int DRAW_GLYPH_LIST = 40;
53+
54+ // state-related ops
55+ public static final int SET_RECT_CLIP = 51;
56+ public static final int BEGIN_SHAPE_CLIP = 52;
57+ public static final int SET_SHAPE_CLIP_SPANS = 53;
58+ public static final int END_SHAPE_CLIP = 54;
59+ public static final int RESET_CLIP = 55;
60+ public static final int SET_ALPHA_COMPOSITE = 56;
61+ public static final int SET_XOR_COMPOSITE = 57;
62+ public static final int RESET_COMPOSITE = 58;
63+ public static final int SET_TRANSFORM = 59;
64+ public static final int RESET_TRANSFORM = 60;
65+
66+ // context-related ops
67+ public static final int SET_SURFACES = 70;
68+ public static final int SET_SCRATCH_SURFACE = 71;
69+ public static final int FLUSH_SURFACE = 72;
70+ public static final int DISPOSE_SURFACE = 73;
71+ public static final int DISPOSE_CONFIG = 74;
72+ public static final int INVALIDATE_CONTEXT = 75;
73+ public static final int SYNC = 76;
74+ public static final int RESTORE_DEVICES = 77;
75+ public static final int SAVE_STATE = 78;
76+ public static final int RESTORE_STATE = 79;
77+
78+ // multibuffering ops
79+ public static final int SWAP_BUFFERS = 80;
80+
81+ // special no-op op code (mainly used for achieving 8-byte alignment)
82+ public static final int NOOP = 90;
83+
84+ // paint-related ops
85+ public static final int RESET_PAINT = 100;
86+ public static final int SET_COLOR = 101;
87+ public static final int SET_GRADIENT_PAINT = 102;
88+ public static final int SET_LINEAR_GRADIENT_PAINT = 103;
89+ public static final int SET_RADIAL_GRADIENT_PAINT = 104;
90+ public static final int SET_TEXTURE_PAINT = 105;
91+
92+ // BufferedImageOp-related ops
93+ public static final int ENABLE_CONVOLVE_OP = 120;
94+ public static final int DISABLE_CONVOLVE_OP = 121;
95+ public static final int ENABLE_RESCALE_OP = 122;
96+ public static final int DISABLE_RESCALE_OP = 123;
97+ public static final int ENABLE_LOOKUP_OP = 124;
98+ public static final int DISABLE_LOOKUP_OP = 125;
99+}
java/pkg/sun/java2d/pipe/BufferedPaints.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/BufferedPaints.java+533−0
@@ -0,0 +1,533 @@
1+/*
2+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Color;
29+import java.awt.GradientPaint;
30+import java.awt.LinearGradientPaint;
31+import java.awt.MultipleGradientPaint;
32+import java.awt.MultipleGradientPaint.ColorSpaceType;
33+import java.awt.MultipleGradientPaint.CycleMethod;
34+import java.awt.Paint;
35+import java.awt.RadialGradientPaint;
36+import java.awt.TexturePaint;
37+import java.awt.geom.AffineTransform;
38+import java.awt.geom.Point2D;
39+import java.awt.geom.Rectangle2D;
40+import java.awt.image.AffineTransformOp;
41+import java.awt.image.BufferedImage;
42+import sun.awt.image.PixelConverter;
43+import sun.java2d.SunGraphics2D;
44+import sun.java2d.SurfaceData;
45+import sun.java2d.loops.CompositeType;
46+import sun.java2d.loops.SurfaceType;
47+import static sun.java2d.pipe.BufferedOpCodes.*;
48+
49+public class BufferedPaints {
50+
51+ static void setPaint(RenderQueue rq, SunGraphics2D sg2d,
52+ Paint paint, int ctxflags)
53+ {
54+ if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {
55+ setColor(rq, sg2d.pixel);
56+ } else {
57+ boolean useMask = (ctxflags & BufferedContext.USE_MASK) != 0;
58+ switch (sg2d.paintState) {
59+ case SunGraphics2D.PAINT_GRADIENT:
60+ setGradientPaint(rq, sg2d,
61+ (GradientPaint)paint, useMask);
62+ break;
63+ case SunGraphics2D.PAINT_LIN_GRADIENT:
64+ setLinearGradientPaint(rq, sg2d,
65+ (LinearGradientPaint)paint, useMask);
66+ break;
67+ case SunGraphics2D.PAINT_RAD_GRADIENT:
68+ setRadialGradientPaint(rq, sg2d,
69+ (RadialGradientPaint)paint, useMask);
70+ break;
71+ case SunGraphics2D.PAINT_TEXTURE:
72+ setTexturePaint(rq, sg2d,
73+ (TexturePaint)paint, useMask);
74+ break;
75+ default:
76+ break;
77+ }
78+ }
79+ }
80+
81+ static void resetPaint(RenderQueue rq) {
82+ // assert rq.lock.isHeldByCurrentThread();
83+ rq.ensureCapacity(4);
84+ RenderBuffer buf = rq.getBuffer();
85+ buf.putInt(RESET_PAINT);
86+ }
87+
88+/****************************** Color support *******************************/
89+
90+ private static void setColor(RenderQueue rq, int pixel) {
91+ // assert rq.lock.isHeldByCurrentThread();
92+ rq.ensureCapacity(8);
93+ RenderBuffer buf = rq.getBuffer();
94+ buf.putInt(SET_COLOR);
95+ buf.putInt(pixel);
96+ }
97+
98+/************************* GradientPaint support ****************************/
99+
100+ /**
101+ * Note: This code is factored out into a separate static method
102+ * so that it can be shared by both the Gradient and LinearGradient
103+ * implementations. LinearGradient uses this code (for the
104+ * two-color sRGB case only) because it can be much faster than the
105+ * equivalent implementation that uses fragment shaders.
106+ *
107+ * We use OpenGL's texture coordinate generator to automatically
108+ * apply a smooth gradient (either cyclic or acyclic) to the geometry
109+ * being rendered. This technique is almost identical to the one
110+ * described in the comments for BufferedPaints.setTexturePaint(),
111+ * except the calculations take place in one dimension instead of two.
112+ * Instead of an anchor rectangle in the TexturePaint case, we use
113+ * the vector between the two GradientPaint end points in our
114+ * calculations. The generator uses a single plane equation that
115+ * takes the (x,y) location (in device space) of the fragment being
116+ * rendered to calculate a (u) texture coordinate for that fragment:
117+ * u = Ax + By + Cz + Dw
118+ *
119+ * The gradient renderer uses a two-pixel 1D texture where the first
120+ * pixel contains the first GradientPaint color, and the second pixel
121+ * contains the second GradientPaint color. (Note that we use the
122+ * GL_CLAMP_TO_EDGE wrapping mode for acyclic gradients so that we
123+ * clamp the colors properly at the extremes.) The following diagram
124+ * attempts to show the layout of the texture containing the two
125+ * GradientPaint colors (C1 and C2):
126+ *
127+ * +-----------------+
128+ * | C1 | C2 |
129+ * | | |
130+ * +-----------------+
131+ * u=0 .25 .5 .75 1
132+ *
133+ * We calculate our plane equation constants (A,B,D) such that u=0.25
134+ * corresponds to the first GradientPaint end point in user space and
135+ * u=0.75 corresponds to the second end point. This is somewhat
136+ * non-obvious, but since the gradient colors are generated by
137+ * interpolating between C1 and C2, we want the pure color at the
138+ * end points, and we will get the pure color only when u correlates
139+ * to the center of a texel. The following chart shows the expected
140+ * color for some sample values of u (where C' is the color halfway
141+ * between C1 and C2):
142+ *
143+ * u value acyclic (GL_CLAMP) cyclic (GL_REPEAT)
144+ * ------- ------------------ ------------------
145+ * -0.25 C1 C2
146+ * 0.0 C1 C'
147+ * 0.25 C1 C1
148+ * 0.5 C' C'
149+ * 0.75 C2 C2
150+ * 1.0 C2 C'
151+ * 1.25 C2 C1
152+ *
153+ * Original inspiration for this technique came from UMD's Agile2D
154+ * project (GradientManager.java).
155+ */
156+ private static void setGradientPaint(RenderQueue rq, AffineTransform at,
157+ Color c1, Color c2,
158+ Point2D pt1, Point2D pt2,
159+ boolean isCyclic, boolean useMask)
160+ {
161+ // convert gradient colors to IntArgbPre format
162+ PixelConverter pc = PixelConverter.ArgbPre.instance;
163+ int pixel1 = pc.rgbToPixel(c1.getRGB(), null);
164+ int pixel2 = pc.rgbToPixel(c2.getRGB(), null);
165+
166+ // calculate plane equation constants
167+ double x = pt1.getX();
168+ double y = pt1.getY();
169+ at.translate(x, y);
170+ // now gradient point 1 is at the origin
171+ x = pt2.getX() - x;
172+ y = pt2.getY() - y;
173+ double len = Math.sqrt(x * x + y * y);
174+ at.rotate(x, y);
175+ // now gradient point 2 is on the positive x-axis
176+ at.scale(2*len, 1);
177+ // now gradient point 2 is at (0.5, 0)
178+ at.translate(-0.25, 0);
179+ // now gradient point 1 is at (0.25, 0), point 2 is at (0.75, 0)
180+
181+ double p0, p1, p3;
182+ try {
183+ at.invert();
184+ p0 = at.getScaleX();
185+ p1 = at.getShearX();
186+ p3 = at.getTranslateX();
187+ } catch (java.awt.geom.NoninvertibleTransformException e) {
188+ p0 = p1 = p3 = 0.0;
189+ }
190+
191+ // assert rq.lock.isHeldByCurrentThread();
192+ rq.ensureCapacityAndAlignment(44, 12);
193+ RenderBuffer buf = rq.getBuffer();
194+ buf.putInt(SET_GRADIENT_PAINT);
195+ buf.putInt(useMask ? 1 : 0);
196+ buf.putInt(isCyclic ? 1 : 0);
197+ buf.putDouble(p0).putDouble(p1).putDouble(p3);
198+ buf.putInt(pixel1).putInt(pixel2);
199+ }
200+
201+ private static void setGradientPaint(RenderQueue rq,
202+ SunGraphics2D sg2d,
203+ GradientPaint paint,
204+ boolean useMask)
205+ {
206+ setGradientPaint(rq, (AffineTransform)sg2d.transform.clone(),
207+ paint.getColor1(), paint.getColor2(),
208+ paint.getPoint1(), paint.getPoint2(),
209+ paint.isCyclic(), useMask);
210+ }
211+
212+/************************** TexturePaint support ****************************/
213+
214+ /**
215+ * We use OpenGL's texture coordinate generator to automatically
216+ * map the TexturePaint image to the geometry being rendered. The
217+ * generator uses two separate plane equations that take the (x,y)
218+ * location (in device space) of the fragment being rendered to
219+ * calculate (u,v) texture coordinates for that fragment:
220+ * u = Ax + By + Cz + Dw
221+ * v = Ex + Fy + Gz + Hw
222+ *
223+ * Since we use a 2D orthographic projection, we can assume that z=0
224+ * and w=1 for any fragment. So we need to calculate appropriate
225+ * values for the plane equation constants (A,B,D) and (E,F,H) such
226+ * that {u,v}=0 for the top-left of the TexturePaint's anchor
227+ * rectangle and {u,v}=1 for the bottom-right of the anchor rectangle.
228+ * We can easily make the texture image repeat for {u,v} values
229+ * outside the range [0,1] by specifying the GL_REPEAT texture wrap
230+ * mode.
231+ *
232+ * Calculating the plane equation constants is surprisingly simple.
233+ * We can think of it as an inverse matrix operation that takes
234+ * device space coordinates and transforms them into user space
235+ * coordinates that correspond to a location relative to the anchor
236+ * rectangle. First, we translate and scale the current user space
237+ * transform by applying the anchor rectangle bounds. We then take
238+ * the inverse of this affine transform. The rows of the resulting
239+ * inverse matrix correlate nicely to the plane equation constants
240+ * we were seeking.
241+ */
242+ private static void setTexturePaint(RenderQueue rq,
243+ SunGraphics2D sg2d,
244+ TexturePaint paint,
245+ boolean useMask)
246+ {
247+ BufferedImage bi = paint.getImage();
248+ SurfaceData dstData = sg2d.surfaceData;
249+ SurfaceData srcData =
250+ dstData.getSourceSurfaceData(bi, sg2d.TRANSFORM_ISIDENT,
251+ CompositeType.SrcOver, null);
252+ boolean filter =
253+ (sg2d.interpolationType !=
254+ AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
255+
256+ // calculate plane equation constants
257+ AffineTransform at = (AffineTransform)sg2d.transform.clone();
258+ Rectangle2D anchor = paint.getAnchorRect();
259+ at.translate(anchor.getX(), anchor.getY());
260+ at.scale(anchor.getWidth(), anchor.getHeight());
261+
262+ double xp0, xp1, xp3, yp0, yp1, yp3;
263+ try {
264+ at.invert();
265+ xp0 = at.getScaleX();
266+ xp1 = at.getShearX();
267+ xp3 = at.getTranslateX();
268+ yp0 = at.getShearY();
269+ yp1 = at.getScaleY();
270+ yp3 = at.getTranslateY();
271+ } catch (java.awt.geom.NoninvertibleTransformException e) {
272+ xp0 = xp1 = xp3 = yp0 = yp1 = yp3 = 0.0;
273+ }
274+
275+ // assert rq.lock.isHeldByCurrentThread();
276+ rq.ensureCapacityAndAlignment(68, 12);
277+ RenderBuffer buf = rq.getBuffer();
278+ buf.putInt(SET_TEXTURE_PAINT);
279+ buf.putInt(useMask ? 1 : 0);
280+ buf.putInt(filter ? 1 : 0);
281+ buf.putLong(srcData.getNativeOps());
282+ buf.putDouble(xp0).putDouble(xp1).putDouble(xp3);
283+ buf.putDouble(yp0).putDouble(yp1).putDouble(yp3);
284+ }
285+
286+/****************** Shared MultipleGradientPaint support ********************/
287+
288+ /**
289+ * The maximum number of gradient "stops" supported by our native
290+ * fragment shader implementations.
291+ *
292+ * This value has been empirically determined and capped to allow
293+ * our native shaders to run on all shader-level graphics hardware,
294+ * even on the older, more limited GPUs. Even the oldest Nvidia
295+ * hardware could handle 16, or even 32 fractions without any problem.
296+ * But the first-generation boards from ATI would fall back into
297+ * software mode (which is unusably slow) for values larger than 12;
298+ * it appears that those boards do not have enough native registers
299+ * to support the number of array accesses required by our gradient
300+ * shaders. So for now we will cap this value at 12, but we can
301+ * re-evaluate this in the future as hardware becomes more capable.
302+ */
303+ public static final int MULTI_MAX_FRACTIONS = 12;
304+
305+ /**
306+ * Helper function to convert a color component in sRGB space to
307+ * linear RGB space. Copied directly from the
308+ * MultipleGradientPaintContext class.
309+ */
310+ public static int convertSRGBtoLinearRGB(int color) {
311+ float input, output;
312+
313+ input = color / 255.0f;
314+ if (input <= 0.04045f) {
315+ output = input / 12.92f;
316+ } else {
317+ output = (float)Math.pow((input + 0.055) / 1.055, 2.4);
318+ }
319+
320+ return Math.round(output * 255.0f);
321+ }
322+
323+ /**
324+ * Helper function to convert a (non-premultiplied) Color in sRGB
325+ * space to an IntArgbPre pixel value, optionally in linear RGB space.
326+ * Based on the PixelConverter.ArgbPre.rgbToPixel() method.
327+ */
328+ private static int colorToIntArgbPrePixel(Color c, boolean linear) {
329+ int rgb = c.getRGB();
330+ if (!linear && ((rgb >> 24) == -1)) {
331+ return rgb;
332+ }
333+ int a = rgb >>> 24;
334+ int r = (rgb >> 16) & 0xff;
335+ int g = (rgb >> 8) & 0xff;
336+ int b = (rgb ) & 0xff;
337+ if (linear) {
338+ r = convertSRGBtoLinearRGB(r);
339+ g = convertSRGBtoLinearRGB(g);
340+ b = convertSRGBtoLinearRGB(b);
341+ }
342+ int a2 = a + (a >> 7);
343+ r = (r * a2) >> 8;
344+ g = (g * a2) >> 8;
345+ b = (b * a2) >> 8;
346+ return ((a << 24) | (r << 16) | (g << 8) | (b));
347+ }
348+
349+ /**
350+ * Converts the given array of Color objects into an int array
351+ * containing IntArgbPre pixel values. If the linear parameter
352+ * is true, the Color values will be converted into a linear RGB
353+ * color space before being returned.
354+ */
355+ private static int[] convertToIntArgbPrePixels(Color[] colors,
356+ boolean linear)
357+ {
358+ int[] pixels = new int[colors.length];
359+ for (int i = 0; i < colors.length; i++) {
360+ pixels[i] = colorToIntArgbPrePixel(colors[i], linear);
361+ }
362+ return pixels;
363+ }
364+
365+/********************** LinearGradientPaint support *************************/
366+
367+ /**
368+ * This method uses techniques that are nearly identical to those
369+ * employed in setGradientPaint() above. The primary difference
370+ * is that at the native level we use a fragment shader to manually
371+ * apply the plane equation constants to the current fragment position
372+ * to calculate the gradient position in the range [0,1] (the native
373+ * code for GradientPaint does the same, except that it uses OpenGL's
374+ * automatic texture coordinate generation facilities).
375+ *
376+ * One other minor difference worth mentioning is that
377+ * setGradientPaint() calculates the plane equation constants
378+ * such that the gradient end points are positioned at 0.25 and 0.75
379+ * (for reasons discussed in the comments for that method). In
380+ * contrast, for LinearGradientPaint we setup the equation constants
381+ * such that the gradient end points fall at 0.0 and 1.0. The
382+ * reason for this difference is that in the fragment shader we
383+ * have more control over how the gradient values are interpreted
384+ * (depending on the paint's CycleMethod).
385+ */
386+ private static void setLinearGradientPaint(RenderQueue rq,
387+ SunGraphics2D sg2d,
388+ LinearGradientPaint paint,
389+ boolean useMask)
390+ {
391+ boolean linear =
392+ (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
393+ Color[] colors = paint.getColors();
394+ int numStops = colors.length;
395+ Point2D pt1 = paint.getStartPoint();
396+ Point2D pt2 = paint.getEndPoint();
397+ AffineTransform at = paint.getTransform();
398+ at.preConcatenate(sg2d.transform);
399+
400+ if (!linear && numStops == 2 &&
401+ paint.getCycleMethod() != CycleMethod.REPEAT)
402+ {
403+ // delegate to the optimized two-color gradient codepath
404+ boolean isCyclic =
405+ (paint.getCycleMethod() != CycleMethod.NO_CYCLE);
406+ setGradientPaint(rq, at,
407+ colors[0], colors[1],
408+ pt1, pt2,
409+ isCyclic, useMask);
410+ return;
411+ }
412+
413+ int cycleMethod = paint.getCycleMethod().ordinal();
414+ float[] fractions = paint.getFractions();
415+ int[] pixels = convertToIntArgbPrePixels(colors, linear);
416+
417+ // calculate plane equation constants
418+ double x = pt1.getX();
419+ double y = pt1.getY();
420+ at.translate(x, y);
421+ // now gradient point 1 is at the origin
422+ x = pt2.getX() - x;
423+ y = pt2.getY() - y;
424+ double len = Math.sqrt(x * x + y * y);
425+ at.rotate(x, y);
426+ // now gradient point 2 is on the positive x-axis
427+ at.scale(len, 1);
428+ // now gradient point 1 is at (0.0, 0), point 2 is at (1.0, 0)
429+
430+ float p0, p1, p3;
431+ try {
432+ at.invert();
433+ p0 = (float)at.getScaleX();
434+ p1 = (float)at.getShearX();
435+ p3 = (float)at.getTranslateX();
436+ } catch (java.awt.geom.NoninvertibleTransformException e) {
437+ p0 = p1 = p3 = 0.0f;
438+ }
439+
440+ // assert rq.lock.isHeldByCurrentThread();
441+ rq.ensureCapacity(20 + 12 + (numStops*4*2));
442+ RenderBuffer buf = rq.getBuffer();
443+ buf.putInt(SET_LINEAR_GRADIENT_PAINT);
444+ buf.putInt(useMask ? 1 : 0);
445+ buf.putInt(linear ? 1 : 0);
446+ buf.putInt(cycleMethod);
447+ buf.putInt(numStops);
448+ buf.putFloat(p0);
449+ buf.putFloat(p1);
450+ buf.putFloat(p3);
451+ buf.put(fractions);
452+ buf.put(pixels);
453+ }
454+
455+/********************** RadialGradientPaint support *************************/
456+
457+ /**
458+ * This method calculates six m** values and a focusX value that
459+ * are used by the native fragment shader. These techniques are
460+ * based on a whitepaper by Daniel Rice on radial gradient performance
461+ * (attached to the bug report for 6521533). One can refer to that
462+ * document for the complete set of formulas and calculations, but
463+ * the basic goal is to compose a transform that will convert an
464+ * (x,y) position in device space into a "u" value that represents
465+ * the relative distance to the gradient focus point. The resulting
466+ * value can be used to look up the appropriate color by linearly
467+ * interpolating between the two nearest colors in the gradient.
468+ */
469+ private static void setRadialGradientPaint(RenderQueue rq,
470+ SunGraphics2D sg2d,
471+ RadialGradientPaint paint,
472+ boolean useMask)
473+ {
474+ boolean linear =
475+ (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
476+ int cycleMethod = paint.getCycleMethod().ordinal();
477+ float[] fractions = paint.getFractions();
478+ Color[] colors = paint.getColors();
479+ int numStops = colors.length;
480+ int[] pixels = convertToIntArgbPrePixels(colors, linear);
481+ Point2D center = paint.getCenterPoint();
482+ Point2D focus = paint.getFocusPoint();
483+ float radius = paint.getRadius();
484+
485+ // save original (untransformed) center and focus points
486+ double cx = center.getX();
487+ double cy = center.getY();
488+ double fx = focus.getX();
489+ double fy = focus.getY();
490+
491+ // transform from gradient coords to device coords
492+ AffineTransform at = paint.getTransform();
493+ at.preConcatenate(sg2d.transform);
494+ focus = at.transform(focus, focus);
495+
496+ // transform unit circle to gradient coords; we start with the
497+ // unit circle (center=(0,0), focus on positive x-axis, radius=1)
498+ // and then transform into gradient space
499+ at.translate(cx, cy);
500+ at.rotate(fx - cx, fy - cy);
501+ at.scale(radius, radius);
502+
503+ // invert to get mapping from device coords to unit circle
504+ try {
505+ at.invert();
506+ } catch (Exception e) {
507+ at.setToScale(0.0, 0.0);
508+ }
509+ focus = at.transform(focus, focus);
510+
511+ // clamp the focus point so that it does not rest on, or outside
512+ // of, the circumference of the gradient circle
513+ fx = Math.min(focus.getX(), 0.99);
514+
515+ // assert rq.lock.isHeldByCurrentThread();
516+ rq.ensureCapacity(20 + 28 + (numStops*4*2));
517+ RenderBuffer buf = rq.getBuffer();
518+ buf.putInt(SET_RADIAL_GRADIENT_PAINT);
519+ buf.putInt(useMask ? 1 : 0);
520+ buf.putInt(linear ? 1 : 0);
521+ buf.putInt(numStops);
522+ buf.putInt(cycleMethod);
523+ buf.putFloat((float)at.getScaleX());
524+ buf.putFloat((float)at.getShearX());
525+ buf.putFloat((float)at.getTranslateX());
526+ buf.putFloat((float)at.getShearY());
527+ buf.putFloat((float)at.getScaleY());
528+ buf.putFloat((float)at.getTranslateY());
529+ buf.putFloat((float)fx);
530+ buf.put(fractions);
531+ buf.put(pixels);
532+ }
533+}
java/pkg/sun/java2d/pipe/BufferedRenderPipe$1.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/BufferedRenderPipe$AAParallelogramPipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/BufferedRenderPipe$BufferedDrawHandler.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/BufferedRenderPipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/BufferedRenderPipe.java+601−0
@@ -0,0 +1,601 @@
1+/*
2+ * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.BasicStroke;
29+import java.awt.Polygon;
30+import java.awt.Shape;
31+import java.awt.geom.AffineTransform;
32+import java.awt.geom.Arc2D;
33+import java.awt.geom.Ellipse2D;
34+import java.awt.geom.Path2D;
35+import java.awt.geom.IllegalPathStateException;
36+import java.awt.geom.PathIterator;
37+import java.awt.geom.Rectangle2D;
38+import java.awt.geom.RoundRectangle2D;
39+import sun.java2d.SunGraphics2D;
40+import sun.java2d.loops.ProcessPath;
41+import static sun.java2d.pipe.BufferedOpCodes.*;
42+
43+/**
44+ * Base class for enqueuing rendering operations in a single-threaded
45+ * rendering environment. Instead of each operation being rendered
46+ * immediately by the underlying graphics library, the operation will be
47+ * added to the provided RenderQueue, which will be processed at a later
48+ * time by a single thread.
49+ *
50+ * This class provides implementations of drawLine(), drawRect(), drawPoly(),
51+ * fillRect(), draw(Shape), and fill(Shape), which are useful for a
52+ * hardware-accelerated renderer. The other draw*() and fill*() methods
53+ * simply delegate to draw(Shape) and fill(Shape), respectively.
54+ */
55+public abstract class BufferedRenderPipe
56+ implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe, ParallelogramPipe
57+{
58+ ParallelogramPipe aapgrampipe = new AAParallelogramPipe();
59+
60+ static final int BYTES_PER_POLY_POINT = 8;
61+ static final int BYTES_PER_SCANLINE = 12;
62+ static final int BYTES_PER_SPAN = 16;
63+
64+ protected RenderQueue rq;
65+ protected RenderBuffer buf;
66+ private BufferedDrawHandler drawHandler;
67+
68+ public BufferedRenderPipe(RenderQueue rq) {
69+ this.rq = rq;
70+ this.buf = rq.getBuffer();
71+ this.drawHandler = new BufferedDrawHandler();
72+ }
73+
74+ public ParallelogramPipe getAAParallelogramPipe() {
75+ return aapgrampipe;
76+ }
77+
78+ /**
79+ * Validates the state in the provided SunGraphics2D object and sets up
80+ * any special resources for this operation (e.g. enabling gradient
81+ * shading).
82+ */
83+ protected abstract void validateContext(SunGraphics2D sg2d);
84+ protected abstract void validateContextAA(SunGraphics2D sg2d);
85+
86+ public void drawLine(SunGraphics2D sg2d,
87+ int x1, int y1, int x2, int y2)
88+ {
89+ int transx = sg2d.transX;
90+ int transy = sg2d.transY;
91+ rq.lock();
92+ try {
93+ validateContext(sg2d);
94+ rq.ensureCapacity(20);
95+ buf.putInt(DRAW_LINE);
96+ buf.putInt(x1 + transx);
97+ buf.putInt(y1 + transy);
98+ buf.putInt(x2 + transx);
99+ buf.putInt(y2 + transy);
100+ } finally {
101+ rq.unlock();
102+ }
103+ }
104+
105+ public void drawRect(SunGraphics2D sg2d,
106+ int x, int y, int width, int height)
107+ {
108+ rq.lock();
109+ try {
110+ validateContext(sg2d);
111+ rq.ensureCapacity(20);
112+ buf.putInt(DRAW_RECT);
113+ buf.putInt(x + sg2d.transX);
114+ buf.putInt(y + sg2d.transY);
115+ buf.putInt(width);
116+ buf.putInt(height);
117+ } finally {
118+ rq.unlock();
119+ }
120+ }
121+
122+ public void fillRect(SunGraphics2D sg2d,
123+ int x, int y, int width, int height)
124+ {
125+ rq.lock();
126+ try {
127+ validateContext(sg2d);
128+ rq.ensureCapacity(20);
129+ buf.putInt(FILL_RECT);
130+ buf.putInt(x + sg2d.transX);
131+ buf.putInt(y + sg2d.transY);
132+ buf.putInt(width);
133+ buf.putInt(height);
134+ } finally {
135+ rq.unlock();
136+ }
137+ }
138+
139+ public void drawRoundRect(SunGraphics2D sg2d,
140+ int x, int y, int width, int height,
141+ int arcWidth, int arcHeight)
142+ {
143+ draw(sg2d, new RoundRectangle2D.Float(x, y, width, height,
144+ arcWidth, arcHeight));
145+ }
146+
147+ public void fillRoundRect(SunGraphics2D sg2d,
148+ int x, int y, int width, int height,
149+ int arcWidth, int arcHeight)
150+ {
151+ fill(sg2d, new RoundRectangle2D.Float(x, y, width, height,
152+ arcWidth, arcHeight));
153+ }
154+
155+ public void drawOval(SunGraphics2D sg2d,
156+ int x, int y, int width, int height)
157+ {
158+ draw(sg2d, new Ellipse2D.Float(x, y, width, height));
159+ }
160+
161+ public void fillOval(SunGraphics2D sg2d,
162+ int x, int y, int width, int height)
163+ {
164+ fill(sg2d, new Ellipse2D.Float(x, y, width, height));
165+ }
166+
167+ public void drawArc(SunGraphics2D sg2d,
168+ int x, int y, int width, int height,
169+ int startAngle, int arcAngle)
170+ {
171+ draw(sg2d, new Arc2D.Float(x, y, width, height,
172+ startAngle, arcAngle,
173+ Arc2D.OPEN));
174+ }
175+
176+ public void fillArc(SunGraphics2D sg2d,
177+ int x, int y, int width, int height,
178+ int startAngle, int arcAngle)
179+ {
180+ fill(sg2d, new Arc2D.Float(x, y, width, height,
181+ startAngle, arcAngle,
182+ Arc2D.PIE));
183+ }
184+
185+ protected void drawPoly(final SunGraphics2D sg2d,
186+ final int[] xPoints, final int[] yPoints,
187+ final int nPoints, final boolean isClosed)
188+ {
189+ if (xPoints == null || yPoints == null) {
190+ throw new NullPointerException("coordinate array");
191+ }
192+ if (xPoints.length < nPoints || yPoints.length < nPoints) {
193+ throw new ArrayIndexOutOfBoundsException("coordinate array");
194+ }
195+
196+ if (nPoints < 2) {
197+ // render nothing
198+ return;
199+ } else if (nPoints == 2 && !isClosed) {
200+ // render a simple line
201+ drawLine(sg2d, xPoints[0], yPoints[0], xPoints[1], yPoints[1]);
202+ return;
203+ }
204+
205+ rq.lock();
206+ try {
207+ validateContext(sg2d);
208+
209+ int pointBytesRequired = nPoints * BYTES_PER_POLY_POINT;
210+ int totalBytesRequired = 20 + pointBytesRequired;
211+
212+ if (totalBytesRequired <= buf.capacity()) {
213+ if (totalBytesRequired > buf.remaining()) {
214+ // process the queue first and then enqueue the points
215+ rq.flushNow();
216+ }
217+ buf.putInt(DRAW_POLY);
218+ // enqueue parameters
219+ buf.putInt(nPoints);
220+ buf.putInt(isClosed ? 1 : 0);
221+ buf.putInt(sg2d.transX);
222+ buf.putInt(sg2d.transY);
223+ // enqueue the points
224+ buf.put(xPoints, 0, nPoints);
225+ buf.put(yPoints, 0, nPoints);
226+ } else {
227+ // queue is too small to accomodate all points; perform the
228+ // operation directly on the queue flushing thread
229+ rq.flushAndInvokeNow(new Runnable() {
230+ public void run() {
231+ drawPoly(xPoints, yPoints,
232+ nPoints, isClosed,
233+ sg2d.transX, sg2d.transY);
234+ }
235+ });
236+ }
237+ } finally {
238+ rq.unlock();
239+ }
240+ }
241+
242+ protected abstract void drawPoly(int[] xPoints, int[] yPoints,
243+ int nPoints, boolean isClosed,
244+ int transX, int transY);
245+
246+ public void drawPolyline(SunGraphics2D sg2d,
247+ int[] xPoints, int[] yPoints,
248+ int nPoints)
249+ {
250+ drawPoly(sg2d, xPoints, yPoints, nPoints, false);
251+ }
252+
253+ public void drawPolygon(SunGraphics2D sg2d,
254+ int[] xPoints, int[] yPoints,
255+ int nPoints)
256+ {
257+ drawPoly(sg2d, xPoints, yPoints, nPoints, true);
258+ }
259+
260+ public void fillPolygon(SunGraphics2D sg2d,
261+ int[] xPoints, int[] yPoints,
262+ int nPoints)
263+ {
264+ fill(sg2d, new Polygon(xPoints, yPoints, nPoints));
265+ }
266+
267+ private class BufferedDrawHandler
268+ extends ProcessPath.DrawHandler
269+ {
270+ BufferedDrawHandler() {
271+ // these are bogus values; the caller will use validate()
272+ // to ensure that they are set properly prior to each usage
273+ super(0, 0, 0, 0);
274+ }
275+
276+ /**
277+ * This method needs to be called prior to each draw/fillPath()
278+ * operation to ensure the clip bounds are up to date.
279+ */
280+ void validate(SunGraphics2D sg2d) {
281+ Region clip = sg2d.getCompClip();
282+ setBounds(clip.getLoX(), clip.getLoY(),
283+ clip.getHiX(), clip.getHiY(),
284+ sg2d.strokeHint);
285+ }
286+
287+ /**
288+ * drawPath() support...
289+ */
290+
291+ public void drawLine(int x1, int y1, int x2, int y2) {
292+ // assert rq.lock.isHeldByCurrentThread();
293+ rq.ensureCapacity(20);
294+ buf.putInt(DRAW_LINE);
295+ buf.putInt(x1);
296+ buf.putInt(y1);
297+ buf.putInt(x2);
298+ buf.putInt(y2);
299+ }
300+
301+ public void drawPixel(int x, int y) {
302+ // assert rq.lock.isHeldByCurrentThread();
303+ rq.ensureCapacity(12);
304+ buf.putInt(DRAW_PIXEL);
305+ buf.putInt(x);
306+ buf.putInt(y);
307+ }
308+
309+ /**
310+ * fillPath() support...
311+ */
312+
313+ private int scanlineCount;
314+ private int scanlineCountIndex;
315+ private int remainingScanlines;
316+
317+ private void resetFillPath() {
318+ buf.putInt(DRAW_SCANLINES);
319+ scanlineCountIndex = buf.position();
320+ buf.putInt(0);
321+ scanlineCount = 0;
322+ remainingScanlines = buf.remaining() / BYTES_PER_SCANLINE;
323+ }
324+
325+ private void updateScanlineCount() {
326+ buf.putInt(scanlineCountIndex, scanlineCount);
327+ }
328+
329+ /**
330+ * Called from fillPath() to indicate that we are about to
331+ * start issuing drawScanline() calls.
332+ */
333+ public void startFillPath() {
334+ rq.ensureCapacity(20); // to ensure room for at least a scanline
335+ resetFillPath();
336+ }
337+
338+ public void drawScanline(int x1, int x2, int y) {
339+ if (remainingScanlines == 0) {
340+ updateScanlineCount();
341+ rq.flushNow();
342+ resetFillPath();
343+ }
344+ buf.putInt(x1);
345+ buf.putInt(x2);
346+ buf.putInt(y);
347+ scanlineCount++;
348+ remainingScanlines--;
349+ }
350+
351+ /**
352+ * Called from fillPath() to indicate that we are done
353+ * issuing drawScanline() calls.
354+ */
355+ public void endFillPath() {
356+ updateScanlineCount();
357+ }
358+ }
359+
360+ protected void drawPath(SunGraphics2D sg2d,
361+ Path2D.Float p2df, int transx, int transy)
362+ {
363+ rq.lock();
364+ try {
365+ validateContext(sg2d);
366+ drawHandler.validate(sg2d);
367+ ProcessPath.drawPath(drawHandler, p2df, transx, transy);
368+ } finally {
369+ rq.unlock();
370+ }
371+ }
372+
373+ protected void fillPath(SunGraphics2D sg2d,
374+ Path2D.Float p2df, int transx, int transy)
375+ {
376+ rq.lock();
377+ try {
378+ validateContext(sg2d);
379+ drawHandler.validate(sg2d);
380+ drawHandler.startFillPath();
381+ ProcessPath.fillPath(drawHandler, p2df, transx, transy);
382+ drawHandler.endFillPath();
383+ } finally {
384+ rq.unlock();
385+ }
386+ }
387+
388+ private native int fillSpans(RenderQueue rq, long buf,
389+ int pos, int limit,
390+ SpanIterator si, long iterator,
391+ int transx, int transy);
392+
393+ protected void fillSpans(SunGraphics2D sg2d, SpanIterator si,
394+ int transx, int transy)
395+ {
396+ rq.lock();
397+ try {
398+ validateContext(sg2d);
399+ rq.ensureCapacity(24); // so that we have room for at least a span
400+ int newpos = fillSpans(rq, buf.getAddress(),
401+ buf.position(), buf.capacity(),
402+ si, si.getNativeIterator(),
403+ transx, transy);
404+ buf.position(newpos);
405+ } finally {
406+ rq.unlock();
407+ }
408+ }
409+
410+ public void fillParallelogram(SunGraphics2D sg2d,
411+ double ux1, double uy1,
412+ double ux2, double uy2,
413+ double x, double y,
414+ double dx1, double dy1,
415+ double dx2, double dy2)
416+ {
417+ rq.lock();
418+ try {
419+ validateContext(sg2d);
420+ rq.ensureCapacity(28);
421+ buf.putInt(FILL_PARALLELOGRAM);
422+ buf.putFloat((float) x);
423+ buf.putFloat((float) y);
424+ buf.putFloat((float) dx1);
425+ buf.putFloat((float) dy1);
426+ buf.putFloat((float) dx2);
427+ buf.putFloat((float) dy2);
428+ } finally {
429+ rq.unlock();
430+ }
431+ }
432+
433+ public void drawParallelogram(SunGraphics2D sg2d,
434+ double ux1, double uy1,
435+ double ux2, double uy2,
436+ double x, double y,
437+ double dx1, double dy1,
438+ double dx2, double dy2,
439+ double lw1, double lw2)
440+ {
441+ rq.lock();
442+ try {
443+ validateContext(sg2d);
444+ rq.ensureCapacity(36);
445+ buf.putInt(DRAW_PARALLELOGRAM);
446+ buf.putFloat((float) x);
447+ buf.putFloat((float) y);
448+ buf.putFloat((float) dx1);
449+ buf.putFloat((float) dy1);
450+ buf.putFloat((float) dx2);
451+ buf.putFloat((float) dy2);
452+ buf.putFloat((float) lw1);
453+ buf.putFloat((float) lw2);
454+ } finally {
455+ rq.unlock();
456+ }
457+ }
458+
459+ private class AAParallelogramPipe implements ParallelogramPipe {
460+ public void fillParallelogram(SunGraphics2D sg2d,
461+ double ux1, double uy1,
462+ double ux2, double uy2,
463+ double x, double y,
464+ double dx1, double dy1,
465+ double dx2, double dy2)
466+ {
467+ rq.lock();
468+ try {
469+ validateContextAA(sg2d);
470+ rq.ensureCapacity(28);
471+ buf.putInt(FILL_AAPARALLELOGRAM);
472+ buf.putFloat((float) x);
473+ buf.putFloat((float) y);
474+ buf.putFloat((float) dx1);
475+ buf.putFloat((float) dy1);
476+ buf.putFloat((float) dx2);
477+ buf.putFloat((float) dy2);
478+ } finally {
479+ rq.unlock();
480+ }
481+ }
482+
483+ public void drawParallelogram(SunGraphics2D sg2d,
484+ double ux1, double uy1,
485+ double ux2, double uy2,
486+ double x, double y,
487+ double dx1, double dy1,
488+ double dx2, double dy2,
489+ double lw1, double lw2)
490+ {
491+ rq.lock();
492+ try {
493+ validateContextAA(sg2d);
494+ rq.ensureCapacity(36);
495+ buf.putInt(DRAW_AAPARALLELOGRAM);
496+ buf.putFloat((float) x);
497+ buf.putFloat((float) y);
498+ buf.putFloat((float) dx1);
499+ buf.putFloat((float) dy1);
500+ buf.putFloat((float) dx2);
501+ buf.putFloat((float) dy2);
502+ buf.putFloat((float) lw1);
503+ buf.putFloat((float) lw2);
504+ } finally {
505+ rq.unlock();
506+ }
507+ }
508+ }
509+
510+ public void draw(SunGraphics2D sg2d, Shape s) {
511+ if (sg2d.strokeState == sg2d.STROKE_THIN) {
512+ if (s instanceof Polygon) {
513+ if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE) {
514+ Polygon p = (Polygon)s;
515+ drawPolygon(sg2d, p.xpoints, p.ypoints, p.npoints);
516+ return;
517+ }
518+ }
519+ Path2D.Float p2df;
520+ int transx, transy;
521+ if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) {
522+ if (s instanceof Path2D.Float) {
523+ p2df = (Path2D.Float)s;
524+ } else {
525+ p2df = new Path2D.Float(s);
526+ }
527+ transx = sg2d.transX;
528+ transy = sg2d.transY;
529+ } else {
530+ p2df = new Path2D.Float(s, sg2d.transform);
531+ transx = 0;
532+ transy = 0;
533+ }
534+ drawPath(sg2d, p2df, transx, transy);
535+ } else if (sg2d.strokeState < sg2d.STROKE_CUSTOM) {
536+ ShapeSpanIterator si = LoopPipe.getStrokeSpans(sg2d, s);
537+ try {
538+ fillSpans(sg2d, si, 0, 0);
539+ } finally {
540+ si.dispose();
541+ }
542+ } else {
543+ fill(sg2d, sg2d.stroke.createStrokedShape(s));
544+ }
545+ }
546+
547+ public void fill(SunGraphics2D sg2d, Shape s) {
548+ int transx, transy;
549+
550+ if (sg2d.strokeState == sg2d.STROKE_THIN) {
551+ // Here we are able to use fillPath() for
552+ // high-quality fills.
553+ Path2D.Float p2df;
554+ if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) {
555+ if (s instanceof Path2D.Float) {
556+ p2df = (Path2D.Float)s;
557+ } else {
558+ p2df = new Path2D.Float(s);
559+ }
560+ transx = sg2d.transX;
561+ transy = sg2d.transY;
562+ } else {
563+ p2df = new Path2D.Float(s, sg2d.transform);
564+ transx = 0;
565+ transy = 0;
566+ }
567+ fillPath(sg2d, p2df, transx, transy);
568+ return;
569+ }
570+
571+ AffineTransform at;
572+ if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) {
573+ // Transform (translation) will be done by FillSpans (we could
574+ // delegate to fillPolygon() here, but most hardware accelerated
575+ // libraries cannot handle non-convex polygons, so we will use
576+ // the FillSpans approach by default)
577+ at = null;
578+ transx = sg2d.transX;
579+ transy = sg2d.transY;
580+ } else {
581+ // Transform will be done by the PathIterator
582+ at = sg2d.transform;
583+ transx = transy = 0;
584+ }
585+
586+ ShapeSpanIterator ssi = LoopPipe.getFillSSI(sg2d);
587+ try {
588+ // Subtract transx/y from the SSI clip to match the
589+ // (potentially untranslated) geometry fed to it
590+ Region clip = sg2d.getCompClip();
591+ ssi.setOutputAreaXYXY(clip.getLoX() - transx,
592+ clip.getLoY() - transy,
593+ clip.getHiX() - transx,
594+ clip.getHiY() - transy);
595+ ssi.appendPath(s.getPathIterator(at));
596+ fillSpans(sg2d, ssi, transx, transy);
597+ } finally {
598+ ssi.dispose();
599+ }
600+ }
601+}
java/pkg/sun/java2d/pipe/BufferedTextPipe.java+168−0
@@ -0,0 +1,168 @@
1+/*
2+ * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.AlphaComposite;
29+import java.awt.Composite;
30+import sun.font.GlyphList;
31+import sun.java2d.SunGraphics2D;
32+import sun.java2d.SurfaceData;
33+import static sun.java2d.pipe.BufferedOpCodes.*;
34+
35+public abstract class BufferedTextPipe extends GlyphListPipe {
36+
37+ private static final int BYTES_PER_GLYPH_IMAGE = 8;
38+ private static final int BYTES_PER_GLYPH_POSITION = 8;
39+
40+ /**
41+ * The following offsets are used to pack the parameters in
42+ * createPackedParams(). (They are also used at the native level when
43+ * unpacking the params.)
44+ */
45+ private static final int OFFSET_CONTRAST = 8;
46+ private static final int OFFSET_RGBORDER = 2;
47+ private static final int OFFSET_SUBPIXPOS = 1;
48+ private static final int OFFSET_POSITIONS = 0;
49+
50+ /**
51+ * Packs the given parameters into a single int value in order to save
52+ * space on the rendering queue. Note that most of these parameters
53+ * are only used for rendering LCD-optimized text, but conditionalizing
54+ * this work wouldn't make any impact on performance, so we will pack
55+ * those parameters even in the non-LCD case.
56+ */
57+ private static int createPackedParams(SunGraphics2D sg2d, GlyphList gl) {
58+ return
59+ (((gl.usePositions() ? 1 : 0) << OFFSET_POSITIONS) |
60+ ((gl.isSubPixPos() ? 1 : 0) << OFFSET_SUBPIXPOS) |
61+ ((gl.isRGBOrder() ? 1 : 0) << OFFSET_RGBORDER ) |
62+ ((sg2d.lcdTextContrast & 0xff) << OFFSET_CONTRAST ));
63+ }
64+
65+ protected final RenderQueue rq;
66+
67+ protected BufferedTextPipe(RenderQueue rq) {
68+ this.rq = rq;
69+ }
70+
71+ @Override
72+ protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
73+ /*
74+ * The native drawGlyphList() only works with two composite types:
75+ * - CompositeType.SrcOver (with any extra alpha), or
76+ * - CompositeType.Xor
77+ */
78+ Composite comp = sg2d.composite;
79+ if (comp == AlphaComposite.Src) {
80+ /*
81+ * In addition to the composite types listed above, the logic
82+ * in OGL/D3DSurfaceData.validatePipe() allows for
83+ * CompositeType.SrcNoEa, but only in the presence of an opaque
84+ * color. If we reach this case, we know the color is opaque,
85+ * and therefore SrcNoEa is the same as SrcOverNoEa, so we
86+ * override the composite here.
87+ */
88+ comp = AlphaComposite.SrcOver;
89+ }
90+
91+ rq.lock();
92+ try {
93+ validateContext(sg2d, comp);
94+ enqueueGlyphList(sg2d, gl);
95+ } finally {
96+ rq.unlock();
97+ }
98+ }
99+
100+ private void enqueueGlyphList(final SunGraphics2D sg2d,
101+ final GlyphList gl)
102+ {
103+ // assert rq.lock.isHeldByCurrentThread();
104+ RenderBuffer buf = rq.getBuffer();
105+ final int totalGlyphs = gl.getNumGlyphs();
106+ int glyphBytesRequired = totalGlyphs * BYTES_PER_GLYPH_IMAGE;
107+ int posBytesRequired =
108+ gl.usePositions() ? totalGlyphs * BYTES_PER_GLYPH_POSITION : 0;
109+ int totalBytesRequired = 24 + glyphBytesRequired + posBytesRequired;
110+
111+ final long[] images = gl.getImages();
112+ final float glyphListOrigX = gl.getX() + 0.5f;
113+ final float glyphListOrigY = gl.getY() + 0.5f;
114+
115+ // make sure the RenderQueue keeps a hard reference to the FontStrike
116+ // so that the associated glyph images are not disposed while enqueued
117+ rq.addReference(gl.getStrike());
118+
119+ if (totalBytesRequired <= buf.capacity()) {
120+ if (totalBytesRequired > buf.remaining()) {
121+ // process the queue first and then enqueue the glyphs
122+ rq.flushNow();
123+ }
124+ rq.ensureAlignment(20);
125+ buf.putInt(DRAW_GLYPH_LIST);
126+ // enqueue parameters
127+ buf.putInt(totalGlyphs);
128+ buf.putInt(createPackedParams(sg2d, gl));
129+ buf.putFloat(glyphListOrigX);
130+ buf.putFloat(glyphListOrigY);
131+ // now enqueue glyph information
132+ buf.put(images, 0, totalGlyphs);
133+ if (gl.usePositions()) {
134+ float[] positions = gl.getPositions();
135+ buf.put(positions, 0, 2*totalGlyphs);
136+ }
137+ } else {
138+ // queue is too small to accomodate glyphs; perform
139+ // the operation directly on the queue flushing thread
140+ rq.flushAndInvokeNow(new Runnable() {
141+ public void run() {
142+ drawGlyphList(totalGlyphs, gl.usePositions(),
143+ gl.isSubPixPos(), gl.isRGBOrder(),
144+ sg2d.lcdTextContrast,
145+ glyphListOrigX, glyphListOrigY,
146+ images, gl.getPositions());
147+ }
148+ });
149+ }
150+ }
151+
152+ /**
153+ * Called as a separate Runnable when the operation is too large to fit
154+ * on the RenderQueue. The OGL/D3D pipelines each have their own (small)
155+ * native implementation of this method.
156+ */
157+ protected abstract void drawGlyphList(int numGlyphs, boolean usePositions,
158+ boolean subPixPos, boolean rgbOrder,
159+ int lcdContrast,
160+ float glOrigX, float glOrigY,
161+ long[] images, float[] positions);
162+
163+ /**
164+ * Validates the state in the provided SunGraphics2D object.
165+ */
166+ protected abstract void validateContext(SunGraphics2D sg2d,
167+ Composite comp);
168+}
java/pkg/sun/java2d/pipe/CompositePipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/CompositePipe.java+50−0
@@ -0,0 +1,50 @@
1+/*
2+ * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Rectangle;
29+import java.awt.Shape;
30+import sun.java2d.SunGraphics2D;
31+
32+/**
33+ * This interface defines the set of calls used by a rendering pipeline
34+ * based on an AATileGenerator to communicate the alpha tile sequence
35+ * to the output (compositing) stages of the pipeline.
36+ */
37+public interface CompositePipe {
38+ public Object startSequence(SunGraphics2D sg, Shape s, Rectangle dev,
39+ int[] abox);
40+
41+ public boolean needTile(Object context, int x, int y, int w, int h);
42+
43+ public void renderPathTile(Object context,
44+ byte[] atile, int offset, int tilesize,
45+ int x, int y, int w, int h);
46+
47+ public void skipTile(Object context, int x, int y);
48+
49+ public void endSequence(Object context);
50+}
java/pkg/sun/java2d/pipe/DrawImage.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/DrawImage.java+1110−0
@@ -0,0 +1,1110 @@
1+/*
2+ * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.AlphaComposite;
29+import java.awt.Color;
30+import java.awt.Graphics2D;
31+import java.awt.Image;
32+import java.awt.Rectangle;
33+import java.awt.Transparency;
34+import java.awt.geom.AffineTransform;
35+import java.awt.geom.NoninvertibleTransformException;
36+import java.awt.image.AffineTransformOp;
37+import java.awt.image.BufferedImage;
38+import java.awt.image.BufferedImageOp;
39+import java.awt.image.ColorModel;
40+import java.awt.image.DataBuffer;
41+import java.awt.image.DirectColorModel;
42+import java.awt.image.ImageObserver;
43+import java.awt.image.IndexColorModel;
44+import java.awt.image.Raster;
45+import java.awt.image.VolatileImage;
46+import java.awt.image.WritableRaster;
47+import java.awt.image.ImagingOpException;
48+import sun.awt.SunHints;
49+import sun.awt.image.ImageRepresentation;
50+import sun.awt.image.ToolkitImage;
51+import sun.java2d.InvalidPipeException;
52+import sun.java2d.SunGraphics2D;
53+import sun.java2d.SurfaceData;
54+import sun.java2d.loops.Blit;
55+import sun.java2d.loops.BlitBg;
56+import sun.java2d.loops.TransformHelper;
57+import sun.java2d.loops.MaskBlit;
58+import sun.java2d.loops.CompositeType;
59+import sun.java2d.loops.ScaledBlit;
60+import sun.java2d.loops.SurfaceType;
61+
62+public class DrawImage implements DrawImagePipe
63+{
64+ public boolean copyImage(SunGraphics2D sg, Image img,
65+ int x, int y,
66+ Color bgColor)
67+ {
68+ int imgw = img.getWidth(null);
69+ int imgh = img.getHeight(null);
70+ if (isSimpleTranslate(sg)) {
71+ return renderImageCopy(sg, img, bgColor,
72+ x + sg.transX, y + sg.transY,
73+ 0, 0, imgw, imgh);
74+ }
75+ AffineTransform atfm = sg.transform;
76+ if ((x | y) != 0) {
77+ atfm = new AffineTransform(atfm);
78+ atfm.translate(x, y);
79+ }
80+ transformImage(sg, img, atfm, sg.interpolationType,
81+ 0, 0, imgw, imgh, bgColor);
82+ return true;
83+ }
84+
85+ public boolean copyImage(SunGraphics2D sg, Image img,
86+ int dx, int dy, int sx, int sy, int w, int h,
87+ Color bgColor)
88+ {
89+ if (isSimpleTranslate(sg)) {
90+ return renderImageCopy(sg, img, bgColor,
91+ dx + sg.transX, dy + sg.transY,
92+ sx, sy, w, h);
93+ }
94+ scaleImage(sg, img, dx, dy, (dx + w), (dy + h),
95+ sx, sy, (sx + w), (sy + h), bgColor);
96+ return true;
97+ }
98+
99+ public boolean scaleImage(SunGraphics2D sg, Image img, int x, int y,
100+ int width, int height,
101+ Color bgColor)
102+ {
103+ int imgw = img.getWidth(null);
104+ int imgh = img.getHeight(null);
105+ // Only accelerate scale if:
106+ // - w/h positive values
107+ // - sg transform integer translate/identity only
108+ // - no bgColor in operation
109+ if ((width > 0) && (height > 0) && isSimpleTranslate(sg)) {
110+ double dx1 = x + sg.transX;
111+ double dy1 = y + sg.transY;
112+ double dx2 = dx1 + width;
113+ double dy2 = dy1 + height;
114+ if (renderImageScale(sg, img, bgColor, sg.interpolationType,
115+ 0, 0, imgw, imgh,
116+ dx1, dy1, dx2, dy2))
117+ {
118+ return true;
119+ }
120+ }
121+
122+ AffineTransform atfm = sg.transform;
123+ if ((x | y) != 0 || width != imgw || height != imgh) {
124+ atfm = new AffineTransform(atfm);
125+ atfm.translate(x, y);
126+ atfm.scale(((double)width)/imgw, ((double)height)/imgh);
127+ }
128+ transformImage(sg, img, atfm, sg.interpolationType,
129+ 0, 0, imgw, imgh, bgColor);
130+ return true;
131+ }
132+
133+ /*
134+ * This method is only called in those circumstances where the
135+ * operation has a non-null secondary transform specfied. Its
136+ * role is to check for various optimizations based on the types
137+ * of both the secondary and SG2D transforms and to do some
138+ * quick calculations to avoid having to combine the transforms
139+ * and/or to call a more generalized method.
140+ */
141+ protected void transformImage(SunGraphics2D sg, Image img, int x, int y,
142+ AffineTransform extraAT, int interpType)
143+ {
144+ int txtype = extraAT.getType();
145+ int imgw = img.getWidth(null);
146+ int imgh = img.getHeight(null);
147+ boolean checkfinalxform;
148+
149+ if (sg.transformState <= sg.TRANSFORM_ANY_TRANSLATE &&
150+ (txtype == AffineTransform.TYPE_IDENTITY ||
151+ txtype == AffineTransform.TYPE_TRANSLATION))
152+ {
153+ // First optimization - both are some kind of translate
154+
155+ // Combine the translations and check if interpolation is necessary.
156+ double tx = extraAT.getTranslateX();
157+ double ty = extraAT.getTranslateY();
158+ tx += sg.transform.getTranslateX();
159+ ty += sg.transform.getTranslateY();
160+ int itx = (int) Math.floor(tx + 0.5);
161+ int ity = (int) Math.floor(ty + 0.5);
162+ if (interpType == AffineTransformOp.TYPE_NEAREST_NEIGHBOR ||
163+ (closeToInteger(itx, tx) && closeToInteger(ity, ty)))
164+ {
165+ renderImageCopy(sg, img, null, x+itx, y+ity, 0, 0, imgw, imgh);
166+ return;
167+ }
168+ checkfinalxform = false;
169+ } else if (sg.transformState <= sg.TRANSFORM_TRANSLATESCALE &&
170+ ((txtype & (AffineTransform.TYPE_FLIP |
171+ AffineTransform.TYPE_MASK_ROTATION |
172+ AffineTransform.TYPE_GENERAL_TRANSFORM)) == 0))
173+ {
174+ // Second optimization - both are some kind of translate or scale
175+
176+ // Combine the scales and check if interpolation is necessary.
177+
178+ // Transform source bounds by extraAT,
179+ // then translate the bounds again by x, y
180+ // then transform the bounds again by sg.transform
181+ double coords[] = new double[] {
182+ 0, 0, imgw, imgh,
183+ };
184+ extraAT.transform(coords, 0, coords, 0, 2);
185+ coords[0] += x;
186+ coords[1] += y;
187+ coords[2] += x;
188+ coords[3] += y;
189+ sg.transform.transform(coords, 0, coords, 0, 2);
190+
191+ if (tryCopyOrScale(sg, img, 0, 0, imgw, imgh,
192+ null, interpType, coords))
193+ {
194+ return;
195+ }
196+ checkfinalxform = false;
197+ } else {
198+ checkfinalxform = true;
199+ }
200+
201+ // Begin Transform
202+ AffineTransform tx = new AffineTransform(sg.transform);
203+ tx.translate(x, y);
204+ tx.concatenate(extraAT);
205+
206+ // Do not try any more optimizations if either of the cases
207+ // above was tried as we have already verified that the
208+ // resulting transform will not simplify.
209+ if (checkfinalxform) {
210+ // In this case neither of the above simple transform
211+ // pairs was found so we will do some final tests on
212+ // the final rendering transform which may be the
213+ // simple product of two complex transforms.
214+ transformImage(sg, img, tx, interpType, 0, 0, imgw, imgh, null);
215+ } else {
216+ renderImageXform(sg, img, tx, interpType, 0, 0, imgw, imgh, null);
217+ }
218+ }
219+
220+ /*
221+ * This method is called with a final rendering transform that
222+ * has combined all of the information about the Graphics2D
223+ * transform attribute with the transformations specified by
224+ * the arguments to the drawImage call.
225+ * Its role is to see if the combined transform ends up being
226+ * acceleratable by either a renderImageCopy or renderImageScale
227+ * once all of the math is done.
228+ *
229+ * Note: The transform supplied here has an origin that is
230+ * already adjusted to point to the device location where
231+ * the (sx1, sy1) location of the source image should be placed.
232+ */
233+ protected void transformImage(SunGraphics2D sg, Image img,
234+ AffineTransform tx, int interpType,
235+ int sx1, int sy1, int sx2, int sy2,
236+ Color bgColor)
237+ {
238+ // Transform 3 source corners by tx and analyze them
239+ // for simplified operations (Copy or Scale). Using
240+ // 3 points lets us analyze any kind of transform,
241+ // even transforms that involve very tiny amounts of
242+ // rotation or skew to see if they degenerate to a
243+ // simple scale or copy operation within the allowable
244+ // error bounds.
245+ // Note that we use (0,0,w,h) instead of (sx1,sy1,sx2,sy2)
246+ // because the transform is already translated such that
247+ // the origin is where sx1, sy1 should go.
248+ double coords[] = new double[6];
249+ /* index: 0 1 2 3 4 5 */
250+ /* coord: (0, 0), (w, h), (0, h) */
251+ coords[2] = sx2 - sx1;
252+ coords[3] = coords[5] = sy2 - sy1;
253+ tx.transform(coords, 0, coords, 0, 3);
254+ // First test if the X coords of the transformed UL
255+ // and LL points match and that the Y coords of the
256+ // transformed LR and LL points also match.
257+ // If they do then it is a "rectilinear" transform and
258+ // tryCopyOrScale will make sure it is upright and
259+ // integer-based.
260+ if (Math.abs(coords[0] - coords[4]) < MAX_TX_ERROR &&
261+ Math.abs(coords[3] - coords[5]) < MAX_TX_ERROR &&
262+ tryCopyOrScale(sg, img, sx1, sy1, sx2, sy2,
263+ bgColor, interpType, coords))
264+ {
265+ return;
266+ }
267+
268+ renderImageXform(sg, img, tx, interpType, sx1, sy1, sx2, sy2, bgColor);
269+ }
270+
271+ /*
272+ * Check the bounding coordinates of the transformed source
273+ * image to see if they fall on integer coordinates such
274+ * that they will cause no interpolation anomalies if we
275+ * use our simplified Blit or ScaledBlit operations instead
276+ * of a full transform operation.
277+ */
278+ protected boolean tryCopyOrScale(SunGraphics2D sg,
279+ Image img,
280+ int sx1, int sy1,
281+ int sx2, int sy2,
282+ Color bgColor, int interpType,
283+ double coords[])
284+ {
285+ double dx = coords[0];
286+ double dy = coords[1];
287+ double dw = coords[2] - dx;
288+ double dh = coords[3] - dy;
289+ // First check if width and height are very close to img w&h.
290+ if (closeToInteger(sx2-sx1, dw) && closeToInteger(sy2-sy1, dh)) {
291+ // Round location to nearest pixel and then test
292+ // if it will cause interpolation anomalies.
293+ int idx = (int) Math.floor(dx + 0.5);
294+ int idy = (int) Math.floor(dy + 0.5);
295+ if (interpType == AffineTransformOp.TYPE_NEAREST_NEIGHBOR ||
296+ (closeToInteger(idx, dx) && closeToInteger(idy, dy)))
297+ {
298+ renderImageCopy(sg, img, bgColor,
299+ idx, idy,
300+ sx1, sy1, sx2-sx1, sy2-sy1);
301+ return true;
302+ }
303+ }
304+ // (For now) We can only use our ScaledBlits if the image
305+ // is upright (i.e. dw & dh both > 0)
306+ if (dw > 0 && dh > 0) {
307+ if (renderImageScale(sg, img, bgColor, interpType,
308+ sx1, sy1, sx2, sy2,
309+ coords[0], coords[1], coords[2], coords[3]))
310+ {
311+ return true;
312+ }
313+ }
314+ return false;
315+ }
316+
317+ /*
318+ * Return a BufferedImage of the requested type with the indicated
319+ * subimage of the original image located at 0,0 in the new image.
320+ * If a bgColor is supplied, composite the original image over that
321+ * color with a SrcOver operation, otherwise make a SrcNoEa copy.
322+ */
323+ BufferedImage makeBufferedImage(Image img, Color bgColor, int type,
324+ int sx1, int sy1, int sx2, int sy2)
325+ {
326+ BufferedImage bimg = new BufferedImage(sx2-sx1, sy2-sy1, type);
327+ Graphics2D g2d = bimg.createGraphics();
328+ g2d.setComposite(AlphaComposite.Src);
329+ if (bgColor != null) {
330+ g2d.setColor(bgColor);
331+ g2d.fillRect(0, 0, sx2-sx1, sy2-sy1);
332+ g2d.setComposite(AlphaComposite.SrcOver);
333+ }
334+ g2d.drawImage(img, -sx1, -sy1, null);
335+ g2d.dispose();
336+ return bimg;
337+ }
338+
339+ protected void renderImageXform(SunGraphics2D sg, Image img,
340+ AffineTransform tx, int interpType,
341+ int sx1, int sy1, int sx2, int sy2,
342+ Color bgColor)
343+ {
344+ Region clip = sg.getCompClip();
345+ SurfaceData dstData = sg.surfaceData;
346+ SurfaceData srcData = dstData.getSourceSurfaceData(img,
347+ sg.TRANSFORM_GENERIC,
348+ sg.imageComp,
349+ bgColor);
350+
351+ if (srcData == null) {
352+ img = getBufferedImage(img);
353+ srcData = dstData.getSourceSurfaceData(img,
354+ sg.TRANSFORM_GENERIC,
355+ sg.imageComp,
356+ bgColor);
357+ if (srcData == null) {
358+ // REMIND: Is this correct? Can this happen?
359+ return;
360+ }
361+ }
362+
363+ if (isBgOperation(srcData, bgColor)) {
364+ // We cannot perform bg operations during transform so make
365+ // an opaque temp image with the appropriate background
366+ // and work from there.
367+ img = makeBufferedImage(img, bgColor, BufferedImage.TYPE_INT_RGB,
368+ sx1, sy1, sx2, sy2);
369+ // Temp image has appropriate subimage at 0,0 now.
370+ sx2 -= sx1;
371+ sy2 -= sy1;
372+ sx1 = sy1 = 0;
373+
374+ srcData = dstData.getSourceSurfaceData(img,
375+ sg.TRANSFORM_GENERIC,
376+ sg.imageComp,
377+ bgColor);
378+ }
379+
380+ SurfaceType srcType = srcData.getSurfaceType();
381+ TransformHelper helper = TransformHelper.getFromCache(srcType);
382+
383+ if (helper == null) {
384+ /* We have no helper for this source image type.
385+ * But we know that we do have helpers for both RGB and ARGB,
386+ * so convert to one of those types depending on transparency.
387+ * ARGB_PRE might be a better choice if the source image has
388+ * alpha, but it may cause some recursion here since we only
389+ * tend to have converters that convert to ARGB.
390+ */
391+ int type = ((srcData.getTransparency() == Transparency.OPAQUE)
392+ ? BufferedImage.TYPE_INT_RGB
393+ : BufferedImage.TYPE_INT_ARGB);
394+ img = makeBufferedImage(img, null, type, sx1, sy1, sx2, sy2);
395+ // Temp image has appropriate subimage at 0,0 now.
396+ sx2 -= sx1;
397+ sy2 -= sy1;
398+ sx1 = sy1 = 0;
399+
400+ srcData = dstData.getSourceSurfaceData(img,
401+ sg.TRANSFORM_GENERIC,
402+ sg.imageComp,
403+ null);
404+ srcType = srcData.getSurfaceType();
405+ helper = TransformHelper.getFromCache(srcType);
406+ // assert(helper != null);
407+ }
408+
409+ AffineTransform itx;
410+ try {
411+ itx = tx.createInverse();
412+ } catch (NoninvertibleTransformException e) {
413+ // Non-invertible transform means no output
414+ return;
415+ }
416+
417+ /*
418+ * Find the maximum bounds on the destination that will be
419+ * affected by the transformed source. First, transform all
420+ * four corners of the source and then min and max the resulting
421+ * destination coordinates of the transformed corners.
422+ * Note that tx already has the offset to sx1,sy1 accounted
423+ * for so we use the box (0, 0, sx2-sx1, sy2-sy1) as the
424+ * source coordinates.
425+ */
426+ double coords[] = new double[8];
427+ /* corner: UL UR LL LR */
428+ /* index: 0 1 2 3 4 5 6 7 */
429+ /* coord: (0, 0), (w, 0), (0, h), (w, h) */
430+ coords[2] = coords[6] = sx2 - sx1;
431+ coords[5] = coords[7] = sy2 - sy1;
432+ tx.transform(coords, 0, coords, 0, 4);
433+ double ddx1, ddy1, ddx2, ddy2;
434+ ddx1 = ddx2 = coords[0];
435+ ddy1 = ddy2 = coords[1];
436+ for (int i = 2; i < coords.length; i += 2) {
437+ double d = coords[i];
438+ if (ddx1 > d) ddx1 = d;
439+ else if (ddx2 < d) ddx2 = d;
440+ d = coords[i+1];
441+ if (ddy1 > d) ddy1 = d;
442+ else if (ddy2 < d) ddy2 = d;
443+ }
444+ int dx1 = (int) Math.floor(ddx1);
445+ int dy1 = (int) Math.floor(ddy1);
446+ int dx2 = (int) Math.ceil(ddx2);
447+ int dy2 = (int) Math.ceil(ddy2);
448+
449+ SurfaceType dstType = dstData.getSurfaceType();
450+ MaskBlit maskblit;
451+ Blit blit;
452+ if (sg.compositeState <= sg.COMP_ALPHA) {
453+ /* NOTE: We either have, or we can make,
454+ * a MaskBlit for any alpha composite type
455+ */
456+ maskblit = MaskBlit.getFromCache(SurfaceType.IntArgbPre,
457+ sg.imageComp,
458+ dstType);
459+
460+ /* NOTE: We can only use the native TransformHelper
461+ * func to go directly to the dest if both the helper
462+ * and the MaskBlit are native.
463+ * All helpers are native at this point, but some MaskBlit
464+ * objects are implemented in Java, so we need to check.
465+ */
466+ if (maskblit.getNativePrim() != 0) {
467+ // We can render directly.
468+ helper.Transform(maskblit, srcData, dstData,
469+ sg.composite, clip,
470+ itx, interpType,
471+ sx1, sy1, sx2, sy2,
472+ dx1, dy1, dx2, dy2,
473+ null, 0, 0);
474+ return;
475+ }
476+ blit = null;
477+ } else {
478+ /* NOTE: We either have, or we can make,
479+ * a Blit for any composite type, even Custom
480+ */
481+ maskblit = null;
482+ blit = Blit.getFromCache(SurfaceType.IntArgbPre,
483+ sg.imageComp,
484+ dstType);
485+ }
486+
487+ // We need to transform to a temp image and then copy
488+ // just the pieces that are valid data to the dest.
489+ BufferedImage tmpimg = new BufferedImage(dx2-dx1, dy2-dy1,
490+ BufferedImage.TYPE_INT_ARGB);
491+ SurfaceData tmpData = SurfaceData.getPrimarySurfaceData(tmpimg);
492+ SurfaceType tmpType = tmpData.getSurfaceType();
493+ MaskBlit tmpmaskblit =
494+ MaskBlit.getFromCache(SurfaceType.IntArgbPre,
495+ CompositeType.SrcNoEa,
496+ tmpType);
497+ /*
498+ * The helper function fills a temporary edges buffer
499+ * for us with the bounding coordinates of each scanline
500+ * in the following format:
501+ *
502+ * edges[0, 1] = [top y, bottom y)
503+ * edges[2, 3] = [left x, right x) of top row
504+ * ...
505+ * edges[h*2, h*2+1] = [left x, right x) of bottom row
506+ *
507+ * all coordinates in the edges array will be relative to dx1, dy1
508+ *
509+ * edges thus has to be h*2+2 in length
510+ */
511+ int edges[] = new int[(dy2-dy1)*2+2];
512+ // It is important that edges[0]=edges[1]=0 when we call
513+ // Transform in case it must return early and we would
514+ // not want to render anything on an error condition.
515+ helper.Transform(tmpmaskblit, srcData, tmpData,
516+ AlphaComposite.Src, null,
517+ itx, interpType,
518+ sx1, sy1, sx2, sy2,
519+ 0, 0, dx2-dx1, dy2-dy1,
520+ edges, dx1, dy1);
521+
522+ /*
523+ * Now copy the results, scanline by scanline, into the dest.
524+ * The edges array helps us minimize the work.
525+ */
526+ int index = 2;
527+ for (int y = edges[0]; y < edges[1]; y++) {
528+ int relx1 = edges[index++];
529+ int relx2 = edges[index++];
530+ if (relx1 >= relx2) {
531+ continue;
532+ }
533+ if (maskblit != null) {
534+ maskblit.MaskBlit(tmpData, dstData,
535+ sg.composite, clip,
536+ relx1, y,
537+ dx1+relx1, dy1+y,
538+ relx2 - relx1, 1,
539+ null, 0, 0);
540+ } else {
541+ blit.Blit(tmpData, dstData,
542+ sg.composite, clip,
543+ relx1, y,
544+ dx1+relx1, dy1+y,
545+ relx2 - relx1, 1);
546+ }
547+ }
548+ }
549+
550+ // Render an image using only integer translation
551+ // (no scale or transform or sub-pixel interpolated translations).
552+ protected boolean renderImageCopy(SunGraphics2D sg, Image img,
553+ Color bgColor,
554+ int dx, int dy,
555+ int sx, int sy,
556+ int w, int h)
557+ {
558+ Region clip = sg.getCompClip();
559+ SurfaceData dstData = sg.surfaceData;
560+
561+ int attempts = 0;
562+ // Loop up to twice through; this gives us a chance to
563+ // revalidate the surfaceData objects in case of an exception
564+ // and try it once more
565+ while (true) {
566+ SurfaceData srcData =
567+ dstData.getSourceSurfaceData(img,
568+ sg.TRANSFORM_ISIDENT,
569+ sg.imageComp,
570+ bgColor);
571+ if (srcData == null) {
572+ return false;
573+ }
574+
575+ try {
576+ SurfaceType srcType = srcData.getSurfaceType();
577+ SurfaceType dstType = dstData.getSurfaceType();
578+ blitSurfaceData(sg, clip,
579+ srcData, dstData, srcType, dstType,
580+ sx, sy, dx, dy, w, h, bgColor);
581+ return true;
582+ } catch (NullPointerException e) {
583+ if (!(SurfaceData.isNull(dstData) ||
584+ SurfaceData.isNull(srcData)))
585+ {
586+ // Something else caused the exception, throw it...
587+ throw e;
588+ }
589+ return false;
590+ // NOP if we have been disposed
591+ } catch (InvalidPipeException e) {
592+ // Always catch the exception; try this a couple of times
593+ // and fail silently if the system is not yet ready to
594+ // revalidate the source or dest surfaceData objects.
595+ ++attempts;
596+ clip = sg.getCompClip(); // ensures sg.surfaceData is valid
597+ dstData = sg.surfaceData;
598+ if (SurfaceData.isNull(dstData) ||
599+ SurfaceData.isNull(srcData) || (attempts > 1))
600+ {
601+ return false;
602+ }
603+ }
604+ }
605+ }
606+
607+ // Render an image using only integer scaling (no transform).
608+ protected boolean renderImageScale(SunGraphics2D sg, Image img,
609+ Color bgColor, int interpType,
610+ int sx1, int sy1,
611+ int sx2, int sy2,
612+ double dx1, double dy1,
613+ double dx2, double dy2)
614+ {
615+ // Currently only NEAREST_NEIGHBOR interpolation is implemented
616+ // for ScaledBlit operations.
617+ if (interpType != AffineTransformOp.TYPE_NEAREST_NEIGHBOR) {
618+ return false;
619+ }
620+
621+ Region clip = sg.getCompClip();
622+ SurfaceData dstData = sg.surfaceData;
623+
624+ int attempts = 0;
625+ // Loop up to twice through; this gives us a chance to
626+ // revalidate the surfaceData objects in case of an exception
627+ // and try it once more
628+ while (true) {
629+ SurfaceData srcData =
630+ dstData.getSourceSurfaceData(img,
631+ sg.TRANSFORM_TRANSLATESCALE,
632+ sg.imageComp,
633+ bgColor);
634+
635+ if (srcData == null || isBgOperation(srcData, bgColor)) {
636+ return false;
637+ }
638+
639+ try {
640+ SurfaceType srcType = srcData.getSurfaceType();
641+ SurfaceType dstType = dstData.getSurfaceType();
642+ return scaleSurfaceData(sg, clip,
643+ srcData, dstData, srcType, dstType,
644+ sx1, sy1, sx2, sy2,
645+ dx1, dy1, dx2, dy2);
646+ } catch (NullPointerException e) {
647+ if (!SurfaceData.isNull(dstData)) {
648+ // Something else caused the exception, throw it...
649+ throw e;
650+ }
651+ return false;
652+ // NOP if we have been disposed
653+ } catch (InvalidPipeException e) {
654+ // Always catch the exception; try this a couple of times
655+ // and fail silently if the system is not yet ready to
656+ // revalidate the source or dest surfaceData objects.
657+ ++attempts;
658+ clip = sg.getCompClip(); // ensures sg.surfaceData is valid
659+ dstData = sg.surfaceData;
660+ if (SurfaceData.isNull(dstData) ||
661+ SurfaceData.isNull(srcData) || (attempts > 1))
662+ {
663+ return false;
664+ }
665+ }
666+ }
667+ }
668+
669+ public boolean scaleImage(SunGraphics2D sg, Image img,
670+ int dx1, int dy1, int dx2, int dy2,
671+ int sx1, int sy1, int sx2, int sy2,
672+ Color bgColor)
673+ {
674+ int srcW, srcH, dstW, dstH;
675+ int srcX, srcY, dstX, dstY;
676+ boolean srcWidthFlip = false;
677+ boolean srcHeightFlip = false;
678+ boolean dstWidthFlip = false;
679+ boolean dstHeightFlip = false;
680+
681+ if (sx2 > sx1) {
682+ srcW = sx2 - sx1;
683+ srcX = sx1;
684+ } else {
685+ srcWidthFlip = true;
686+ srcW = sx1 - sx2;
687+ srcX = sx2;
688+ }
689+ if (sy2 > sy1) {
690+ srcH = sy2-sy1;
691+ srcY = sy1;
692+ } else {
693+ srcHeightFlip = true;
694+ srcH = sy1-sy2;
695+ srcY = sy2;
696+ }
697+ if (dx2 > dx1) {
698+ dstW = dx2 - dx1;
699+ dstX = dx1;
700+ } else {
701+ dstW = dx1 - dx2;
702+ dstWidthFlip = true;
703+ dstX = dx2;
704+ }
705+ if (dy2 > dy1) {
706+ dstH = dy2 - dy1;
707+ dstY = dy1;
708+ } else {
709+ dstH = dy1 - dy2;
710+ dstHeightFlip = true;
711+ dstY = dy2;
712+ }
713+ if (srcW <= 0 || srcH <= 0) {
714+ return true;
715+ }
716+ // Only accelerate scale if it does not involve a flip or transform
717+ if ((srcWidthFlip == dstWidthFlip) &&
718+ (srcHeightFlip == dstHeightFlip) &&
719+ isSimpleTranslate(sg))
720+ {
721+ double ddx1 = dstX + sg.transX;
722+ double ddy1 = dstY + sg.transY;
723+ double ddx2 = ddx1 + dstW;
724+ double ddy2 = ddy1 + dstH;
725+ if (renderImageScale(sg, img, bgColor, sg.interpolationType,
726+ srcX, srcY, srcX+srcW, srcY+srcH,
727+ ddx1, ddy1, ddx2, ddy2))
728+ {
729+ return true;
730+ }
731+ }
732+
733+ AffineTransform atfm = new AffineTransform(sg.transform);
734+ atfm.translate(dx1, dy1);
735+ double m00 = (double)(dx2-dx1)/(sx2-sx1);
736+ double m11 = (double)(dy2-dy1)/(sy2-sy1);
737+ atfm.scale(m00, m11);
738+ atfm.translate(srcX-sx1, srcY-sy1);
739+
740+ int imgW = img.getWidth(null);
741+ int imgH = img.getHeight(null);
742+ srcW += srcX;
743+ srcH += srcY;
744+ // Make sure we are not out of bounds
745+ if (srcW > imgW) {
746+ srcW = imgW;
747+ }
748+ if (srcH > imgH) {
749+ srcH = imgH;
750+ }
751+ if (srcX < 0) {
752+ atfm.translate(-srcX, 0);
753+ srcX = 0;
754+ }
755+ if (srcY < 0) {
756+ atfm.translate(0, -srcY);
757+ srcY = 0;
758+ }
759+ if (srcX >= srcW || srcY >= srcH) {
760+ return true;
761+ }
762+ // Note: src[WH] are currently the right and bottom coordinates.
763+ // The following two lines would adjust src[WH] back to being
764+ // dimensions.
765+ // srcW -= srcX;
766+ // srcH -= srcY;
767+ // Since transformImage needs right and bottom coords we will
768+ // omit this adjustment.
769+
770+ transformImage(sg, img, atfm, sg.interpolationType,
771+ srcX, srcY, srcW, srcH, bgColor);
772+ return true;
773+ }
774+
775+ /**
776+ ** Utilities
777+ ** The following methods are used by the public methods above
778+ ** for performing various operations
779+ **/
780+
781+ /*
782+ * This constant represents a tradeoff between the
783+ * need to make sure that image transformations are
784+ * "very close" to integer device coordinates before
785+ * we decide to use an integer scale or copy operation
786+ * as a substitute and the fact that roundoff errors
787+ * in AffineTransforms are frequently introduced by
788+ * performing multiple sequential operations on them.
789+ *
790+ * The evaluation of bug 4990624 details the potential
791+ * for this error cutoff to result in display anomalies
792+ * in different types of image operations and how this
793+ * value represents a good compromise here.
794+ */
795+ private static final double MAX_TX_ERROR = .0001;
796+
797+ public static boolean closeToInteger(int i, double d) {
798+ return (Math.abs(d-i) < MAX_TX_ERROR);
799+ }
800+
801+ public static boolean isSimpleTranslate(SunGraphics2D sg) {
802+ int ts = sg.transformState;
803+ if (ts <= sg.TRANSFORM_INT_TRANSLATE) {
804+ // Integer translates are always "simple"
805+ return true;
806+ }
807+ if (ts >= sg.TRANSFORM_TRANSLATESCALE) {
808+ // Scales and beyond are always "not simple"
809+ return false;
810+ }
811+ // non-integer translates are only simple when not interpolating
812+ if (sg.interpolationType == AffineTransformOp.TYPE_NEAREST_NEIGHBOR) {
813+ return true;
814+ }
815+ return false;
816+ }
817+
818+ protected static boolean isBgOperation(SurfaceData srcData, Color bgColor) {
819+ // If we cannot get the srcData, then cannot assume anything about
820+ // the image
821+ return ((srcData == null) ||
822+ ((bgColor != null) &&
823+ (srcData.getTransparency() != Transparency.OPAQUE)));
824+ }
825+
826+ protected BufferedImage getBufferedImage(Image img) {
827+ if (img instanceof BufferedImage) {
828+ return (BufferedImage)img;
829+ }
830+ // Must be VolatileImage; get BufferedImage representation
831+ return ((VolatileImage)img).getSnapshot();
832+ }
833+
834+ /*
835+ * Return the color model to be used with this BufferedImage and
836+ * transform.
837+ */
838+ private ColorModel getTransformColorModel(SunGraphics2D sg,
839+ BufferedImage bImg,
840+ AffineTransform tx) {
841+ ColorModel cm = bImg.getColorModel();
842+ ColorModel dstCM = cm;
843+
844+ if (tx.isIdentity()) {
845+ return dstCM;
846+ }
847+ int type = tx.getType();
848+ boolean needTrans =
849+ ((type&(tx.TYPE_MASK_ROTATION|tx.TYPE_GENERAL_TRANSFORM)) != 0);
850+ if (! needTrans && type != tx.TYPE_TRANSLATION && type != tx.TYPE_IDENTITY)
851+ {
852+ double[] mtx = new double[4];
853+ tx.getMatrix(mtx);
854+ // Check out the matrix. A non-integral scale will force ARGB
855+ // since the edge conditions cannot be guaranteed.
856+ needTrans = (mtx[0] != (int)mtx[0] || mtx[3] != (int)mtx[3]);
857+ }
858+
859+ if (sg.renderHint != SunHints.INTVAL_RENDER_QUALITY) {
860+ if (cm instanceof IndexColorModel) {
861+ Raster raster = bImg.getRaster();
862+ IndexColorModel icm = (IndexColorModel) cm;
863+ // Just need to make sure that we have a transparent pixel
864+ if (needTrans && cm.getTransparency() == cm.OPAQUE) {
865+ // Fix 4221407
866+ if (raster instanceof sun.awt.image.BytePackedRaster) {
867+ dstCM = ColorModel.getRGBdefault();
868+ }
869+ else {
870+ double[] matrix = new double[6];
871+ tx.getMatrix(matrix);
872+ if (matrix[1] == 0. && matrix[2] ==0.
873+ && matrix[4] == 0. && matrix[5] == 0.) {
874+ // Only scaling so do not need to create
875+ }
876+ else {
877+ int mapSize = icm.getMapSize();
878+ if (mapSize < 256) {
879+ int[] cmap = new int[mapSize+1];
880+ icm.getRGBs(cmap);
881+ cmap[mapSize] = 0x0000;
882+ dstCM = new
883+ IndexColorModel(icm.getPixelSize(),
884+ mapSize+1,
885+ cmap, 0, true, mapSize,
886+ DataBuffer.TYPE_BYTE);
887+ }
888+ else {
889+ dstCM = ColorModel.getRGBdefault();
890+ }
891+ } /* if (matrix[0] < 1.f ...) */
892+ } /* raster instanceof sun.awt.image.BytePackedRaster */
893+ } /* if (cm.getTransparency() == cm.OPAQUE) */
894+ } /* if (cm instanceof IndexColorModel) */
895+ else if (needTrans && cm.getTransparency() == cm.OPAQUE) {
896+ // Need a bitmask transparency
897+ // REMIND: for now, use full transparency since no loops
898+ // for bitmask
899+ dstCM = ColorModel.getRGBdefault();
900+ }
901+ } /* if (sg.renderHint == RENDER_QUALITY) */
902+ else {
903+
904+ if (cm instanceof IndexColorModel ||
905+ (needTrans && cm.getTransparency() == cm.OPAQUE))
906+ {
907+ // Need a bitmask transparency
908+ // REMIND: for now, use full transparency since no loops
909+ // for bitmask
910+ dstCM = ColorModel.getRGBdefault();
911+ }
912+ }
913+
914+ return dstCM;
915+ }
916+
917+ protected void blitSurfaceData(SunGraphics2D sg,
918+ Region clipRegion,
919+ SurfaceData srcData,
920+ SurfaceData dstData,
921+ SurfaceType srcType,
922+ SurfaceType dstType,
923+ int sx, int sy, int dx, int dy,
924+ int w, int h,
925+ Color bgColor)
926+ {
927+ if (w <= 0 || h <= 0) {
928+ /*
929+ * Fix for bugid 4783274 - BlitBg throws an exception for
930+ * a particular set of anomalous parameters.
931+ * REMIND: The native loops do proper clipping and would
932+ * detect this situation themselves, but the Java loops
933+ * all seem to trust their parameters a little too well
934+ * to the point where they will try to process a negative
935+ * area of pixels and throw exceptions. The real fix is
936+ * to modify the Java loops to do proper clipping so that
937+ * they can deal with negative dimensions as well as
938+ * improperly large dimensions, but that fix is too risky
939+ * to integrate for Mantis at this point. In the meantime
940+ * eliminating the negative or zero dimensions here is
941+ * "correct" and saves them from some nasty exceptional
942+ * conditions, one of which is the test case of 4783274.
943+ */
944+ return;
945+ }
946+ CompositeType comp = sg.imageComp;
947+ if (CompositeType.SrcOverNoEa.equals(comp) &&
948+ (srcData.getTransparency() == Transparency.OPAQUE ||
949+ (bgColor != null &&
950+ bgColor.getTransparency() == Transparency.OPAQUE)))
951+ {
952+ comp = CompositeType.SrcNoEa;
953+ }
954+ if (!isBgOperation(srcData, bgColor)) {
955+ Blit blit = Blit.getFromCache(srcType, comp, dstType);
956+ blit.Blit(srcData, dstData, sg.composite, clipRegion,
957+ sx, sy, dx, dy, w, h);
958+ } else {
959+ BlitBg blit = BlitBg.getFromCache(srcType, comp, dstType);
960+ blit.BlitBg(srcData, dstData, sg.composite, clipRegion,
961+ bgColor.getRGB(), sx, sy, dx, dy, w, h);
962+ }
963+ }
964+
965+ protected boolean scaleSurfaceData(SunGraphics2D sg,
966+ Region clipRegion,
967+ SurfaceData srcData,
968+ SurfaceData dstData,
969+ SurfaceType srcType,
970+ SurfaceType dstType,
971+ int sx1, int sy1,
972+ int sx2, int sy2,
973+ double dx1, double dy1,
974+ double dx2, double dy2)
975+ {
976+ CompositeType comp = sg.imageComp;
977+ if (CompositeType.SrcOverNoEa.equals(comp) &&
978+ (srcData.getTransparency() == Transparency.OPAQUE))
979+ {
980+ comp = CompositeType.SrcNoEa;
981+ }
982+
983+ ScaledBlit blit = ScaledBlit.getFromCache(srcType, comp, dstType);
984+ if (blit != null) {
985+ blit.Scale(srcData, dstData, sg.composite, clipRegion,
986+ sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
987+ return true;
988+ }
989+ return false;
990+ }
991+
992+ protected static boolean imageReady(ToolkitImage sunimg,
993+ ImageObserver observer)
994+ {
995+ if (sunimg.hasError()) {
996+ if (observer != null) {
997+ observer.imageUpdate(sunimg,
998+ ImageObserver.ERROR|ImageObserver.ABORT,
999+ -1, -1, -1, -1);
1000+ }
1001+ return false;
1002+ }
1003+ return true;
1004+ }
1005+
1006+ public boolean copyImage(SunGraphics2D sg, Image img,
1007+ int x, int y,
1008+ Color bgColor,
1009+ ImageObserver observer) {
1010+ if (!(img instanceof ToolkitImage)) {
1011+ return copyImage(sg, img, x, y, bgColor);
1012+ } else {
1013+ ToolkitImage sunimg = (ToolkitImage)img;
1014+ if (!imageReady(sunimg, observer)) {
1015+ return false;
1016+ }
1017+ ImageRepresentation ir = sunimg.getImageRep();
1018+ return ir.drawToBufImage(sg, sunimg, x, y, bgColor, observer);
1019+ }
1020+ }
1021+
1022+ public boolean copyImage(SunGraphics2D sg, Image img,
1023+ int dx, int dy, int sx, int sy, int w, int h,
1024+ Color bgColor,
1025+ ImageObserver observer) {
1026+ if (!(img instanceof ToolkitImage)) {
1027+ return copyImage(sg, img, dx, dy, sx, sy, w, h, bgColor);
1028+ } else {
1029+ ToolkitImage sunimg = (ToolkitImage)img;
1030+ if (!imageReady(sunimg, observer)) {
1031+ return false;
1032+ }
1033+ ImageRepresentation ir = sunimg.getImageRep();
1034+ return ir.drawToBufImage(sg, sunimg,
1035+ dx, dy, (dx + w), (dy + h),
1036+ sx, sy, (sx + w), (sy + h),
1037+ bgColor, observer);
1038+ }
1039+ }
1040+
1041+ public boolean scaleImage(SunGraphics2D sg, Image img,
1042+ int x, int y,
1043+ int width, int height,
1044+ Color bgColor,
1045+ ImageObserver observer) {
1046+ if (!(img instanceof ToolkitImage)) {
1047+ return scaleImage(sg, img, x, y, width, height, bgColor);
1048+ } else {
1049+ ToolkitImage sunimg = (ToolkitImage)img;
1050+ if (!imageReady(sunimg, observer)) {
1051+ return false;
1052+ }
1053+ ImageRepresentation ir = sunimg.getImageRep();
1054+ return ir.drawToBufImage(sg, sunimg, x, y, width, height, bgColor,
1055+ observer);
1056+ }
1057+ }
1058+
1059+ public boolean scaleImage(SunGraphics2D sg, Image img,
1060+ int dx1, int dy1, int dx2, int dy2,
1061+ int sx1, int sy1, int sx2, int sy2,
1062+ Color bgColor,
1063+ ImageObserver observer) {
1064+ if (!(img instanceof ToolkitImage)) {
1065+ return scaleImage(sg, img, dx1, dy1, dx2, dy2,
1066+ sx1, sy1, sx2, sy2, bgColor);
1067+ } else {
1068+ ToolkitImage sunimg = (ToolkitImage)img;
1069+ if (!imageReady(sunimg, observer)) {
1070+ return false;
1071+ }
1072+ ImageRepresentation ir = sunimg.getImageRep();
1073+ return ir.drawToBufImage(sg, sunimg, dx1, dy1, dx2, dy2,
1074+ sx1, sy1, sx2, sy2, bgColor, observer);
1075+ }
1076+ }
1077+
1078+ public boolean transformImage(SunGraphics2D sg, Image img,
1079+ AffineTransform atfm,
1080+ ImageObserver observer) {
1081+ if (!(img instanceof ToolkitImage)) {
1082+ transformImage(sg, img, 0, 0, atfm, sg.interpolationType);
1083+ return true;
1084+ } else {
1085+ ToolkitImage sunimg = (ToolkitImage)img;
1086+ if (!imageReady(sunimg, observer)) {
1087+ return false;
1088+ }
1089+ ImageRepresentation ir = sunimg.getImageRep();
1090+ return ir.drawToBufImage(sg, sunimg, atfm, observer);
1091+ }
1092+ }
1093+
1094+ public void transformImage(SunGraphics2D sg, BufferedImage img,
1095+ BufferedImageOp op, int x, int y)
1096+ {
1097+ if (op != null) {
1098+ if (op instanceof AffineTransformOp) {
1099+ AffineTransformOp atop = (AffineTransformOp) op;
1100+ transformImage(sg, img, x, y,
1101+ atop.getTransform(),
1102+ atop.getInterpolationType());
1103+ return;
1104+ } else {
1105+ img = op.filter(img, null);
1106+ }
1107+ }
1108+ copyImage(sg, img, x, y, null);
1109+ }
1110+}
java/pkg/sun/java2d/pipe/DrawImagePipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/DrawImagePipe.java+86−0
@@ -0,0 +1,86 @@
1+/*
2+ * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Color;
29+import java.awt.Image;
30+import java.awt.image.BufferedImage;
31+import java.awt.image.BufferedImageOp;
32+import java.awt.image.ImageObserver;
33+import java.awt.geom.AffineTransform;
34+import sun.java2d.SunGraphics2D;
35+
36+/**
37+ * This interface defines the set of calls that pipeline objects
38+ * can use to pass on responsibility for performing various
39+ * image copy commands.
40+ * There are 3 types of image copies handled by this class:
41+ * - copyImage: These methods simply copy the pixels
42+ * from the src to dest, either from (0, 0) (implicit)
43+ * or from a given (sx, sy) location.
44+ * - scaleImage: These methods copy from src to dest while
45+ * scaling the source image. The src and dest rectangles
46+ * are used to specify the scale.
47+ * - copyImageBg: These methods behave the same as the
48+ * copyImage methods except they substitute the given
49+ * background color for any transparent pixels.
50+ * - scaleImageBg: These methods behave the same as the
51+ * scaleImage methods except they substitute the given
52+ * background color for any transparent pixels.
53+ * - transformImage....
54+ */
55+public interface DrawImagePipe {
56+
57+ public boolean copyImage(SunGraphics2D sg, Image img,
58+ int x, int y,
59+ Color bgColor,
60+ ImageObserver observer);
61+
62+ public boolean copyImage(SunGraphics2D sg, Image img,
63+ int dx, int dy, int sx, int sy, int w, int h,
64+ Color bgColor,
65+ ImageObserver observer);
66+
67+ public boolean scaleImage(SunGraphics2D sg, Image img, int x, int y,
68+ int width, int height,
69+ Color bgColor,
70+ ImageObserver observer);
71+
72+ public boolean scaleImage(SunGraphics2D sg, Image img,
73+ int dx1, int dy1, int dx2, int dy2,
74+ int sx1, int sy1, int sx2, int sy2,
75+ Color bgColor,
76+ ImageObserver observer);
77+
78+ public boolean transformImage(SunGraphics2D sg, Image img,
79+ AffineTransform atfm,
80+ ImageObserver observer);
81+
82+ public void transformImage(SunGraphics2D sg, BufferedImage img,
83+ BufferedImageOp op, int x, int y);
84+
85+
86+}
java/pkg/sun/java2d/pipe/GeneralCompositePipe$TileContext.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/GeneralCompositePipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/GeneralCompositePipe.java+154−0
@@ -0,0 +1,154 @@
1+/*
2+ * Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.AlphaComposite;
29+import java.awt.CompositeContext;
30+import java.awt.PaintContext;
31+import java.awt.Rectangle;
32+import java.awt.Shape;
33+import java.awt.RenderingHints;
34+import java.awt.image.ColorModel;
35+import java.awt.image.BufferedImage;
36+import java.awt.image.Raster;
37+import java.awt.image.WritableRaster;
38+import sun.awt.image.BufImgSurfaceData;
39+import sun.java2d.SunGraphics2D;
40+import sun.java2d.SurfaceData;
41+import sun.java2d.loops.Blit;
42+import sun.java2d.loops.MaskBlit;
43+import sun.java2d.loops.CompositeType;
44+
45+public class GeneralCompositePipe implements CompositePipe {
46+ class TileContext {
47+ SunGraphics2D sunG2D;
48+ PaintContext paintCtxt;
49+ CompositeContext compCtxt;
50+ ColorModel compModel;
51+ Object pipeState;
52+
53+ public TileContext(SunGraphics2D sg, PaintContext pCtx,
54+ CompositeContext cCtx, ColorModel cModel) {
55+ sunG2D = sg;
56+ paintCtxt = pCtx;
57+ compCtxt = cCtx;
58+ compModel = cModel;
59+ }
60+ }
61+
62+ public Object startSequence(SunGraphics2D sg, Shape s, Rectangle devR,
63+ int[] abox) {
64+ RenderingHints hints = sg.getRenderingHints();
65+ ColorModel model = sg.getDeviceColorModel();
66+ PaintContext paintContext =
67+ sg.paint.createContext(model, devR, s.getBounds2D(),
68+ sg.cloneTransform(),
69+ hints);
70+ CompositeContext compositeContext =
71+ sg.composite.createContext(paintContext.getColorModel(), model,
72+ hints);
73+ return new TileContext(sg, paintContext, compositeContext, model);
74+ }
75+
76+ public boolean needTile(Object ctx, int x, int y, int w, int h) {
77+ return true;
78+ }
79+
80+ /**
81+ * GeneralCompositePipe.renderPathTile works with custom composite operator
82+ * provided by an application
83+ */
84+ public void renderPathTile(Object ctx,
85+ byte[] atile, int offset, int tilesize,
86+ int x, int y, int w, int h) {
87+ TileContext context = (TileContext) ctx;
88+ PaintContext paintCtxt = context.paintCtxt;
89+ CompositeContext compCtxt = context.compCtxt;
90+ SunGraphics2D sg = context.sunG2D;
91+
92+ Raster srcRaster = paintCtxt.getRaster(x, y, w, h);
93+ ColorModel paintModel = paintCtxt.getColorModel();
94+
95+ Raster dstRaster;
96+ Raster dstIn;
97+ WritableRaster dstOut;
98+
99+ SurfaceData sd = sg.getSurfaceData();
100+ dstRaster = sd.getRaster(x, y, w, h);
101+ if (dstRaster instanceof WritableRaster && atile == null) {
102+ dstOut = (WritableRaster) dstRaster;
103+ dstOut = dstOut.createWritableChild(x, y, w, h, 0, 0, null);
104+ dstIn = dstOut;
105+ } else {
106+ dstIn = dstRaster.createChild(x, y, w, h, 0, 0, null);
107+ dstOut = dstIn.createCompatibleWritableRaster();
108+ }
109+
110+ compCtxt.compose(srcRaster, dstIn, dstOut);
111+
112+ if (dstRaster != dstOut && dstOut.getParent() != dstRaster) {
113+ if (dstRaster instanceof WritableRaster && atile == null) {
114+ ((WritableRaster) dstRaster).setDataElements(x, y, dstOut);
115+ } else {
116+ ColorModel cm = sg.getDeviceColorModel();
117+ BufferedImage resImg =
118+ new BufferedImage(cm, dstOut,
119+ cm.isAlphaPremultiplied(),
120+ null);
121+ SurfaceData resData = BufImgSurfaceData.createData(resImg);
122+ if (atile == null) {
123+ Blit blit = Blit.getFromCache(resData.getSurfaceType(),
124+ CompositeType.SrcNoEa,
125+ sd.getSurfaceType());
126+ blit.Blit(resData, sd, AlphaComposite.Src, null,
127+ 0, 0, x, y, w, h);
128+ } else {
129+ MaskBlit blit = MaskBlit.getFromCache(resData.getSurfaceType(),
130+ CompositeType.SrcNoEa,
131+ sd.getSurfaceType());
132+ blit.MaskBlit(resData, sd, AlphaComposite.Src, null,
133+ 0, 0, x, y, w, h,
134+ atile, offset, tilesize);
135+ }
136+ }
137+ }
138+ }
139+
140+ public void skipTile(Object ctx, int x, int y) {
141+ return;
142+ }
143+
144+ public void endSequence(Object ctx) {
145+ TileContext context = (TileContext) ctx;
146+ if (context.paintCtxt != null) {
147+ context.paintCtxt.dispose();
148+ }
149+ if (context.compCtxt != null) {
150+ context.compCtxt.dispose();
151+ }
152+ }
153+
154+}
java/pkg/sun/java2d/pipe/GlyphListLoopPipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/GlyphListLoopPipe.java+60−0
@@ -0,0 +1,60 @@
1+/*
2+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.font.GlyphVector;
29+import sun.awt.SunHints;
30+import sun.java2d.SunGraphics2D;
31+import sun.font.GlyphList;
32+
33+/**
34+ * A delegate pipe of SG2D which implements redispatching of
35+ * for the src mode loops in the drawGlyphVector case where
36+ * the installed loop may not match the glyphvector.
37+ */
38+
39+public abstract class GlyphListLoopPipe extends GlyphListPipe
40+ implements LoopBasedPipe
41+{
42+ protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl,
43+ int aaHint) {
44+ switch (aaHint) {
45+ case SunHints.INTVAL_TEXT_ANTIALIAS_OFF:
46+ sg2d.loops.drawGlyphListLoop.
47+ DrawGlyphList(sg2d, sg2d.surfaceData, gl);
48+ return;
49+ case SunHints.INTVAL_TEXT_ANTIALIAS_ON:
50+ sg2d.loops.drawGlyphListAALoop.
51+ DrawGlyphListAA(sg2d, sg2d.surfaceData, gl);
52+ return;
53+ case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB:
54+ case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB:
55+ sg2d.loops.drawGlyphListLCDLoop.
56+ DrawGlyphListLCD(sg2d,sg2d.surfaceData, gl);
57+ return;
58+ }
59+ }
60+}
java/pkg/sun/java2d/pipe/GlyphListPipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/GlyphListPipe.java+147−0
@@ -0,0 +1,147 @@
1+/*
2+ * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Font;
29+import java.awt.Rectangle;
30+import java.awt.Shape;
31+import java.awt.font.FontRenderContext;
32+import java.awt.font.GlyphVector;
33+import java.awt.font.TextLayout;
34+
35+import sun.awt.SunHints;
36+import sun.java2d.SunGraphics2D;
37+import sun.java2d.SurfaceData;
38+import sun.font.GlyphList;
39+import sun.java2d.loops.FontInfo;
40+
41+/**
42+ * A delegate pipe of SG2D for drawing text.
43+ */
44+
45+public abstract class GlyphListPipe implements TextPipe {
46+
47+ public void drawString(SunGraphics2D sg2d, String s,
48+ double x, double y)
49+ {
50+ FontInfo info = sg2d.getFontInfo();
51+ if (info.pixelHeight > OutlineTextRenderer.THRESHHOLD) {
52+ SurfaceData.outlineTextRenderer.drawString(sg2d, s, x, y);
53+ return;
54+ }
55+
56+ float devx, devy;
57+ if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) {
58+ double origin[] = {x + info.originX, y + info.originY};
59+ sg2d.transform.transform(origin, 0, origin, 0, 1);
60+ devx = (float)origin[0];
61+ devy = (float)origin[1];
62+ } else {
63+ devx = (float)(x + info.originX + sg2d.transX);
64+ devy = (float)(y + info.originY + sg2d.transY);
65+ }
66+ /* setFromString returns false if shaping is needed, and we then back
67+ * off to a TextLayout. Such text may benefit slightly from a lower
68+ * overhead in this approach over the approach in previous releases.
69+ */
70+ GlyphList gl = GlyphList.getInstance();
71+ if (gl.setFromString(info, s, devx, devy)) {
72+ drawGlyphList(sg2d, gl);
73+ gl.dispose();
74+ } else {
75+ gl.dispose(); // release this asap.
76+ TextLayout tl = new TextLayout(s, sg2d.getFont(),
77+ sg2d.getFontRenderContext());
78+ tl.draw(sg2d, (float)x, (float)y);
79+ }
80+ }
81+
82+ public void drawChars(SunGraphics2D sg2d,
83+ char data[], int offset, int length,
84+ int ix, int iy)
85+ {
86+ FontInfo info = sg2d.getFontInfo();
87+ float x, y;
88+ if (info.pixelHeight > OutlineTextRenderer.THRESHHOLD) {
89+ SurfaceData.outlineTextRenderer.drawChars(
90+ sg2d, data, offset, length, ix, iy);
91+ return;
92+ }
93+ if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) {
94+ double origin[] = {ix + info.originX, iy + info.originY};
95+ sg2d.transform.transform(origin, 0, origin, 0, 1);
96+ x = (float) origin[0];
97+ y = (float) origin[1];
98+ } else {
99+ x = ix + info.originX + sg2d.transX;
100+ y = iy + info.originY + sg2d.transY;
101+ }
102+ GlyphList gl = GlyphList.getInstance();
103+ if (gl.setFromChars(info, data, offset, length, x, y)) {
104+ drawGlyphList(sg2d, gl);
105+ gl.dispose();
106+ } else {
107+ gl.dispose(); // release this asap.
108+ TextLayout tl = new TextLayout(new String(data, offset, length),
109+ sg2d.getFont(),
110+ sg2d.getFontRenderContext());
111+ tl.draw(sg2d, ix, iy);
112+
113+ }
114+ }
115+
116+ public void drawGlyphVector(SunGraphics2D sg2d, GlyphVector gv,
117+ float x, float y)
118+ {
119+ FontRenderContext frc = gv.getFontRenderContext();
120+ FontInfo info = sg2d.getGVFontInfo(gv.getFont(), frc);
121+ if (info.pixelHeight > OutlineTextRenderer.THRESHHOLD) {
122+ SurfaceData.outlineTextRenderer.drawGlyphVector(sg2d, gv, x, y);
123+ return;
124+ }
125+ if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) {
126+ double origin[] = {x, y};
127+ sg2d.transform.transform(origin, 0, origin, 0, 1);
128+ x = (float) origin[0];
129+ y = (float) origin[1];
130+ } else {
131+ x += sg2d.transX; // don't use the glyph info origin, already in gv.
132+ y += sg2d.transY;
133+ }
134+
135+ GlyphList gl = GlyphList.getInstance();
136+ gl.setFromGlyphVector(info, gv, x, y);
137+ drawGlyphList(sg2d, gl, info.aaHint);
138+ gl.dispose();
139+ }
140+
141+ protected abstract void drawGlyphList(SunGraphics2D sg2d, GlyphList gl);
142+
143+ protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl,
144+ int aaHint) {
145+ drawGlyphList(sg2d, gl);
146+ }
147+}
java/pkg/sun/java2d/pipe/LCDTextRenderer.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/LCDTextRenderer.java+44−0
@@ -0,0 +1,44 @@
1+/*
2+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.font.GlyphVector;
29+import sun.java2d.SunGraphics2D;
30+import sun.font.GlyphList;
31+import static sun.awt.SunHints.*;
32+
33+/**
34+ * A delegate pipe of SG2D for drawing LCD text with
35+ * a solid source colour to an opaque destination.
36+ */
37+
38+public class LCDTextRenderer extends GlyphListLoopPipe {
39+
40+ protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
41+ sg2d.loops.drawGlyphListLCDLoop.
42+ DrawGlyphListLCD(sg2d, sg2d.surfaceData, gl);
43+ }
44+}
java/pkg/sun/java2d/pipe/LoopBasedPipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/LoopBasedPipe.java+37−0
@@ -0,0 +1,37 @@
1+/*
2+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+/**
29+ * This is a marker interface used by Pipes that need RenderLoops.
30+ * RenderLoops are validated in SurfaceData when a pipe is recognised to
31+ * implement this interface.
32+ *
33+ * @author Mario Torre <neugens@aicas.com>
34+ */
35+public interface LoopBasedPipe {
36+
37+}
java/pkg/sun/java2d/pipe/LoopPipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/LoopPipe.java+378−0
@@ -0,0 +1,378 @@
1+/*
2+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Font;
29+import java.awt.Shape;
30+import java.awt.BasicStroke;
31+import java.awt.Polygon;
32+import java.awt.geom.AffineTransform;
33+import java.awt.geom.PathIterator;
34+import java.awt.geom.RoundRectangle2D;
35+import java.awt.geom.Ellipse2D;
36+import java.awt.geom.Arc2D;
37+import java.awt.geom.IllegalPathStateException;
38+import java.awt.geom.Path2D;
39+import java.awt.font.GlyphVector;
40+import sun.java2d.SunGraphics2D;
41+import sun.java2d.SurfaceData;
42+import sun.java2d.loops.FontInfo;
43+import sun.java2d.loops.DrawPolygons;
44+import sun.java2d.loops.FillParallelogram;
45+import sun.java2d.loops.DrawParallelogram;
46+import sun.awt.SunHints;
47+
48+public class LoopPipe
49+ implements PixelDrawPipe,
50+ PixelFillPipe,
51+ ParallelogramPipe,
52+ ShapeDrawPipe,
53+ LoopBasedPipe
54+{
55+ final static RenderingEngine RenderEngine = RenderingEngine.getInstance();
56+
57+ public void drawLine(SunGraphics2D sg2d,
58+ int x1, int y1, int x2, int y2)
59+ {
60+ int tX = sg2d.transX;
61+ int tY = sg2d.transY;
62+ sg2d.loops.drawLineLoop.DrawLine(sg2d, sg2d.getSurfaceData(),
63+ x1 + tX, y1 + tY,
64+ x2 + tX, y2 + tY);
65+ }
66+
67+ public void drawRect(SunGraphics2D sg2d,
68+ int x, int y, int width, int height)
69+ {
70+ sg2d.loops.drawRectLoop.DrawRect(sg2d, sg2d.getSurfaceData(),
71+ x + sg2d.transX,
72+ y + sg2d.transY,
73+ width, height);
74+ }
75+
76+ public void drawRoundRect(SunGraphics2D sg2d,
77+ int x, int y, int width, int height,
78+ int arcWidth, int arcHeight)
79+ {
80+ sg2d.shapepipe.draw(sg2d,
81+ new RoundRectangle2D.Float(x, y, width, height,
82+ arcWidth, arcHeight));
83+ }
84+
85+ public void drawOval(SunGraphics2D sg2d,
86+ int x, int y, int width, int height)
87+ {
88+ sg2d.shapepipe.draw(sg2d, new Ellipse2D.Float(x, y, width, height));
89+ }
90+
91+ public void drawArc(SunGraphics2D sg2d,
92+ int x, int y, int width, int height,
93+ int startAngle, int arcAngle)
94+ {
95+ sg2d.shapepipe.draw(sg2d, new Arc2D.Float(x, y, width, height,
96+ startAngle, arcAngle,
97+ Arc2D.OPEN));
98+ }
99+
100+ public void drawPolyline(SunGraphics2D sg2d,
101+ int xPoints[], int yPoints[],
102+ int nPoints)
103+ {
104+ int nPointsArray[] = { nPoints };
105+ sg2d.loops.drawPolygonsLoop.DrawPolygons(sg2d, sg2d.getSurfaceData(),
106+ xPoints, yPoints,
107+ nPointsArray, 1,
108+ sg2d.transX, sg2d.transY,
109+ false);
110+ }
111+
112+ public void drawPolygon(SunGraphics2D sg2d,
113+ int xPoints[], int yPoints[],
114+ int nPoints)
115+ {
116+ int nPointsArray[] = { nPoints };
117+ sg2d.loops.drawPolygonsLoop.DrawPolygons(sg2d, sg2d.getSurfaceData(),
118+ xPoints, yPoints,
119+ nPointsArray, 1,
120+ sg2d.transX, sg2d.transY,
121+ true);
122+ }
123+
124+ public void fillRect(SunGraphics2D sg2d,
125+ int x, int y, int width, int height)
126+ {
127+ sg2d.loops.fillRectLoop.FillRect(sg2d, sg2d.getSurfaceData(),
128+ x + sg2d.transX,
129+ y + sg2d.transY,
130+ width, height);
131+ }
132+
133+ public void fillRoundRect(SunGraphics2D sg2d,
134+ int x, int y, int width, int height,
135+ int arcWidth, int arcHeight)
136+ {
137+ sg2d.shapepipe.fill(sg2d,
138+ new RoundRectangle2D.Float(x, y, width, height,
139+ arcWidth, arcHeight));
140+ }
141+
142+ public void fillOval(SunGraphics2D sg2d,
143+ int x, int y, int width, int height)
144+ {
145+ sg2d.shapepipe.fill(sg2d, new Ellipse2D.Float(x, y, width, height));
146+ }
147+
148+ public void fillArc(SunGraphics2D sg2d,
149+ int x, int y, int width, int height,
150+ int startAngle, int arcAngle)
151+ {
152+ sg2d.shapepipe.fill(sg2d, new Arc2D.Float(x, y, width, height,
153+ startAngle, arcAngle,
154+ Arc2D.PIE));
155+ }
156+
157+ public void fillPolygon(SunGraphics2D sg2d,
158+ int xPoints[], int yPoints[],
159+ int nPoints)
160+ {
161+ ShapeSpanIterator sr = getFillSSI(sg2d);
162+
163+ try {
164+ sr.setOutputArea(sg2d.getCompClip());
165+ sr.appendPoly(xPoints, yPoints, nPoints, sg2d.transX, sg2d.transY);
166+ fillSpans(sg2d, sr);
167+ } finally {
168+ sr.dispose();
169+ }
170+ }
171+
172+
173+ public void draw(SunGraphics2D sg2d, Shape s) {
174+ if (sg2d.strokeState == sg2d.STROKE_THIN) {
175+ Path2D.Float p2df;
176+ int transX;
177+ int transY;
178+ if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) {
179+ if (s instanceof Path2D.Float) {
180+ p2df = (Path2D.Float)s;
181+ } else {
182+ p2df = new Path2D.Float(s);
183+ }
184+ transX = sg2d.transX;
185+ transY = sg2d.transY;
186+ } else {
187+ p2df = new Path2D.Float(s, sg2d.transform);
188+ transX = 0;
189+ transY = 0;
190+ }
191+ sg2d.loops.drawPathLoop.DrawPath(sg2d, sg2d.getSurfaceData(),
192+ transX, transY, p2df);
193+ return;
194+ }
195+
196+ if (sg2d.strokeState == sg2d.STROKE_CUSTOM) {
197+ fill(sg2d, sg2d.stroke.createStrokedShape(s));
198+ return;
199+ }
200+
201+ ShapeSpanIterator sr = getStrokeSpans(sg2d, s);
202+
203+ try {
204+ fillSpans(sg2d, sr);
205+ } finally {
206+ sr.dispose();
207+ }
208+ }
209+
210+ /**
211+ * Return a ShapeSpanIterator instance that normalizes as
212+ * appropriate for a fill operation as per the settings in
213+ * the specified SunGraphics2D object.
214+ *
215+ * The ShapeSpanIterator will be newly constructed and ready
216+ * to start taking in geometry.
217+ *
218+ * Note that the caller is responsible for calling dispose()
219+ * on the returned ShapeSpanIterator inside a try/finally block:
220+ * <pre>
221+ * ShapeSpanIterator ssi = LoopPipe.getFillSSI(sg2d);
222+ * try {
223+ * ssi.setOutputArea(clip);
224+ * ssi.appendPath(...); // or appendPoly
225+ * // iterate the spans from ssi and operate on them
226+ * } finally {
227+ * ssi.dispose();
228+ * }
229+ * </pre>
230+ */
231+ public static ShapeSpanIterator getFillSSI(SunGraphics2D sg2d) {
232+ boolean adjust = ((sg2d.stroke instanceof BasicStroke) &&
233+ sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE);
234+ return new ShapeSpanIterator(adjust);
235+ }
236+
237+ /*
238+ * Return a ShapeSpanIterator ready to iterate the spans of the wide
239+ * outline of Shape s using the attributes of the SunGraphics2D
240+ * object.
241+ *
242+ * The ShapeSpanIterator returned will be fully constructed
243+ * and filled with the geometry from the Shape widened by the
244+ * appropriate BasicStroke and normalization parameters taken
245+ * from the SunGraphics2D object and be ready to start returning
246+ * spans.
247+ *
248+ * Note that the caller is responsible for calling dispose()
249+ * on the returned ShapeSpanIterator inside a try/finally block.
250+ * <pre>
251+ * ShapeSpanIterator ssi = LoopPipe.getStrokeSpans(sg2d, s);
252+ * try {
253+ * // iterate the spans from ssi and operate on them
254+ * } finally {
255+ * ssi.dispose();
256+ * }
257+ * </pre>
258+ *
259+ * REMIND: This should return a SpanIterator interface object
260+ * but the caller needs to dispose() the object and that method
261+ * is only on ShapeSpanIterator.
262+ * TODO: Add a dispose() method to the SpanIterator interface.
263+ */
264+ public static ShapeSpanIterator getStrokeSpans(SunGraphics2D sg2d,
265+ Shape s)
266+ {
267+ ShapeSpanIterator sr = new ShapeSpanIterator(false);
268+
269+ try {
270+ sr.setOutputArea(sg2d.getCompClip());
271+ sr.setRule(PathIterator.WIND_NON_ZERO);
272+
273+ BasicStroke bs = (BasicStroke) sg2d.stroke;
274+ boolean thin = (sg2d.strokeState <= sg2d.STROKE_THINDASHED);
275+ boolean normalize =
276+ (sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE);
277+
278+ RenderEngine.strokeTo(s,
279+ sg2d.transform, bs,
280+ thin, normalize, false, sr);
281+ } catch (Throwable t) {
282+ sr.dispose();
283+ sr = null;
284+ t.printStackTrace();
285+ throw new InternalError("Unable to Stroke shape ("+
286+ t.getMessage()+")");
287+ }
288+ return sr;
289+ }
290+
291+ public void fill(SunGraphics2D sg2d, Shape s) {
292+ if (sg2d.strokeState == sg2d.STROKE_THIN) {
293+ Path2D.Float p2df;
294+ int transX;
295+ int transY;
296+ if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) {
297+ if (s instanceof Path2D.Float) {
298+ p2df = (Path2D.Float)s;
299+ } else {
300+ p2df = new Path2D.Float(s);
301+ }
302+ transX = sg2d.transX;
303+ transY = sg2d.transY;
304+ } else {
305+ p2df = new Path2D.Float(s, sg2d.transform);
306+ transX = 0;
307+ transY = 0;
308+ }
309+ sg2d.loops.fillPathLoop.FillPath(sg2d, sg2d.getSurfaceData(),
310+ transX, transY, p2df);
311+ return;
312+ }
313+
314+ ShapeSpanIterator sr = getFillSSI(sg2d);
315+ try {
316+ sr.setOutputArea(sg2d.getCompClip());
317+ AffineTransform at =
318+ ((sg2d.transformState == sg2d.TRANSFORM_ISIDENT)
319+ ? null
320+ : sg2d.transform);
321+ sr.appendPath(s.getPathIterator(at));
322+ fillSpans(sg2d, sr);
323+ } finally {
324+ sr.dispose();
325+ }
326+ }
327+
328+ private static void fillSpans(SunGraphics2D sg2d, SpanIterator si) {
329+ // REMIND: Eventually, the plan is that it will not be possible for
330+ // fs to be null since the FillSpans loop will be the fundamental
331+ // loop implemented for any destination type...
332+ if (sg2d.clipState == sg2d.CLIP_SHAPE) {
333+ si = sg2d.clipRegion.filter(si);
334+ // REMIND: Region.filter produces a Java-only iterator
335+ // with no native counterpart...
336+ } else {
337+ sun.java2d.loops.FillSpans fs = sg2d.loops.fillSpansLoop;
338+ if (fs != null) {
339+ fs.FillSpans(sg2d, sg2d.getSurfaceData(), si);
340+ return;
341+ }
342+ }
343+ int spanbox[] = new int[4];
344+ SurfaceData sd = sg2d.getSurfaceData();
345+ while (si.nextSpan(spanbox)) {
346+ int x = spanbox[0];
347+ int y = spanbox[1];
348+ int w = spanbox[2] - x;
349+ int h = spanbox[3] - y;
350+ sg2d.loops.fillRectLoop.FillRect(sg2d, sd, x, y, w, h);
351+ }
352+ }
353+
354+ public void fillParallelogram(SunGraphics2D sg2d,
355+ double ux1, double uy1,
356+ double ux2, double uy2,
357+ double x, double y,
358+ double dx1, double dy1,
359+ double dx2, double dy2)
360+ {
361+ FillParallelogram fp = sg2d.loops.fillParallelogramLoop;
362+ fp.FillParallelogram(sg2d, sg2d.getSurfaceData(),
363+ x, y, dx1, dy1, dx2, dy2);
364+ }
365+
366+ public void drawParallelogram(SunGraphics2D sg2d,
367+ double ux1, double uy1,
368+ double ux2, double uy2,
369+ double x, double y,
370+ double dx1, double dy1,
371+ double dx2, double dy2,
372+ double lw1, double lw2)
373+ {
374+ DrawParallelogram dp = sg2d.loops.drawParallelogramLoop;
375+ dp.DrawParallelogram(sg2d, sg2d.getSurfaceData(),
376+ x, y, dx1, dy1, dx2, dy2, lw1, lw2);
377+ }
378+}
java/pkg/sun/java2d/pipe/NullPipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/NullPipe.java+155−0
@@ -0,0 +1,155 @@
1+/*
2+ * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Color;
29+import java.awt.Image;
30+import java.awt.Shape;
31+import java.awt.geom.AffineTransform;
32+import java.awt.image.BufferedImage;
33+import java.awt.image.BufferedImageOp;
34+import java.awt.image.ImageObserver;
35+import java.awt.font.GlyphVector;
36+import sun.java2d.SunGraphics2D;
37+
38+/**
39+ * This is a class that implements all of the basic pixel rendering
40+ * methods as NOPs.
41+ * This class is useful for installing as the pipeline when the
42+ * clip is determined to be empty or when the composite operation is
43+ * determined to have no effect (i.e. rule == SRC_OVER, extraAlpha == 0.0).
44+ */
45+public class NullPipe
46+ implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe, TextPipe,
47+ DrawImagePipe
48+{
49+ public void drawLine(SunGraphics2D sg,
50+ int x1, int y1, int x2, int y2) {
51+ }
52+
53+ public void drawRect(SunGraphics2D sg,
54+ int x, int y, int width, int height) {
55+ }
56+
57+ public void fillRect(SunGraphics2D sg,
58+ int x, int y, int width, int height) {
59+ }
60+
61+ public void drawRoundRect(SunGraphics2D sg,
62+ int x, int y, int width, int height,
63+ int arcWidth, int arcHeight) {
64+ }
65+
66+ public void fillRoundRect(SunGraphics2D sg,
67+ int x, int y, int width, int height,
68+ int arcWidth, int arcHeight) {
69+ }
70+
71+ public void drawOval(SunGraphics2D sg,
72+ int x, int y, int width, int height) {
73+ }
74+
75+ public void fillOval(SunGraphics2D sg,
76+ int x, int y, int width, int height) {
77+ }
78+
79+ public void drawArc(SunGraphics2D sg,
80+ int x, int y, int width, int height,
81+ int startAngle, int arcAngle) {
82+ }
83+
84+ public void fillArc(SunGraphics2D sg,
85+ int x, int y, int width, int height,
86+ int startAngle, int arcAngle) {
87+ }
88+
89+ public void drawPolyline(SunGraphics2D sg,
90+ int xPoints[], int yPoints[],
91+ int nPoints) {
92+ }
93+
94+ public void drawPolygon(SunGraphics2D sg,
95+ int xPoints[], int yPoints[],
96+ int nPoints) {
97+ }
98+
99+ public void fillPolygon(SunGraphics2D sg,
100+ int xPoints[], int yPoints[],
101+ int nPoints) {
102+ }
103+
104+ public void draw(SunGraphics2D sg, Shape s) {
105+ }
106+
107+ public void fill(SunGraphics2D sg, Shape s) {
108+ }
109+
110+ public void drawString(SunGraphics2D sg, String s, double x, double y) {
111+ }
112+
113+ public void drawGlyphVector(SunGraphics2D sg, GlyphVector g,
114+ float x, float y) {
115+ }
116+
117+ public void drawChars(SunGraphics2D sg,
118+ char data[], int offset, int length,
119+ int x, int y) {
120+ }
121+
122+ public boolean copyImage(SunGraphics2D sg, Image img,
123+ int x, int y,
124+ Color bgColor,
125+ ImageObserver observer) {
126+ return false;
127+ }
128+ public boolean copyImage(SunGraphics2D sg, Image img,
129+ int dx, int dy, int sx, int sy, int w, int h,
130+ Color bgColor,
131+ ImageObserver observer) {
132+ return false;
133+ }
134+ public boolean scaleImage(SunGraphics2D sg, Image img, int x, int y,
135+ int w, int h,
136+ Color bgColor,
137+ ImageObserver observer) {
138+ return false;
139+ }
140+ public boolean scaleImage(SunGraphics2D sg, Image img,
141+ int dx1, int dy1, int dx2, int dy2,
142+ int sx1, int sy1, int sx2, int sy2,
143+ Color bgColor,
144+ ImageObserver observer) {
145+ return false;
146+ }
147+ public boolean transformImage(SunGraphics2D sg, Image img,
148+ AffineTransform atfm,
149+ ImageObserver observer) {
150+ return false;
151+ }
152+ public void transformImage(SunGraphics2D sg, BufferedImage img,
153+ BufferedImageOp op, int x, int y) {
154+ }
155+}
java/pkg/sun/java2d/pipe/OutlineTextRenderer.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/OutlineTextRenderer.java+145−0
@@ -0,0 +1,145 @@
1+/*
2+ * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.font.FontRenderContext;
29+import java.awt.font.GlyphVector;
30+import java.awt.font.TextLayout;
31+import sun.java2d.SunGraphics2D;
32+import sun.font.GlyphList;
33+import sun.awt.SunHints;
34+
35+import java.awt.Shape;
36+import java.awt.geom.AffineTransform;
37+import java.awt.font.TextLayout;
38+
39+/**
40+ * A delegate pipe of SG2D for drawing "large" text with
41+ * a solid source colour to an opaque destination.
42+ * The text is drawn as a filled outline.
43+ * Since the developer is not explicitly requesting this way of
44+ * rendering, this should not be used if the current paint is not
45+ * a solid colour.
46+ *
47+ * If text anti-aliasing is requested by the application, and
48+ * filling path, an anti-aliasing fill pipe needs to
49+ * be invoked.
50+ * This involves making some of the same decisions as in the
51+ * validatePipe call, which may be in a SurfaceData subclass, so
52+ * its awkward to always ensure that the correct pipe is used.
53+ * The easiest thing, rather than reproducing much of that logic
54+ * is to call validatePipe() which works but is expensive, although
55+ * probably not compared to the cost of filling the path.
56+ * Note if AA hint is ON but text-AA hint is OFF this logic will
57+ * produce AA text which perhaps isn't what the user expected.
58+ * Note that the glyphvector obeys its FRC, not the G2D.
59+ */
60+
61+public class OutlineTextRenderer implements TextPipe {
62+
63+ // Text with a height greater than the threshhold will be
64+ // drawn via this pipe.
65+ public static final int THRESHHOLD = 100;
66+
67+ public void drawChars(SunGraphics2D g2d,
68+ char data[], int offset, int length,
69+ int x, int y) {
70+
71+ String s = new String(data, offset, length);
72+ drawString(g2d, s, x, y);
73+ }
74+
75+ public void drawString(SunGraphics2D g2d, String str, double x, double y) {
76+
77+ if ("".equals(str)) {
78+ return; // TextLayout constructor throws IAE on "".
79+ }
80+ TextLayout tl = new TextLayout(str, g2d.getFont(),
81+ g2d.getFontRenderContext());
82+ Shape s = tl.getOutline(AffineTransform.getTranslateInstance(x, y));
83+
84+ int textAAHint = g2d.getFontInfo().aaHint;
85+
86+ int prevaaHint = - 1;
87+ if (textAAHint != SunHints.INTVAL_TEXT_ANTIALIAS_OFF &&
88+ g2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) {
89+ prevaaHint = g2d.antialiasHint;
90+ g2d.antialiasHint = SunHints.INTVAL_ANTIALIAS_ON;
91+ g2d.validatePipe();
92+ } else if (textAAHint == SunHints.INTVAL_TEXT_ANTIALIAS_OFF
93+ && g2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_OFF) {
94+ prevaaHint = g2d.antialiasHint;
95+ g2d.antialiasHint = SunHints.INTVAL_ANTIALIAS_OFF;
96+ g2d.validatePipe();
97+ }
98+
99+ g2d.fill(s);
100+
101+ if (prevaaHint != -1) {
102+ g2d.antialiasHint = prevaaHint;
103+ g2d.validatePipe();
104+ }
105+ }
106+
107+ public void drawGlyphVector(SunGraphics2D g2d, GlyphVector gv,
108+ float x, float y) {
109+
110+
111+ Shape s = gv.getOutline(x, y);
112+ int prevaaHint = - 1;
113+ FontRenderContext frc = gv.getFontRenderContext();
114+ boolean aa = frc.isAntiAliased();
115+
116+ /* aa will be true if any AA mode has been specified.
117+ * ie for LCD and 'gasp' modes too.
118+ * We will check if 'gasp' has resolved AA to be "OFF", and
119+ * in all other cases (ie AA ON and all LCD modes) use AA outlines.
120+ */
121+ if (aa) {
122+ if (g2d.getGVFontInfo(gv.getFont(), frc).aaHint ==
123+ SunHints.INTVAL_TEXT_ANTIALIAS_OFF) {
124+ aa = false;
125+ }
126+ }
127+
128+ if (aa && g2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) {
129+ prevaaHint = g2d.antialiasHint;
130+ g2d.antialiasHint = SunHints.INTVAL_ANTIALIAS_ON;
131+ g2d.validatePipe();
132+ } else if (!aa && g2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_OFF) {
133+ prevaaHint = g2d.antialiasHint;
134+ g2d.antialiasHint = SunHints.INTVAL_ANTIALIAS_OFF;
135+ g2d.validatePipe();
136+ }
137+
138+ g2d.fill(s);
139+
140+ if (prevaaHint != -1) {
141+ g2d.antialiasHint = prevaaHint;
142+ g2d.validatePipe();
143+ }
144+ }
145+}
java/pkg/sun/java2d/pipe/ParallelogramPipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/ParallelogramPipe.java+76−0
@@ -0,0 +1,76 @@
1+/*
2+ * Copyright (c) 2008, 2011 Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import sun.java2d.SunGraphics2D;
29+
30+/**
31+ * This interface defines the set of calls that pipeline objects
32+ * can use to pass on responsibility for drawing arbitrary
33+ * parallelogram shapes.
34+ * Six floating point numbers are provided and the parallelogram
35+ * is defined as the quadrilateral with the following vertices:
36+ * <pre>
37+ * origin: (x, y)
38+ * => (x+dx1, y+dy1)
39+ * => (x+dx1+dx2, y+dy1+dy2)
40+ * => (x+dx2, y+dy2)
41+ * => origin
42+ * </pre>
43+ * The four u[xy][12] parameters are the unsorted extreme coordinates
44+ * of the primitive in user space. They may have been generated by a
45+ * line or a rectangle so they could have u[xy]2 < u[xy]1 in some cases.
46+ * They should be sorted before calculating the bounds of the original
47+ * primitive (such as for calculating the user space bounds for the
48+ * Paint.createContext() method).
49+ */
50+public interface ParallelogramPipe {
51+ public void fillParallelogram(SunGraphics2D sg,
52+ double ux1, double uy1,
53+ double ux2, double uy2,
54+ double x, double y,
55+ double dx1, double dy1,
56+ double dx2, double dy2);
57+
58+ /**
59+ * Draw a Parallelogram with the indicated line widths
60+ * assuming a standard BasicStroke with MITER joins.
61+ * lw1 specifies the width of the stroke along the dx1,dy1
62+ * vector and lw2 specifies the width of the stroke along
63+ * the dx2,dy2 vector.
64+ * This is equivalent to outsetting the indicated
65+ * parallelogram by lw/2 pixels, then insetting the
66+ * same parallelogram by lw/2 pixels and filling the
67+ * difference between the outer and inner parallelograms.
68+ */
69+ public void drawParallelogram(SunGraphics2D sg,
70+ double ux1, double uy1,
71+ double ux2, double uy2,
72+ double x, double y,
73+ double dx1, double dy1,
74+ double dx2, double dy2,
75+ double lw1, double lw2);
76+}
java/pkg/sun/java2d/pipe/PixelDrawPipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/PixelDrawPipe.java+67−0
@@ -0,0 +1,67 @@
1+/*
2+ * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import sun.java2d.SunGraphics2D;
29+
30+/**
31+ * This interface defines the set of calls that pipeline objects
32+ * can use to pass on responsibility for drawing various basic
33+ * geometric figures defined by explicit integer coordinates.
34+ * Typically this interface will be used for communication when
35+ * the coordinates of the rendering have been narrowed down to
36+ * actual device pixels, or for communication of untransformed
37+ * coordinates when the coordinates were specified using integers.
38+ * This interface does not cover all of the rendering calls that
39+ * are possible in Graphics since many of the rendering calls can
40+ * be transformed into one or more variants of these calls.
41+ */
42+public interface PixelDrawPipe {
43+ public void drawLine(SunGraphics2D sg,
44+ int x1, int y1, int x2, int y2);
45+
46+ public void drawRect(SunGraphics2D sg,
47+ int x, int y, int width, int height);
48+
49+ public void drawRoundRect(SunGraphics2D sg,
50+ int x, int y, int width, int height,
51+ int arcWidth, int arcHeight);
52+
53+ public void drawOval(SunGraphics2D sg,
54+ int x, int y, int width, int height);
55+
56+ public void drawArc(SunGraphics2D sg,
57+ int x, int y, int width, int height,
58+ int startAngle, int arcAngle);
59+
60+ public void drawPolyline(SunGraphics2D sg,
61+ int xPoints[], int yPoints[],
62+ int nPoints);
63+
64+ public void drawPolygon(SunGraphics2D sg,
65+ int xPoints[], int yPoints[],
66+ int nPoints);
67+}
java/pkg/sun/java2d/pipe/PixelFillPipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/PixelFillPipe.java+61−0
@@ -0,0 +1,61 @@
1+/*
2+ * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import sun.java2d.SunGraphics2D;
29+
30+/**
31+ * This interface defines the set of calls that pipeline objects
32+ * can use to pass on responsibility for filling various basic
33+ * geometric figures defined by explicit integer coordinates.
34+ * Typically this interface will be used for communication when
35+ * the coordinates of the rendering have been narrowed down to
36+ * actual device pixels, or for communication of untransformed
37+ * coordinates when the coordinates were specified using integers.
38+ * This interface does not cover all of the rendering calls that
39+ * are possible in Graphics since many of the rendering calls can
40+ * be transformed into one or more variants of these calls.
41+ */
42+public interface PixelFillPipe {
43+ public void fillRect(SunGraphics2D sg,
44+ int x, int y, int width, int height);
45+
46+
47+ public void fillRoundRect(SunGraphics2D sg,
48+ int x, int y, int width, int height,
49+ int arcWidth, int arcHeight);
50+
51+ public void fillOval(SunGraphics2D sg,
52+ int x, int y, int width, int height);
53+
54+ public void fillArc(SunGraphics2D sg,
55+ int x, int y, int width, int height,
56+ int startAngle, int arcAngle);
57+
58+ public void fillPolygon(SunGraphics2D sg,
59+ int xPoints[], int yPoints[],
60+ int nPoints);
61+}
java/pkg/sun/java2d/pipe/PixelToParallelogramConverter.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/PixelToParallelogramConverter.java+429−0
@@ -0,0 +1,429 @@
1+/*
2+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Shape;
29+import java.awt.BasicStroke;
30+import java.awt.geom.Line2D;
31+import java.awt.geom.Rectangle2D;
32+import java.awt.geom.AffineTransform;
33+import sun.java2d.SunGraphics2D;
34+import sun.awt.SunHints;
35+
36+/**
37+ * This class converts calls to the basic pixel rendering methods
38+ * into calls to the methods on a ParallelogramPipe.
39+ * Most calls are transformed into calls to the fill(Shape) method
40+ * by the parent PixelToShapeConverter class, but some calls are
41+ * transformed into calls to fill/drawParallelogram().
42+ */
43+public class PixelToParallelogramConverter extends PixelToShapeConverter
44+ implements ShapeDrawPipe
45+{
46+ ParallelogramPipe outrenderer;
47+ double minPenSize;
48+ double normPosition;
49+ double normRoundingBias;
50+ boolean adjustfill;
51+
52+ /**
53+ * @param shapepipe pipeline to forward shape calls to
54+ * @param pgrampipe pipeline to forward parallelogram calls to
55+ * (and drawLine calls if possible)
56+ * @param minPenSize minimum pen size for dropout control
57+ * @param normPosition sub-pixel location to normalize endpoints
58+ * for STROKE_NORMALIZE cases
59+ * @param adjustFill boolean to control whethere normalization
60+ * constants are also applied to fill operations
61+ * (normally true for non-AA, false for AA)
62+ */
63+ public PixelToParallelogramConverter(ShapeDrawPipe shapepipe,
64+ ParallelogramPipe pgrampipe,
65+ double minPenSize,
66+ double normPosition,
67+ boolean adjustfill)
68+ {
69+ super(shapepipe);
70+ outrenderer = pgrampipe;
71+ this.minPenSize = minPenSize;
72+ this.normPosition = normPosition;
73+ this.normRoundingBias = 0.5 - normPosition;
74+ this.adjustfill = adjustfill;
75+ }
76+
77+ public void drawLine(SunGraphics2D sg2d,
78+ int x1, int y1, int x2, int y2)
79+ {
80+ if (!drawGeneralLine(sg2d, x1, y1, x2, y2)) {
81+ super.drawLine(sg2d, x1, y1, x2, y2);
82+ }
83+ }
84+
85+ public void drawRect(SunGraphics2D sg2d,
86+ int x, int y, int w, int h)
87+ {
88+ if (w >= 0 && h >= 0) {
89+ if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM) {
90+ BasicStroke bs = ((BasicStroke) sg2d.stroke);
91+ if (w > 0 && h > 0) {
92+ if (bs.getLineJoin() == BasicStroke.JOIN_MITER &&
93+ bs.getDashArray() == null)
94+ {
95+ double lw = bs.getLineWidth();
96+ drawRectangle(sg2d, x, y, w, h, lw);
97+ return;
98+ }
99+ } else {
100+ // Note: This calls the integer version which
101+ // will verify that the local drawLine optimizations
102+ // work and call super.drawLine(), if not.
103+ drawLine(sg2d, x, y, x+w, y+h);
104+ return;
105+ }
106+ }
107+ super.drawRect(sg2d, x, y, w, h);
108+ }
109+ }
110+
111+ public void fillRect(SunGraphics2D sg2d,
112+ int x, int y, int w, int h)
113+ {
114+ if (w > 0 && h > 0) {
115+ fillRectangle(sg2d, x, y, w, h);
116+ }
117+ }
118+
119+ public void draw(SunGraphics2D sg2d, Shape s) {
120+ if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM) {
121+ BasicStroke bs = ((BasicStroke) sg2d.stroke);
122+ if (s instanceof Rectangle2D) {
123+ if (bs.getLineJoin() == BasicStroke.JOIN_MITER &&
124+ bs.getDashArray() == null)
125+ {
126+ Rectangle2D r2d = (Rectangle2D) s;
127+ double w = r2d.getWidth();
128+ double h = r2d.getHeight();
129+ double x = r2d.getX();
130+ double y = r2d.getY();
131+ if (w >= 0 && h >= 0) {
132+ double lw = bs.getLineWidth();
133+ drawRectangle(sg2d, x, y, w, h, lw);
134+ }
135+ return;
136+ }
137+ } else if (s instanceof Line2D) {
138+ Line2D l2d = (Line2D) s;
139+ if (drawGeneralLine(sg2d,
140+ l2d.getX1(), l2d.getY1(),
141+ l2d.getX2(), l2d.getY2()))
142+ {
143+ return;
144+ }
145+ }
146+ }
147+
148+ outpipe.draw(sg2d, s);
149+ }
150+
151+ public void fill(SunGraphics2D sg2d, Shape s) {
152+ if (s instanceof Rectangle2D) {
153+ Rectangle2D r2d = (Rectangle2D) s;
154+ double w = r2d.getWidth();
155+ double h = r2d.getHeight();
156+ if (w > 0 && h > 0) {
157+ double x = r2d.getX();
158+ double y = r2d.getY();
159+ fillRectangle(sg2d, x, y, w, h);
160+ }
161+ return;
162+ }
163+
164+ outpipe.fill(sg2d, s);
165+ }
166+
167+ static double len(double x, double y) {
168+ return ((x == 0) ? Math.abs(y)
169+ : ((y == 0) ? Math.abs(x)
170+ : Math.sqrt(x * x + y * y)));
171+ }
172+
173+ double normalize(double v) {
174+ return Math.floor(v + normRoundingBias) + normPosition;
175+ }
176+
177+ public boolean drawGeneralLine(SunGraphics2D sg2d,
178+ double ux1, double uy1,
179+ double ux2, double uy2)
180+ {
181+ if (sg2d.strokeState == SunGraphics2D.STROKE_CUSTOM ||
182+ sg2d.strokeState == SunGraphics2D.STROKE_THINDASHED)
183+ {
184+ return false;
185+ }
186+ BasicStroke bs = (BasicStroke) sg2d.stroke;
187+ int cap = bs.getEndCap();
188+ if (cap == BasicStroke.CAP_ROUND || bs.getDashArray() != null) {
189+ // TODO: we could construct the GeneralPath directly
190+ // for CAP_ROUND and save a lot of processing in that case...
191+ // And again, we would need to deal with dropout control...
192+ return false;
193+ }
194+ double lw = bs.getLineWidth();
195+ // Save the original dx, dy in case we need it to transform
196+ // the linewidth as a perpendicular vector below
197+ double dx = ux2 - ux1;
198+ double dy = uy2 - uy1;
199+ double x1, y1, x2, y2;
200+ switch (sg2d.transformState) {
201+ case SunGraphics2D.TRANSFORM_GENERIC:
202+ case SunGraphics2D.TRANSFORM_TRANSLATESCALE:
203+ {
204+ double coords[] = {ux1, uy1, ux2, uy2};
205+ sg2d.transform.transform(coords, 0, coords, 0, 2);
206+ x1 = coords[0];
207+ y1 = coords[1];
208+ x2 = coords[2];
209+ y2 = coords[3];
210+ }
211+ break;
212+ case SunGraphics2D.TRANSFORM_ANY_TRANSLATE:
213+ case SunGraphics2D.TRANSFORM_INT_TRANSLATE:
214+ {
215+ double tx = sg2d.transform.getTranslateX();
216+ double ty = sg2d.transform.getTranslateY();
217+ x1 = ux1 + tx;
218+ y1 = uy1 + ty;
219+ x2 = ux2 + tx;
220+ y2 = uy2 + ty;
221+ }
222+ break;
223+ case SunGraphics2D.TRANSFORM_ISIDENT:
224+ x1 = ux1;
225+ y1 = uy1;
226+ x2 = ux2;
227+ y2 = uy2;
228+ break;
229+ default:
230+ throw new InternalError("unknown TRANSFORM state...");
231+ }
232+ if (sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE) {
233+ if (sg2d.strokeState == SunGraphics2D.STROKE_THIN &&
234+ outrenderer instanceof PixelDrawPipe)
235+ {
236+ // PixelDrawPipes will add sg2d.transXY so we need to factor
237+ // that out...
238+ int ix1 = (int) Math.floor(x1 - sg2d.transX);
239+ int iy1 = (int) Math.floor(y1 - sg2d.transY);
240+ int ix2 = (int) Math.floor(x2 - sg2d.transX);
241+ int iy2 = (int) Math.floor(y2 - sg2d.transY);
242+ ((PixelDrawPipe)outrenderer).drawLine(sg2d, ix1, iy1, ix2, iy2);
243+ return true;
244+ }
245+ x1 = normalize(x1);
246+ y1 = normalize(y1);
247+ x2 = normalize(x2);
248+ y2 = normalize(y2);
249+ }
250+ if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
251+ // Transform the linewidth...
252+ // calculate the scaling factor for a unit vector
253+ // perpendicular to the original user space line.
254+ double len = len(dx, dy);
255+ if (len == 0) {
256+ dx = len = 1;
257+ // dy = 0; already
258+ }
259+ // delta transform the transposed (90 degree rotated) unit vector
260+ double unitvector[] = {dy/len, -dx/len};
261+ sg2d.transform.deltaTransform(unitvector, 0, unitvector, 0, 1);
262+ lw *= len(unitvector[0], unitvector[1]);
263+ }
264+ lw = Math.max(lw, minPenSize);
265+ dx = x2 - x1;
266+ dy = y2 - y1;
267+ double len = len(dx, dy);
268+ double udx, udy;
269+ if (len == 0) {
270+ if (cap == BasicStroke.CAP_BUTT) {
271+ return true;
272+ }
273+ udx = lw;
274+ udy = 0;
275+ } else {
276+ udx = lw * dx / len;
277+ udy = lw * dy / len;
278+ }
279+ double px = x1 + udy / 2.0;
280+ double py = y1 - udx / 2.0;
281+ if (cap == BasicStroke.CAP_SQUARE) {
282+ px -= udx / 2.0;
283+ py -= udy / 2.0;
284+ dx += udx;
285+ dy += udy;
286+ }
287+ outrenderer.fillParallelogram(sg2d, ux1, uy1, ux2, uy2,
288+ px, py, -udy, udx, dx, dy);
289+ return true;
290+ }
291+
292+ public void fillRectangle(SunGraphics2D sg2d,
293+ double rx, double ry,
294+ double rw, double rh)
295+ {
296+ double px, py;
297+ double dx1, dy1, dx2, dy2;
298+ AffineTransform txform = sg2d.transform;
299+ dx1 = txform.getScaleX();
300+ dy1 = txform.getShearY();
301+ dx2 = txform.getShearX();
302+ dy2 = txform.getScaleY();
303+ px = rx * dx1 + ry * dx2 + txform.getTranslateX();
304+ py = rx * dy1 + ry * dy2 + txform.getTranslateY();
305+ dx1 *= rw;
306+ dy1 *= rw;
307+ dx2 *= rh;
308+ dy2 *= rh;
309+ if (adjustfill &&
310+ sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM &&
311+ sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE)
312+ {
313+ double newx = normalize(px);
314+ double newy = normalize(py);
315+ dx1 = normalize(px + dx1) - newx;
316+ dy1 = normalize(py + dy1) - newy;
317+ dx2 = normalize(px + dx2) - newx;
318+ dy2 = normalize(py + dy2) - newy;
319+ px = newx;
320+ py = newy;
321+ }
322+ outrenderer.fillParallelogram(sg2d, rx, ry, rx+rw, ry+rh,
323+ px, py, dx1, dy1, dx2, dy2);
324+ }
325+
326+ public void drawRectangle(SunGraphics2D sg2d,
327+ double rx, double ry,
328+ double rw, double rh,
329+ double lw)
330+ {
331+ double px, py;
332+ double dx1, dy1, dx2, dy2;
333+ double lw1, lw2;
334+ AffineTransform txform = sg2d.transform;
335+ dx1 = txform.getScaleX();
336+ dy1 = txform.getShearY();
337+ dx2 = txform.getShearX();
338+ dy2 = txform.getScaleY();
339+ px = rx * dx1 + ry * dx2 + txform.getTranslateX();
340+ py = rx * dy1 + ry * dy2 + txform.getTranslateY();
341+ // lw along dx1,dy1 scale by transformed length of dx2,dy2 vectors
342+ // and vice versa
343+ lw1 = len(dx1, dy1) * lw;
344+ lw2 = len(dx2, dy2) * lw;
345+ dx1 *= rw;
346+ dy1 *= rw;
347+ dx2 *= rh;
348+ dy2 *= rh;
349+ if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM &&
350+ sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE)
351+ {
352+ double newx = normalize(px);
353+ double newy = normalize(py);
354+ dx1 = normalize(px + dx1) - newx;
355+ dy1 = normalize(py + dy1) - newy;
356+ dx2 = normalize(px + dx2) - newx;
357+ dy2 = normalize(py + dy2) - newy;
358+ px = newx;
359+ py = newy;
360+ }
361+ lw1 = Math.max(lw1, minPenSize);
362+ lw2 = Math.max(lw2, minPenSize);
363+ double len1 = len(dx1, dy1);
364+ double len2 = len(dx2, dy2);
365+ if (lw1 >= len1 || lw2 >= len2) {
366+ // The line widths are large enough to consume the
367+ // entire hole in the middle of the parallelogram
368+ // so we can just fill the outer parallelogram.
369+ fillOuterParallelogram(sg2d,
370+ rx, ry, rx+rw, ry+rh,
371+ px, py, dx1, dy1, dx2, dy2,
372+ len1, len2, lw1, lw2);
373+ } else {
374+ outrenderer.drawParallelogram(sg2d,
375+ rx, ry, rx+rw, ry+rh,
376+ px, py, dx1, dy1, dx2, dy2,
377+ lw1 / len1, lw2 / len2);
378+ }
379+ }
380+
381+ /**
382+ * This utility function handles the case where a drawRectangle
383+ * operation discovered that the interior hole in the rectangle
384+ * or parallelogram has been completely filled in by the stroke
385+ * width. It calculates the outer parallelogram of the stroke
386+ * and issues a single fillParallelogram request to fill it.
387+ */
388+ public void fillOuterParallelogram(SunGraphics2D sg2d,
389+ double ux1, double uy1,
390+ double ux2, double uy2,
391+ double px, double py,
392+ double dx1, double dy1,
393+ double dx2, double dy2,
394+ double len1, double len2,
395+ double lw1, double lw2)
396+ {
397+ double udx1 = dx1 / len1;
398+ double udy1 = dy1 / len1;
399+ double udx2 = dx2 / len2;
400+ double udy2 = dy2 / len2;
401+ if (len1 == 0) {
402+ // len1 is 0, replace udxy1 with perpendicular of udxy2
403+ if (len2 == 0) {
404+ // both are 0, use a unit Y vector for udxy2
405+ udx2 = 0;
406+ udy2 = 1;
407+ }
408+ udx1 = udy2;
409+ udy1 = -udx2;
410+ } else if (len2 == 0) {
411+ // len2 is 0, replace udxy2 with perpendicular of udxy1
412+ udx2 = udy1;
413+ udy2 = -udx1;
414+ }
415+ udx1 *= lw1;
416+ udy1 *= lw1;
417+ udx2 *= lw2;
418+ udy2 *= lw2;
419+ px -= (udx1 + udx2) / 2;
420+ py -= (udy1 + udy2) / 2;
421+ dx1 += udx1;
422+ dy1 += udy1;
423+ dx2 += udx2;
424+ dy2 += udy2;
425+
426+ outrenderer.fillParallelogram(sg2d, ux1, uy1, ux2, uy2,
427+ px, py, dx1, dy1, dx2, dy2);
428+ }
429+}
java/pkg/sun/java2d/pipe/PixelToShapeConverter.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/PixelToShapeConverter.java+133−0
@@ -0,0 +1,133 @@
1+/*
2+ * Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Rectangle;
29+import java.awt.Shape;
30+import java.awt.geom.Arc2D;
31+import java.awt.geom.Ellipse2D;
32+import java.awt.geom.Line2D;
33+import java.awt.geom.RoundRectangle2D;
34+import java.awt.geom.GeneralPath;
35+import sun.java2d.SunGraphics2D;
36+
37+/**
38+ * This class converts calls to the basic pixel rendering methods
39+ * into calls to a generic Shape rendering pipeline.
40+ */
41+public class PixelToShapeConverter
42+ implements PixelDrawPipe, PixelFillPipe
43+{
44+ ShapeDrawPipe outpipe;
45+
46+ public PixelToShapeConverter(ShapeDrawPipe pipe) {
47+ outpipe = pipe;
48+ }
49+
50+ public void drawLine(SunGraphics2D sg,
51+ int x1, int y1, int x2, int y2) {
52+ outpipe.draw(sg, new Line2D.Float(x1, y1, x2, y2));
53+ }
54+
55+ public void drawRect(SunGraphics2D sg,
56+ int x, int y, int w, int h) {
57+ outpipe.draw(sg, new Rectangle(x, y, w, h));
58+ }
59+
60+ public void fillRect(SunGraphics2D sg,
61+ int x, int y, int w, int h) {
62+ outpipe.fill(sg, new Rectangle(x, y, w, h));
63+ }
64+
65+ public void drawRoundRect(SunGraphics2D sg,
66+ int x, int y, int w, int h,
67+ int aW, int aH) {
68+ outpipe.draw(sg, new RoundRectangle2D.Float(x, y, w, h, aW, aH));
69+ }
70+
71+ public void fillRoundRect(SunGraphics2D sg,
72+ int x, int y, int w, int h,
73+ int aW, int aH) {
74+ outpipe.fill(sg, new RoundRectangle2D.Float(x, y, w, h, aW, aH));
75+ }
76+
77+ public void drawOval(SunGraphics2D sg,
78+ int x, int y, int w, int h) {
79+ outpipe.draw(sg, new Ellipse2D.Float(x, y, w, h));
80+ }
81+
82+ public void fillOval(SunGraphics2D sg,
83+ int x, int y, int w, int h) {
84+ outpipe.fill(sg, new Ellipse2D.Float(x, y, w, h));
85+ }
86+
87+ public void drawArc(SunGraphics2D sg,
88+ int x, int y, int w, int h,
89+ int start, int extent) {
90+ outpipe.draw(sg, new Arc2D.Float(x, y, w, h,
91+ start, extent, Arc2D.OPEN));
92+ }
93+
94+ public void fillArc(SunGraphics2D sg,
95+ int x, int y, int w, int h,
96+ int start, int extent) {
97+ outpipe.fill(sg, new Arc2D.Float(x, y, w, h,
98+ start, extent, Arc2D.PIE));
99+ }
100+
101+ private Shape makePoly(int xPoints[], int yPoints[],
102+ int nPoints, boolean close) {
103+ GeneralPath gp = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
104+ if (nPoints > 0) {
105+ gp.moveTo(xPoints[0], yPoints[0]);
106+ }
107+ for (int i = 1; i < nPoints; i++) {
108+ gp.lineTo(xPoints[i], yPoints[i]);
109+ }
110+ if (close) {
111+ gp.closePath();
112+ }
113+ return gp;
114+ }
115+
116+ public void drawPolyline(SunGraphics2D sg,
117+ int xPoints[], int yPoints[],
118+ int nPoints) {
119+ outpipe.draw(sg, makePoly(xPoints, yPoints, nPoints, false));
120+ }
121+
122+ public void drawPolygon(SunGraphics2D sg,
123+ int xPoints[], int yPoints[],
124+ int nPoints) {
125+ outpipe.draw(sg, makePoly(xPoints, yPoints, nPoints, true));
126+ }
127+
128+ public void fillPolygon(SunGraphics2D sg,
129+ int xPoints[], int yPoints[],
130+ int nPoints) {
131+ outpipe.fill(sg, makePoly(xPoints, yPoints, nPoints, true));
132+ }
133+}
java/pkg/sun/java2d/pipe/Region$ImmutableRegion.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/Region.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/Region.java+1255−0
@@ -0,0 +1,1255 @@
1+/*
2+ * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Rectangle;
29+import java.awt.Shape;
30+import java.awt.geom.AffineTransform;
31+import java.awt.geom.RectangularShape;
32+
33+/**
34+ * This class encapsulates a definition of a two dimensional region which
35+ * consists of a number of Y ranges each containing multiple X bands.
36+ * <p>
37+ * A rectangular Region is allowed to have a null band list in which
38+ * case the rectangular shape is defined by the bounding box parameters
39+ * (lox, loy, hix, hiy).
40+ * <p>
41+ * The band list, if present, consists of a list of rows in ascending Y
42+ * order, ending at endIndex which is the index beyond the end of the
43+ * last row. Each row consists of at least 3 + 2n entries (n >= 1)
44+ * where the first 3 entries specify the Y range as start, end, and
45+ * the number of X ranges in that Y range. These 3 entries are
46+ * followed by pairs of X coordinates in ascending order:
47+ * <pre>
48+ * bands[rowstart+0] = Y0; // starting Y coordinate
49+ * bands[rowstart+1] = Y1; // ending Y coordinate - endY > startY
50+ * bands[rowstart+2] = N; // number of X bands - N >= 1
51+ *
52+ * bands[rowstart+3] = X10; // starting X coordinate of first band
53+ * bands[rowstart+4] = X11; // ending X coordinate of first band
54+ * bands[rowstart+5] = X20; // starting X coordinate of second band
55+ * bands[rowstart+6] = X21; // ending X coordinate of second band
56+ * ...
57+ * bands[rowstart+3+N*2-2] = XN0; // starting X coord of last band
58+ * bands[rowstart+3+N*2-1] = XN1; // ending X coord of last band
59+ *
60+ * bands[rowstart+3+N*2] = ... // start of next Y row
61+ * </pre>
62+ */
63+public class Region {
64+ static final int INIT_SIZE = 50;
65+ static final int GROW_SIZE = 50;
66+
67+ /**
68+ * Immutable Region.
69+ */
70+ private static final class ImmutableRegion extends Region {
71+ protected ImmutableRegion(int lox, int loy, int hix, int hiy) {
72+ super(lox, loy, hix, hiy);
73+ }
74+
75+ // Override all the methods that mutate the object
76+ public void appendSpans(sun.java2d.pipe.SpanIterator si) {}
77+ public void setOutputArea(java.awt.Rectangle r) {}
78+ public void setOutputAreaXYWH(int x, int y, int w, int h) {}
79+ public void setOutputArea(int[] box) {}
80+ public void setOutputAreaXYXY(int lox, int loy, int hix, int hiy) {}
81+ }
82+
83+ public static final Region EMPTY_REGION = new ImmutableRegion(0, 0, 0, 0);
84+ public static final Region WHOLE_REGION = new ImmutableRegion(
85+ Integer.MIN_VALUE,
86+ Integer.MIN_VALUE,
87+ Integer.MAX_VALUE,
88+ Integer.MAX_VALUE);
89+
90+ int lox;
91+ int loy;
92+ int hix;
93+ int hiy;
94+
95+ int endIndex;
96+ int[] bands;
97+
98+ private static native void initIDs();
99+
100+ static {
101+ initIDs();
102+ }
103+
104+ /**
105+ * Adds the dimension <code>dim</code> to the coordinate
106+ * <code>start</code> with appropriate clipping. If
107+ * <code>dim</code> is non-positive then the method returns
108+ * the start coordinate. If the sum overflows an integer
109+ * data type then the method returns <code>Integer.MAX_VALUE</code>.
110+ */
111+ public static int dimAdd(int start, int dim) {
112+ if (dim <= 0) return start;
113+ if ((dim += start) < start) return Integer.MAX_VALUE;
114+ return dim;
115+ }
116+
117+ /**
118+ * Adds the delta {@code dv} to the value {@code v} with
119+ * appropriate clipping to the bounds of Integer resolution.
120+ * If the answer would be greater than {@code Integer.MAX_VALUE}
121+ * then {@code Integer.MAX_VALUE} is returned.
122+ * If the answer would be less than {@code Integer.MIN_VALUE}
123+ * then {@code Integer.MIN_VALUE} is returned.
124+ * Otherwise the sum is returned.
125+ */
126+ public static int clipAdd(int v, int dv) {
127+ int newv = v + dv;
128+ if ((newv > v) != (dv > 0)) {
129+ newv = (dv < 0) ? Integer.MIN_VALUE : Integer.MAX_VALUE;
130+ }
131+ return newv;
132+ }
133+
134+ protected Region(int lox, int loy, int hix, int hiy) {
135+ this.lox = lox;
136+ this.loy = loy;
137+ this.hix = hix;
138+ this.hiy = hiy;
139+ }
140+
141+ /**
142+ * Returns a Region object covering the pixels which would be
143+ * touched by a fill or clip operation on a Graphics implementation
144+ * on the specified Shape object under the optionally specified
145+ * AffineTransform object.
146+ *
147+ * @param s a non-null Shape object specifying the geometry enclosing
148+ * the pixels of interest
149+ * @param at an optional <code>AffineTransform</code> to be applied to the
150+ * coordinates as they are returned in the iteration, or
151+ * <code>null</code> if untransformed coordinates are desired
152+ */
153+ public static Region getInstance(Shape s, AffineTransform at) {
154+ return getInstance(WHOLE_REGION, false, s, at);
155+ }
156+
157+ /**
158+ * Returns a Region object covering the pixels which would be
159+ * touched by a fill or clip operation on a Graphics implementation
160+ * on the specified Shape object under the optionally specified
161+ * AffineTransform object further restricted by the specified
162+ * device bounds.
163+ * <p>
164+ * Note that only the bounds of the specified Region are used to
165+ * restrict the resulting Region.
166+ * If devBounds is non-rectangular and clipping to the specific
167+ * bands of devBounds is needed, then an intersection of the
168+ * resulting Region with devBounds must be performed in a
169+ * subsequent step.
170+ *
171+ * @param devBounds a non-null Region specifying some bounds to
172+ * clip the geometry to
173+ * @param s a non-null Shape object specifying the geometry enclosing
174+ * the pixels of interest
175+ * @param at an optional <code>AffineTransform</code> to be applied to the
176+ * coordinates as they are returned in the iteration, or
177+ * <code>null</code> if untransformed coordinates are desired
178+ */
179+ public static Region getInstance(Region devBounds,
180+ Shape s, AffineTransform at)
181+ {
182+ return getInstance(devBounds, false, s, at);
183+ }
184+
185+ /**
186+ * Returns a Region object covering the pixels which would be
187+ * touched by a fill or clip operation on a Graphics implementation
188+ * on the specified Shape object under the optionally specified
189+ * AffineTransform object further restricted by the specified
190+ * device bounds.
191+ * If the normalize parameter is true then coordinate normalization
192+ * is performed as per the 2D Graphics non-antialiasing implementation
193+ * of the VALUE_STROKE_NORMALIZE hint.
194+ * <p>
195+ * Note that only the bounds of the specified Region are used to
196+ * restrict the resulting Region.
197+ * If devBounds is non-rectangular and clipping to the specific
198+ * bands of devBounds is needed, then an intersection of the
199+ * resulting Region with devBounds must be performed in a
200+ * subsequent step.
201+ *
202+ * @param devBounds a non-null Region specifying some bounds to
203+ * clip the geometry to
204+ * @param normalize a boolean indicating whether or not to apply
205+ * normalization
206+ * @param s a non-null Shape object specifying the geometry enclosing
207+ * the pixels of interest
208+ * @param at an optional <code>AffineTransform</code> to be applied to the
209+ * coordinates as they are returned in the iteration, or
210+ * <code>null</code> if untransformed coordinates are desired
211+ */
212+ public static Region getInstance(Region devBounds, boolean normalize,
213+ Shape s, AffineTransform at)
214+ {
215+ // Optimize for empty shapes to avoid involving the SpanIterator
216+ if (s instanceof RectangularShape &&
217+ ((RectangularShape)s).isEmpty())
218+ {
219+ return EMPTY_REGION;
220+ }
221+
222+ int box[] = new int[4];
223+ ShapeSpanIterator sr = new ShapeSpanIterator(normalize);
224+ try {
225+ sr.setOutputArea(devBounds);
226+ sr.appendPath(s.getPathIterator(at));
227+ sr.getPathBox(box);
228+ Region r = Region.getInstance(box);
229+ r.appendSpans(sr);
230+ return r;
231+ } finally {
232+ sr.dispose();
233+ }
234+ }
235+
236+ /**
237+ * Returns a Region object with a rectangle of interest specified
238+ * by the indicated Rectangle object.
239+ * <p>
240+ * This method can also be used to create a simple rectangular
241+ * region.
242+ */
243+ public static Region getInstance(Rectangle r) {
244+ return Region.getInstanceXYWH(r.x, r.y, r.width, r.height);
245+ }
246+
247+ /**
248+ * Returns a Region object with a rectangle of interest specified
249+ * by the indicated rectangular area in x, y, width, height format.
250+ * <p>
251+ * This method can also be used to create a simple rectangular
252+ * region.
253+ */
254+ public static Region getInstanceXYWH(int x, int y, int w, int h) {
255+ return Region.getInstanceXYXY(x, y, dimAdd(x, w), dimAdd(y, h));
256+ }
257+
258+ /**
259+ * Returns a Region object with a rectangle of interest specified
260+ * by the indicated span array.
261+ * <p>
262+ * This method can also be used to create a simple rectangular
263+ * region.
264+ */
265+ public static Region getInstance(int box[]) {
266+ return new Region(box[0], box[1], box[2], box[3]);
267+ }
268+
269+ /**
270+ * Returns a Region object with a rectangle of interest specified
271+ * by the indicated rectangular area in lox, loy, hix, hiy format.
272+ * <p>
273+ * This method can also be used to create a simple rectangular
274+ * region.
275+ */
276+ public static Region getInstanceXYXY(int lox, int loy, int hix, int hiy) {
277+ return new Region(lox, loy, hix, hiy);
278+ }
279+
280+ /**
281+ * Sets the rectangle of interest for storing and returning
282+ * region bands.
283+ * <p>
284+ * This method can also be used to initialize a simple rectangular
285+ * region.
286+ */
287+ public void setOutputArea(Rectangle r) {
288+ setOutputAreaXYWH(r.x, r.y, r.width, r.height);
289+ }
290+
291+ /**
292+ * Sets the rectangle of interest for storing and returning
293+ * region bands. The rectangle is specified in x, y, width, height
294+ * format and appropriate clipping is performed as per the method
295+ * <code>dimAdd</code>.
296+ * <p>
297+ * This method can also be used to initialize a simple rectangular
298+ * region.
299+ */
300+ public void setOutputAreaXYWH(int x, int y, int w, int h) {
301+ setOutputAreaXYXY(x, y, dimAdd(x, w), dimAdd(y, h));
302+ }
303+
304+ /**
305+ * Sets the rectangle of interest for storing and returning
306+ * region bands. The rectangle is specified as a span array.
307+ * <p>
308+ * This method can also be used to initialize a simple rectangular
309+ * region.
310+ */
311+ public void setOutputArea(int box[]) {
312+ this.lox = box[0];
313+ this.loy = box[1];
314+ this.hix = box[2];
315+ this.hiy = box[3];
316+ }
317+
318+ /**
319+ * Sets the rectangle of interest for storing and returning
320+ * region bands. The rectangle is specified in lox, loy,
321+ * hix, hiy format.
322+ * <p>
323+ * This method can also be used to initialize a simple rectangular
324+ * region.
325+ */
326+ public void setOutputAreaXYXY(int lox, int loy, int hix, int hiy) {
327+ this.lox = lox;
328+ this.loy = loy;
329+ this.hix = hix;
330+ this.hiy = hiy;
331+ }
332+
333+ /**
334+ * Appends the list of spans returned from the indicated
335+ * SpanIterator. Each span must be at a higher starting
336+ * Y coordinate than the previous data or it must have a
337+ * Y range equal to the highest Y band in the region and a
338+ * higher X coordinate than any of the spans in that band.
339+ */
340+ public void appendSpans(SpanIterator si) {
341+ int[] box = new int[6];
342+
343+ while (si.nextSpan(box)) {
344+ appendSpan(box);
345+ }
346+
347+ endRow(box);
348+ calcBBox();
349+ }
350+
351+ /**
352+ * Returns a Region object that represents the same list of
353+ * rectangles as the current Region object, translated by
354+ * the specified dx, dy translation factors.
355+ */
356+ public Region getTranslatedRegion(int dx, int dy) {
357+ if ((dx | dy) == 0) {
358+ return this;
359+ }
360+ int tlox = lox + dx;
361+ int tloy = loy + dy;
362+ int thix = hix + dx;
363+ int thiy = hiy + dy;
364+ if ((tlox > lox) != (dx > 0) ||
365+ (tloy > loy) != (dy > 0) ||
366+ (thix > hix) != (dx > 0) ||
367+ (thiy > hiy) != (dy > 0))
368+ {
369+ return getSafeTranslatedRegion(dx, dy);
370+ }
371+ Region ret = new Region(tlox, tloy, thix, thiy);
372+ int bands[] = this.bands;
373+ if (bands != null) {
374+ int end = endIndex;
375+ ret.endIndex = end;
376+ int newbands[] = new int[end];
377+ ret.bands = newbands;
378+ int i = 0;
379+ int ncol;
380+ while (i < end) {
381+ newbands[i] = bands[i] + dy; i++;
382+ newbands[i] = bands[i] + dy; i++;
383+ newbands[i] = ncol = bands[i]; i++;
384+ while (--ncol >= 0) {
385+ newbands[i] = bands[i] + dx; i++;
386+ newbands[i] = bands[i] + dx; i++;
387+ }
388+ }
389+ }
390+ return ret;
391+ }
392+
393+ private Region getSafeTranslatedRegion(int dx, int dy) {
394+ int tlox = clipAdd(lox, dx);
395+ int tloy = clipAdd(loy, dy);
396+ int thix = clipAdd(hix, dx);
397+ int thiy = clipAdd(hiy, dy);
398+ Region ret = new Region(tlox, tloy, thix, thiy);
399+ int bands[] = this.bands;
400+ if (bands != null) {
401+ int end = endIndex;
402+ int newbands[] = new int[end];
403+ int i = 0; // index for source bands
404+ int j = 0; // index for translated newbands
405+ int ncol;
406+ while (i < end) {
407+ int y1, y2;
408+ newbands[j++] = y1 = clipAdd(bands[i++], dy);
409+ newbands[j++] = y2 = clipAdd(bands[i++], dy);
410+ newbands[j++] = ncol = bands[i++];
411+ int savej = j;
412+ if (y1 < y2) {
413+ while (--ncol >= 0) {
414+ int x1 = clipAdd(bands[i++], dx);
415+ int x2 = clipAdd(bands[i++], dx);
416+ if (x1 < x2) {
417+ newbands[j++] = x1;
418+ newbands[j++] = x2;
419+ }
420+ }
421+ } else {
422+ i += ncol * 2;
423+ }
424+ // Did we get any non-empty bands in this row?
425+ if (j > savej) {
426+ newbands[savej-1] = (j - savej) / 2;
427+ } else {
428+ j = savej - 3;
429+ }
430+ }
431+ if (j <= 5) {
432+ if (j < 5) {
433+ // No rows or bands were generated...
434+ ret.lox = ret.loy = ret.hix = ret.hiy = 0;
435+ } else {
436+ // Only generated one single rect in the end...
437+ ret.loy = newbands[0];
438+ ret.hiy = newbands[1];
439+ ret.lox = newbands[3];
440+ ret.hix = newbands[4];
441+ }
442+ // ret.endIndex and ret.bands were never initialized...
443+ // ret.endIndex = 0;
444+ // ret.newbands = null;
445+ } else {
446+ // Generated multiple bands and/or multiple rows...
447+ ret.endIndex = j;
448+ ret.bands = newbands;
449+ }
450+ }
451+ return ret;
452+ }
453+
454+ /**
455+ * Returns a Region object that represents the intersection of
456+ * this object with the specified Rectangle. The return value
457+ * may be this same object if no clipping occurs.
458+ */
459+ public Region getIntersection(Rectangle r) {
460+ return getIntersectionXYWH(r.x, r.y, r.width, r.height);
461+ }
462+
463+ /**
464+ * Returns a Region object that represents the intersection of
465+ * this object with the specified rectangular area. The return
466+ * value may be this same object if no clipping occurs.
467+ */
468+ public Region getIntersectionXYWH(int x, int y, int w, int h) {
469+ return getIntersectionXYXY(x, y, dimAdd(x, w), dimAdd(y, h));
470+ }
471+
472+ /**
473+ * Returns a Region object that represents the intersection of
474+ * this object with the specified rectangular area. The return
475+ * value may be this same object if no clipping occurs.
476+ */
477+ public Region getIntersectionXYXY(int lox, int loy, int hix, int hiy) {
478+ if (isInsideXYXY(lox, loy, hix, hiy)) {
479+ return this;
480+ }
481+ Region ret = new Region((lox < this.lox) ? this.lox : lox,
482+ (loy < this.loy) ? this.loy : loy,
483+ (hix > this.hix) ? this.hix : hix,
484+ (hiy > this.hiy) ? this.hiy : hiy);
485+ if (bands != null) {
486+ ret.appendSpans(this.getSpanIterator());
487+ }
488+ return ret;
489+ }
490+
491+ /**
492+ * Returns a Region object that represents the intersection of this
493+ * object with the specified Region object.
494+ * <p>
495+ * If {@code A} and {@code B} are both Region Objects and
496+ * <code>C = A.getIntersection(B);</code> then a point will
497+ * be contained in {@code C} iff it is contained in both
498+ * {@code A} and {@code B}.
499+ * <p>
500+ * The return value may be this same object or the argument
501+ * Region object if no clipping occurs.
502+ */
503+ public Region getIntersection(Region r) {
504+ if (this.isInsideQuickCheck(r)) {
505+ return this;
506+ }
507+ if (r.isInsideQuickCheck(this)) {
508+ return r;
509+ }
510+ Region ret = new Region((r.lox < this.lox) ? this.lox : r.lox,
511+ (r.loy < this.loy) ? this.loy : r.loy,
512+ (r.hix > this.hix) ? this.hix : r.hix,
513+ (r.hiy > this.hiy) ? this.hiy : r.hiy);
514+ if (!ret.isEmpty()) {
515+ ret.filterSpans(this, r, INCLUDE_COMMON);
516+ }
517+ return ret;
518+ }
519+
520+ /**
521+ * Returns a Region object that represents the union of this
522+ * object with the specified Region object.
523+ * <p>
524+ * If {@code A} and {@code B} are both Region Objects and
525+ * <code>C = A.getUnion(B);</code> then a point will
526+ * be contained in {@code C} iff it is contained in either
527+ * {@code A} or {@code B}.
528+ * <p>
529+ * The return value may be this same object or the argument
530+ * Region object if no augmentation occurs.
531+ */
532+ public Region getUnion(Region r) {
533+ if (r.isEmpty() || r.isInsideQuickCheck(this)) {
534+ return this;
535+ }
536+ if (this.isEmpty() || this.isInsideQuickCheck(r)) {
537+ return r;
538+ }
539+ Region ret = new Region((r.lox > this.lox) ? this.lox : r.lox,
540+ (r.loy > this.loy) ? this.loy : r.loy,
541+ (r.hix < this.hix) ? this.hix : r.hix,
542+ (r.hiy < this.hiy) ? this.hiy : r.hiy);
543+ ret.filterSpans(this, r, INCLUDE_A | INCLUDE_B | INCLUDE_COMMON);
544+ return ret;
545+ }
546+
547+ /**
548+ * Returns a Region object that represents the difference of the
549+ * specified Region object subtracted from this object.
550+ * <p>
551+ * If {@code A} and {@code B} are both Region Objects and
552+ * <code>C = A.getDifference(B);</code> then a point will
553+ * be contained in {@code C} iff it is contained in
554+ * {@code A} but not contained in {@code B}.
555+ * <p>
556+ * The return value may be this same object or the argument
557+ * Region object if no clipping occurs.
558+ */
559+ public Region getDifference(Region r) {
560+ if (!r.intersectsQuickCheck(this)) {
561+ return this;
562+ }
563+ if (this.isInsideQuickCheck(r)) {
564+ return EMPTY_REGION;
565+ }
566+ Region ret = new Region(this.lox, this.loy, this.hix, this.hiy);
567+ ret.filterSpans(this, r, INCLUDE_A);
568+ return ret;
569+ }
570+
571+ /**
572+ * Returns a Region object that represents the exclusive or of this
573+ * object with the specified Region object.
574+ * <p>
575+ * If {@code A} and {@code B} are both Region Objects and
576+ * <code>C = A.getExclusiveOr(B);</code> then a point will
577+ * be contained in {@code C} iff it is contained in either
578+ * {@code A} or {@code B}, but not if it is contained in both.
579+ * <p>
580+ * The return value may be this same object or the argument
581+ * Region object if either is empty.
582+ */
583+ public Region getExclusiveOr(Region r) {
584+ if (r.isEmpty()) {
585+ return this;
586+ }
587+ if (this.isEmpty()) {
588+ return r;
589+ }
590+ Region ret = new Region((r.lox > this.lox) ? this.lox : r.lox,
591+ (r.loy > this.loy) ? this.loy : r.loy,
592+ (r.hix < this.hix) ? this.hix : r.hix,
593+ (r.hiy < this.hiy) ? this.hiy : r.hiy);
594+ ret.filterSpans(this, r, INCLUDE_A | INCLUDE_B);
595+ return ret;
596+ }
597+
598+ static final int INCLUDE_A = 1;
599+ static final int INCLUDE_B = 2;
600+ static final int INCLUDE_COMMON = 4;
601+
602+ private void filterSpans(Region ra, Region rb, int flags) {
603+ int abands[] = ra.bands;
604+ int bbands[] = rb.bands;
605+ if (abands == null) {
606+ abands = new int[] {ra.loy, ra.hiy, 1, ra.lox, ra.hix};
607+ }
608+ if (bbands == null) {
609+ bbands = new int[] {rb.loy, rb.hiy, 1, rb.lox, rb.hix};
610+ }
611+ int box[] = new int[6];
612+ int acolstart = 0;
613+ int ay1 = abands[acolstart++];
614+ int ay2 = abands[acolstart++];
615+ int acolend = abands[acolstart++];
616+ acolend = acolstart + 2 * acolend;
617+ int bcolstart = 0;
618+ int by1 = bbands[bcolstart++];
619+ int by2 = bbands[bcolstart++];
620+ int bcolend = bbands[bcolstart++];
621+ bcolend = bcolstart + 2 * bcolend;
622+ int y = loy;
623+ while (y < hiy) {
624+ if (y >= ay2) {
625+ if (acolend < ra.endIndex) {
626+ acolstart = acolend;
627+ ay1 = abands[acolstart++];
628+ ay2 = abands[acolstart++];
629+ acolend = abands[acolstart++];
630+ acolend = acolstart + 2 * acolend;
631+ } else {
632+ if ((flags & INCLUDE_B) == 0) break;
633+ ay1 = ay2 = hiy;
634+ }
635+ continue;
636+ }
637+ if (y >= by2) {
638+ if (bcolend < rb.endIndex) {
639+ bcolstart = bcolend;
640+ by1 = bbands[bcolstart++];
641+ by2 = bbands[bcolstart++];
642+ bcolend = bbands[bcolstart++];
643+ bcolend = bcolstart + 2 * bcolend;
644+ } else {
645+ if ((flags & INCLUDE_A) == 0) break;
646+ by1 = by2 = hiy;
647+ }
648+ continue;
649+ }
650+ int yend;
651+ if (y < by1) {
652+ if (y < ay1) {
653+ y = Math.min(ay1, by1);
654+ continue;
655+ }
656+ // We are in a set of rows that belong only to A
657+ yend = Math.min(ay2, by1);
658+ if ((flags & INCLUDE_A) != 0) {
659+ box[1] = y;
660+ box[3] = yend;
661+ int acol = acolstart;
662+ while (acol < acolend) {
663+ box[0] = abands[acol++];
664+ box[2] = abands[acol++];
665+ appendSpan(box);
666+ }
667+ }
668+ } else if (y < ay1) {
669+ // We are in a set of rows that belong only to B
670+ yend = Math.min(by2, ay1);
671+ if ((flags & INCLUDE_B) != 0) {
672+ box[1] = y;
673+ box[3] = yend;
674+ int bcol = bcolstart;
675+ while (bcol < bcolend) {
676+ box[0] = bbands[bcol++];
677+ box[2] = bbands[bcol++];
678+ appendSpan(box);
679+ }
680+ }
681+ } else {
682+ // We are in a set of rows that belong to both A and B
683+ yend = Math.min(ay2, by2);
684+ box[1] = y;
685+ box[3] = yend;
686+ int acol = acolstart;
687+ int bcol = bcolstart;
688+ int ax1 = abands[acol++];
689+ int ax2 = abands[acol++];
690+ int bx1 = bbands[bcol++];
691+ int bx2 = bbands[bcol++];
692+ int x = Math.min(ax1, bx1);
693+ if (x < lox) x = lox;
694+ while (x < hix) {
695+ if (x >= ax2) {
696+ if (acol < acolend) {
697+ ax1 = abands[acol++];
698+ ax2 = abands[acol++];
699+ } else {
700+ if ((flags & INCLUDE_B) == 0) break;
701+ ax1 = ax2 = hix;
702+ }
703+ continue;
704+ }
705+ if (x >= bx2) {
706+ if (bcol < bcolend) {
707+ bx1 = bbands[bcol++];
708+ bx2 = bbands[bcol++];
709+ } else {
710+ if ((flags & INCLUDE_A) == 0) break;
711+ bx1 = bx2 = hix;
712+ }
713+ continue;
714+ }
715+ int xend;
716+ boolean appendit;
717+ if (x < bx1) {
718+ if (x < ax1) {
719+ xend = Math.min(ax1, bx1);
720+ appendit = false;
721+ } else {
722+ xend = Math.min(ax2, bx1);
723+ appendit = ((flags & INCLUDE_A) != 0);
724+ }
725+ } else if (x < ax1) {
726+ xend = Math.min(ax1, bx2);
727+ appendit = ((flags & INCLUDE_B) != 0);
728+ } else {
729+ xend = Math.min(ax2, bx2);
730+ appendit = ((flags & INCLUDE_COMMON) != 0);
731+ }
732+ if (appendit) {
733+ box[0] = x;
734+ box[2] = xend;
735+ appendSpan(box);
736+ }
737+ x = xend;
738+ }
739+ }
740+ y = yend;
741+ }
742+ endRow(box);
743+ calcBBox();
744+ }
745+
746+ /**
747+ * Returns a Region object that represents the bounds of the
748+ * intersection of this object with the bounds of the specified
749+ * Region object.
750+ * <p>
751+ * The return value may be this same object if no clipping occurs
752+ * and this Region is rectangular.
753+ */
754+ public Region getBoundsIntersection(Rectangle r) {
755+ return getBoundsIntersectionXYWH(r.x, r.y, r.width, r.height);
756+ }
757+
758+ /**
759+ * Returns a Region object that represents the bounds of the
760+ * intersection of this object with the bounds of the specified
761+ * rectangular area in x, y, width, height format.
762+ * <p>
763+ * The return value may be this same object if no clipping occurs
764+ * and this Region is rectangular.
765+ */
766+ public Region getBoundsIntersectionXYWH(int x, int y, int w, int h) {
767+ return getBoundsIntersectionXYXY(x, y, dimAdd(x, w), dimAdd(y, h));
768+ }
769+
770+ /**
771+ * Returns a Region object that represents the bounds of the
772+ * intersection of this object with the bounds of the specified
773+ * rectangular area in lox, loy, hix, hiy format.
774+ * <p>
775+ * The return value may be this same object if no clipping occurs
776+ * and this Region is rectangular.
777+ */
778+ public Region getBoundsIntersectionXYXY(int lox, int loy,
779+ int hix, int hiy)
780+ {
781+ if (this.bands == null &&
782+ this.lox >= lox && this.loy >= loy &&
783+ this.hix <= hix && this.hiy <= hiy)
784+ {
785+ return this;
786+ }
787+ return new Region((lox < this.lox) ? this.lox : lox,
788+ (loy < this.loy) ? this.loy : loy,
789+ (hix > this.hix) ? this.hix : hix,
790+ (hiy > this.hiy) ? this.hiy : hiy);
791+ }
792+
793+ /**
794+ * Returns a Region object that represents the intersection of
795+ * this object with the bounds of the specified Region object.
796+ * <p>
797+ * The return value may be this same object or the argument
798+ * Region object if no clipping occurs and the Regions are
799+ * rectangular.
800+ */
801+ public Region getBoundsIntersection(Region r) {
802+ if (this.encompasses(r)) {
803+ return r;
804+ }
805+ if (r.encompasses(this)) {
806+ return this;
807+ }
808+ return new Region((r.lox < this.lox) ? this.lox : r.lox,
809+ (r.loy < this.loy) ? this.loy : r.loy,
810+ (r.hix > this.hix) ? this.hix : r.hix,
811+ (r.hiy > this.hiy) ? this.hiy : r.hiy);
812+ }
813+
814+ /**
815+ * Appends a single span defined by the 4 parameters
816+ * spanlox, spanloy, spanhix, spanhiy.
817+ * This span must be at a higher starting Y coordinate than
818+ * the previous data or it must have a Y range equal to the
819+ * highest Y band in the region and a higher X coordinate
820+ * than any of the spans in that band.
821+ */
822+ private void appendSpan(int box[]) {
823+ int spanlox, spanloy, spanhix, spanhiy;
824+ if ((spanlox = box[0]) < lox) spanlox = lox;
825+ if ((spanloy = box[1]) < loy) spanloy = loy;
826+ if ((spanhix = box[2]) > hix) spanhix = hix;
827+ if ((spanhiy = box[3]) > hiy) spanhiy = hiy;
828+ if (spanhix <= spanlox || spanhiy <= spanloy) {
829+ return;
830+ }
831+
832+ int curYrow = box[4];
833+ if (endIndex == 0 || spanloy >= bands[curYrow + 1]) {
834+ if (bands == null) {
835+ bands = new int[INIT_SIZE];
836+ } else {
837+ needSpace(5);
838+ endRow(box);
839+ curYrow = box[4];
840+ }
841+ bands[endIndex++] = spanloy;
842+ bands[endIndex++] = spanhiy;
843+ bands[endIndex++] = 0;
844+ } else if (spanloy == bands[curYrow] &&
845+ spanhiy == bands[curYrow + 1] &&
846+ spanlox >= bands[endIndex - 1]) {
847+ if (spanlox == bands[endIndex - 1]) {
848+ bands[endIndex - 1] = spanhix;
849+ return;
850+ }
851+ needSpace(2);
852+ } else {
853+ throw new InternalError("bad span");
854+ }
855+ bands[endIndex++] = spanlox;
856+ bands[endIndex++] = spanhix;
857+ bands[curYrow + 2]++;
858+ }
859+
860+ private void needSpace(int num) {
861+ if (endIndex + num >= bands.length) {
862+ int[] newbands = new int[bands.length + GROW_SIZE];
863+ System.arraycopy(bands, 0, newbands, 0, endIndex);
864+ bands = newbands;
865+ }
866+ }
867+
868+ private void endRow(int box[]) {
869+ int cur = box[4];
870+ int prev = box[5];
871+ if (cur > prev) {
872+ int[] bands = this.bands;
873+ if (bands[prev + 1] == bands[cur] &&
874+ bands[prev + 2] == bands[cur + 2])
875+ {
876+ int num = bands[cur + 2] * 2;
877+ cur += 3;
878+ prev += 3;
879+ while (num > 0) {
880+ if (bands[cur++] != bands[prev++]) {
881+ break;
882+ }
883+ num--;
884+ }
885+ if (num == 0) {
886+ // prev == box[4]
887+ bands[box[5] + 1] = bands[prev + 1];
888+ endIndex = prev;
889+ return;
890+ }
891+ }
892+ }
893+ box[5] = box[4];
894+ box[4] = endIndex;
895+ }
896+
897+ private void calcBBox() {
898+ int[] bands = this.bands;
899+ if (endIndex <= 5) {
900+ if (endIndex == 0) {
901+ lox = loy = hix = hiy = 0;
902+ } else {
903+ loy = bands[0];
904+ hiy = bands[1];
905+ lox = bands[3];
906+ hix = bands[4];
907+ endIndex = 0;
908+ }
909+ this.bands = null;
910+ return;
911+ }
912+ int lox = this.hix;
913+ int hix = this.lox;
914+ int hiyindex = 0;
915+
916+ int i = 0;
917+ while (i < endIndex) {
918+ hiyindex = i;
919+ int numbands = bands[i + 2];
920+ i += 3;
921+ if (lox > bands[i]) {
922+ lox = bands[i];
923+ }
924+ i += numbands * 2;
925+ if (hix < bands[i - 1]) {
926+ hix = bands[i - 1];
927+ }
928+ }
929+
930+ this.lox = lox;
931+ this.loy = bands[0];
932+ this.hix = hix;
933+ this.hiy = bands[hiyindex + 1];
934+ }
935+
936+ /**
937+ * Returns the lowest X coordinate in the Region.
938+ */
939+ public final int getLoX() {
940+ return lox;
941+ }
942+
943+ /**
944+ * Returns the lowest Y coordinate in the Region.
945+ */
946+ public final int getLoY() {
947+ return loy;
948+ }
949+
950+ /**
951+ * Returns the highest X coordinate in the Region.
952+ */
953+ public final int getHiX() {
954+ return hix;
955+ }
956+
957+ /**
958+ * Returns the highest Y coordinate in the Region.
959+ */
960+ public final int getHiY() {
961+ return hiy;
962+ }
963+
964+ /**
965+ * Returns the width of this Region clipped to the range (0 - MAX_INT).
966+ */
967+ public final int getWidth() {
968+ if (hix < lox) return 0;
969+ int w;
970+ if ((w = hix - lox) < 0) {
971+ w = Integer.MAX_VALUE;
972+ }
973+ return w;
974+ }
975+
976+ /**
977+ * Returns the height of this Region clipped to the range (0 - MAX_INT).
978+ */
979+ public final int getHeight() {
980+ if (hiy < loy) return 0;
981+ int h;
982+ if ((h = hiy - loy) < 0) {
983+ h = Integer.MAX_VALUE;
984+ }
985+ return h;
986+ }
987+
988+ /**
989+ * Returns true iff this Region encloses no area.
990+ */
991+ public boolean isEmpty() {
992+ return (hix <= lox || hiy <= loy);
993+ }
994+
995+ /**
996+ * Returns true iff this Region represents a single simple
997+ * rectangular area.
998+ */
999+ public boolean isRectangular() {
1000+ return (bands == null);
1001+ }
1002+
1003+ /**
1004+ * Returns true iff this Region contains the specified coordinate.
1005+ */
1006+ public boolean contains(int x, int y) {
1007+ if (x < lox || x >= hix || y < loy || y >= hiy) return false;
1008+ if (bands == null) return true;
1009+ int i = 0;
1010+ while (i < endIndex) {
1011+ if (y < bands[i++]) {
1012+ return false;
1013+ }
1014+ if (y >= bands[i++]) {
1015+ int numspans = bands[i++];
1016+ i += numspans * 2;
1017+ } else {
1018+ int end = bands[i++];
1019+ end = i + end * 2;
1020+ while (i < end) {
1021+ if (x < bands[i++]) return false;
1022+ if (x < bands[i++]) return true;
1023+ }
1024+ return false;
1025+ }
1026+ }
1027+ return false;
1028+ }
1029+
1030+ /**
1031+ * Returns true iff this Region lies inside the indicated
1032+ * rectangular area specified in x, y, width, height format
1033+ * with appropriate clipping performed as per the dimAdd method.
1034+ */
1035+ public boolean isInsideXYWH(int x, int y, int w, int h) {
1036+ return isInsideXYXY(x, y, dimAdd(x, w), dimAdd(y, h));
1037+ }
1038+
1039+ /**
1040+ * Returns true iff this Region lies inside the indicated
1041+ * rectangular area specified in lox, loy, hix, hiy format.
1042+ */
1043+ public boolean isInsideXYXY(int lox, int loy, int hix, int hiy) {
1044+ return (this.lox >= lox && this.loy >= loy &&
1045+ this.hix <= hix && this.hiy <= hiy);
1046+
1047+ }
1048+
1049+ /**
1050+ * Quickly checks if this Region lies inside the specified
1051+ * Region object.
1052+ * <p>
1053+ * This method will return false if the specified Region
1054+ * object is not a simple rectangle.
1055+ */
1056+ public boolean isInsideQuickCheck(Region r) {
1057+ return (r.bands == null &&
1058+ r.lox <= this.lox && r.loy <= this.loy &&
1059+ r.hix >= this.hix && r.hiy >= this.hiy);
1060+ }
1061+
1062+ /**
1063+ * Quickly checks if this Region intersects the specified
1064+ * rectangular area specified in lox, loy, hix, hiy format.
1065+ * <p>
1066+ * This method tests only against the bounds of this region
1067+ * and does not bother to test if the rectangular region
1068+ * actually intersects any bands.
1069+ */
1070+ public boolean intersectsQuickCheckXYXY(int lox, int loy,
1071+ int hix, int hiy)
1072+ {
1073+ return (hix > this.lox && lox < this.hix &&
1074+ hiy > this.loy && loy < this.hiy);
1075+ }
1076+
1077+ /**
1078+ * Quickly checks if this Region intersects the specified
1079+ * Region object.
1080+ * <p>
1081+ * This method tests only against the bounds of this region
1082+ * and does not bother to test if the rectangular region
1083+ * actually intersects any bands.
1084+ */
1085+ public boolean intersectsQuickCheck(Region r) {
1086+ return (r.hix > this.lox && r.lox < this.hix &&
1087+ r.hiy > this.loy && r.loy < this.hiy);
1088+ }
1089+
1090+ /**
1091+ * Quickly checks if this Region surrounds the specified
1092+ * Region object.
1093+ * <p>
1094+ * This method will return false if this Region object is
1095+ * not a simple rectangle.
1096+ */
1097+ public boolean encompasses(Region r) {
1098+ return (this.bands == null &&
1099+ this.lox <= r.lox && this.loy <= r.loy &&
1100+ this.hix >= r.hix && this.hiy >= r.hiy);
1101+ }
1102+
1103+ /**
1104+ * Quickly checks if this Region surrounds the specified
1105+ * rectangular area specified in x, y, width, height format.
1106+ * <p>
1107+ * This method will return false if this Region object is
1108+ * not a simple rectangle.
1109+ */
1110+ public boolean encompassesXYWH(int x, int y, int w, int h) {
1111+ return encompassesXYXY(x, y, dimAdd(x, w), dimAdd(y, h));
1112+ }
1113+
1114+ /**
1115+ * Quickly checks if this Region surrounds the specified
1116+ * rectangular area specified in lox, loy, hix, hiy format.
1117+ * <p>
1118+ * This method will return false if this Region object is
1119+ * not a simple rectangle.
1120+ */
1121+ public boolean encompassesXYXY(int lox, int loy, int hix, int hiy) {
1122+ return (this.bands == null &&
1123+ this.lox <= lox && this.loy <= loy &&
1124+ this.hix >= hix && this.hiy >= hiy);
1125+ }
1126+
1127+ /**
1128+ * Gets the bbox of the available spans, clipped to the OutputArea.
1129+ */
1130+ public void getBounds(int pathbox[]) {
1131+ pathbox[0] = lox;
1132+ pathbox[1] = loy;
1133+ pathbox[2] = hix;
1134+ pathbox[3] = hiy;
1135+ }
1136+
1137+ /**
1138+ * Clips the indicated bbox array to the bounds of this Region.
1139+ */
1140+ public void clipBoxToBounds(int bbox[]) {
1141+ if (bbox[0] < lox) bbox[0] = lox;
1142+ if (bbox[1] < loy) bbox[1] = loy;
1143+ if (bbox[2] > hix) bbox[2] = hix;
1144+ if (bbox[3] > hiy) bbox[3] = hiy;
1145+ }
1146+
1147+ /**
1148+ * Gets an iterator object to iterate over the spans in this region.
1149+ */
1150+ public RegionIterator getIterator() {
1151+ return new RegionIterator(this);
1152+ }
1153+
1154+ /**
1155+ * Gets a span iterator object that iterates over the spans in this region
1156+ */
1157+ public SpanIterator getSpanIterator() {
1158+ return new RegionSpanIterator(this);
1159+ }
1160+
1161+ /**
1162+ * Gets a span iterator object that iterates over the spans in this region
1163+ * but clipped to the bounds given in the argument (xlo, ylo, xhi, yhi).
1164+ */
1165+ public SpanIterator getSpanIterator(int bbox[]) {
1166+ SpanIterator result = getSpanIterator();
1167+ result.intersectClipBox(bbox[0], bbox[1], bbox[2], bbox[3]);
1168+ return result;
1169+ }
1170+
1171+ /**
1172+ * Returns a SpanIterator that is the argument iterator filtered by
1173+ * this region.
1174+ */
1175+ public SpanIterator filter(SpanIterator si) {
1176+ if (bands == null) {
1177+ si.intersectClipBox(lox, loy, hix, hiy);
1178+ } else {
1179+ si = new RegionClipSpanIterator(this, si);
1180+ }
1181+ return si;
1182+ }
1183+
1184+ public String toString() {
1185+ StringBuffer sb = new StringBuffer();
1186+ sb.append("Region[[");
1187+ sb.append(lox);
1188+ sb.append(", ");
1189+ sb.append(loy);
1190+ sb.append(" => ");
1191+ sb.append(hix);
1192+ sb.append(", ");
1193+ sb.append(hiy);
1194+ sb.append("]");
1195+ if (bands != null) {
1196+ int col = 0;
1197+ while (col < endIndex) {
1198+ sb.append("y{");
1199+ sb.append(bands[col++]);
1200+ sb.append(",");
1201+ sb.append(bands[col++]);
1202+ sb.append("}[");
1203+ int end = bands[col++];
1204+ end = col + end * 2;
1205+ while (col < end) {
1206+ sb.append("x(");
1207+ sb.append(bands[col++]);
1208+ sb.append(", ");
1209+ sb.append(bands[col++]);
1210+ sb.append(")");
1211+ }
1212+ sb.append("]");
1213+ }
1214+ }
1215+ sb.append("]");
1216+ return sb.toString();
1217+ }
1218+
1219+ public int hashCode() {
1220+ return (isEmpty() ? 0 : (lox * 3 + loy * 5 + hix * 7 + hiy * 9));
1221+ }
1222+
1223+ public boolean equals(Object o) {
1224+ if (!(o instanceof Region)) {
1225+ return false;
1226+ }
1227+ Region r = (Region) o;
1228+ if (this.isEmpty()) {
1229+ return r.isEmpty();
1230+ } else if (r.isEmpty()) {
1231+ return false;
1232+ }
1233+ if (r.lox != this.lox || r.loy != this.loy ||
1234+ r.hix != this.hix || r.hiy != this.hiy)
1235+ {
1236+ return false;
1237+ }
1238+ if (this.bands == null) {
1239+ return (r.bands == null);
1240+ } else if (r.bands == null) {
1241+ return false;
1242+ }
1243+ if (this.endIndex != r.endIndex) {
1244+ return false;
1245+ }
1246+ int abands[] = this.bands;
1247+ int bbands[] = r.bands;
1248+ for (int i = 0; i < endIndex; i++) {
1249+ if (abands[i] != bbands[i]) {
1250+ return false;
1251+ }
1252+ }
1253+ return true;
1254+ }
1255+}
java/pkg/sun/java2d/pipe/RegionClipSpanIterator.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/RegionClipSpanIterator.java+392−0
@@ -0,0 +1,392 @@
1+/*
2+ * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.geom.PathIterator;
29+import java.awt.Rectangle;
30+
31+/**
32+ * This class clips a SpanIterator to a Region and outputs the
33+ * resulting spans as another SpanIterator.
34+ *
35+ * Spans are output in the usual y/x order, unless the input span
36+ * iterator doesn't conform to this order, or the iterator's span
37+ * straddle more than one band of the Region used for clipping.
38+ *
39+ * Principle of operation:
40+ *
41+ * The iterator maintains a several cursors onto the RegionIterator
42+ * in order to avoid having to buffer spans from the SpanIterator.
43+ * They are:
44+ * resetState The initial state of the RegionIterator
45+ * lwm Low Water Mark, a running start point for
46+ * processing each band. Usually goes down, but
47+ * can be reset to resetState if a span has a lower
48+ * start coordinate than the previous one.
49+ * row The start of the current band of the RegionIterator
50+ * box The current span of the current row
51+ *
52+ * The main nextSpan() loop implements a coroutine like structure, with
53+ * three producers to get the next span, row and box calling each other
54+ * to iterate through the span iterator and region.
55+ *
56+ * REMIND: Needs a native implementation!
57+ */
58+public class RegionClipSpanIterator implements SpanIterator {
59+
60+ // The inputs to the filter
61+ Region rgn;
62+ SpanIterator spanIter;
63+
64+ // The cursors that track the progress through the region
65+ RegionIterator resetState;
66+ RegionIterator lwm;
67+ RegionIterator row;
68+ RegionIterator box;
69+
70+ // The bounds of the current span iterator span
71+ int spanlox, spanhix, spanloy, spanhiy;
72+
73+ // The extent of the region band marking the low water mark
74+ int lwmloy, lwmhiy;
75+
76+ // The bounds of the current region box
77+ int rgnlox, rgnloy, rgnhix, rgnhiy;
78+
79+ // The bounding box of the input Region. Used for click
80+ // rejection of iterator spans
81+ int rgnbndslox, rgnbndsloy, rgnbndshix, rgnbndshiy;
82+
83+ // The array used to hold coordinates from the region iterator
84+ int rgnbox[] = new int[4];
85+
86+ // The array used to hold coordinates from the span iterator
87+ int spanbox[] = new int[4];
88+
89+ // True if the next iterator span should be read on the next
90+ // iteration of the main nextSpan() loop
91+ boolean doNextSpan;
92+
93+ // True if the next region box should be read on the next
94+ // iteration of the main nextSpan() loop
95+ boolean doNextBox;
96+
97+ // True if there are no more spans or the Region is empty
98+ boolean done = false;
99+
100+ /*
101+ * Creates an instance that filters the spans generated by
102+ * spanIter through the region described by rgn.
103+ */
104+ public RegionClipSpanIterator(Region rgn, SpanIterator spanIter) {
105+
106+ this.spanIter = spanIter;
107+
108+ resetState = rgn.getIterator();
109+ lwm = resetState.createCopy();
110+
111+ if (!lwm.nextYRange(rgnbox)) {
112+ done = true;
113+ return;
114+ }
115+
116+ rgnloy = lwmloy = rgnbox[1];
117+ rgnhiy = lwmhiy = rgnbox[3];
118+
119+ rgn.getBounds(rgnbox);
120+ rgnbndslox = rgnbox[0];
121+ rgnbndsloy = rgnbox[1];
122+ rgnbndshix = rgnbox[2];
123+ rgnbndshiy = rgnbox[3];
124+ if (rgnbndslox >= rgnbndshix ||
125+ rgnbndsloy >= rgnbndshiy) {
126+ done = true;
127+ return;
128+ }
129+
130+ this.rgn = rgn;
131+
132+
133+ row = lwm.createCopy();
134+ box = row.createCopy();
135+ doNextSpan = true;
136+ doNextBox = false;
137+ }
138+
139+ /*
140+ * Gets the bbox of the available path segments, clipped to the
141+ * Region.
142+ */
143+ public void getPathBox(int pathbox[]) {
144+ int[] rgnbox = new int[4];
145+ rgn.getBounds(rgnbox);
146+ spanIter.getPathBox(pathbox);
147+
148+ if (pathbox[0] < rgnbox[0]) {
149+ pathbox[0] = rgnbox[0];
150+ }
151+
152+ if (pathbox[1] < rgnbox[1]) {
153+ pathbox[1] = rgnbox[1];
154+ }
155+
156+ if (pathbox[2] > rgnbox[2]) {
157+ pathbox[2] = rgnbox[2];
158+ }
159+
160+ if (pathbox[3] > rgnbox[3]) {
161+ pathbox[3] = rgnbox[3];
162+ }
163+}
164+
165+ /*
166+ * Intersects the path box with the given bbox.
167+ * Returned spans are clipped to this region, or discarded
168+ * altogether if they lie outside it.
169+ */
170+ public void intersectClipBox(int lox, int loy, int hix, int hiy) {
171+ spanIter.intersectClipBox(lox, loy, hix, hiy);
172+ }
173+
174+
175+ /*
176+ * Fetches the next span that needs to be operated on.
177+ * If the return value is false then there are no more spans.
178+ */
179+ public boolean nextSpan(int resultbox[]) {
180+ if (done) {
181+ return false;
182+ }
183+
184+ int resultlox, resultloy, resulthix, resulthiy;
185+ boolean doNextRow = false;
186+
187+ // REMIND: Cache the coordinate inst vars used in this loop
188+ // in locals vars.
189+ while (true) {
190+ // We've exhausted the current span so get the next one
191+ if (doNextSpan) {
192+ if (!spanIter.nextSpan(spanbox)) {
193+ done = true;
194+ return false;
195+ } else {
196+ spanlox = spanbox[0];
197+ // Clip out spans that lie outside of the rgn's bounds
198+ if (spanlox >= rgnbndshix) {
199+ continue;
200+ }
201+
202+ spanloy = spanbox[1];
203+ if (spanloy >= rgnbndshiy) {
204+ continue;
205+ }
206+
207+ spanhix = spanbox[2];
208+ if (spanhix <= rgnbndslox) {
209+ continue;
210+ }
211+
212+ spanhiy = spanbox[3];
213+ if (spanhiy <= rgnbndsloy) {
214+ continue;
215+ }
216+ }
217+ // If the span starts higher up than the low-water mark,
218+ // reset the lwm. This can only happen if spans aren't
219+ // returned in strict y/x order, or the first time through.
220+ if (lwmloy > spanloy) {
221+ lwm.copyStateFrom(resetState);
222+ lwm.nextYRange(rgnbox);
223+ lwmloy = rgnbox[1];
224+ lwmhiy = rgnbox[3];
225+ }
226+ // Skip to the first rgn row whose bottom edge is
227+ // below the top of the current span. This will only
228+ // execute >0 times when the current span starts in a
229+ // lower region row than the previous one, or possibly the
230+ // first time through.
231+ while (lwmhiy <= spanloy) {
232+ if (!lwm.nextYRange(rgnbox))
233+ break;
234+ lwmloy = rgnbox[1];
235+ lwmhiy = rgnbox[3];
236+ }
237+ // If the row overlaps the span, process it, otherwise
238+ // fetch another span
239+ if (lwmhiy > spanloy && lwmloy < spanhiy) {
240+ // Update the current row if it's different from the
241+ // new lwm
242+ if (rgnloy != lwmloy) {
243+ row.copyStateFrom(lwm);
244+ rgnloy = lwmloy;
245+ rgnhiy = lwmhiy;
246+ }
247+ box.copyStateFrom(row);
248+ doNextBox = true;
249+ doNextSpan = false;
250+ }
251+ continue;
252+ }
253+
254+ // The current row's spans are exhausted, do the next one
255+ if (doNextRow) {
256+ // Next time we either do the next span or the next box
257+ doNextRow = false;
258+ // Get the next row
259+ boolean ok = row.nextYRange(rgnbox);
260+ // If there was one, update the bounds
261+ if (ok) {
262+ rgnloy = rgnbox[1];
263+ rgnhiy = rgnbox[3];
264+ }
265+ if (!ok || rgnloy >= spanhiy) {
266+ // If we've exhausted the rows or this one is below the span,
267+ // go onto the next span
268+ doNextSpan = true;
269+ }
270+ else {
271+ // Otherwise get the first box on this row
272+ box.copyStateFrom(row);
273+ doNextBox = true;
274+ }
275+ continue;
276+ }
277+
278+ // Process the next box in the current row
279+ if (doNextBox) {
280+ boolean ok = box.nextXBand(rgnbox);
281+ if (ok) {
282+ rgnlox = rgnbox[0];
283+ rgnhix = rgnbox[2];
284+ }
285+ if (!ok || rgnlox >= spanhix) {
286+ // If there was no next rgn span or it's beyond the
287+ // source span, go onto the next row or span
288+ doNextBox = false;
289+ if (rgnhiy >= spanhiy) {
290+ // If the current row totally overlaps the span,
291+ // go onto the next span
292+ doNextSpan = true;
293+ } else {
294+ // otherwise go onto the next rgn row
295+ doNextRow = true;
296+ }
297+ } else {
298+ // Otherwise, if the new rgn span overlaps the
299+ // spanbox, no need to get another box
300+ doNextBox = rgnhix <= spanlox;
301+ }
302+ continue;
303+ }
304+
305+ // Prepare to do the next box either on this call or
306+ // or the subsequent one
307+ doNextBox = true;
308+
309+ // Clip the current span against the current box
310+ if (spanlox > rgnlox) {
311+ resultlox = spanlox;
312+ }
313+ else {
314+ resultlox = rgnlox;
315+ }
316+
317+ if (spanloy > rgnloy) {
318+ resultloy = spanloy;
319+ }
320+ else {
321+ resultloy = rgnloy;
322+ }
323+
324+ if (spanhix < rgnhix) {
325+ resulthix = spanhix;
326+ }
327+ else {
328+ resulthix = rgnhix;
329+ }
330+
331+ if (spanhiy < rgnhiy) {
332+ resulthiy = spanhiy;
333+ }
334+ else {
335+ resulthiy = rgnhiy;
336+ }
337+
338+ // If the result is empty, try then next box
339+ // otherwise return the box.
340+ // REMIND: I think by definition it's non-empty
341+ // if we're here. Need to think about this some more.
342+ if (resultlox >= resulthix ||
343+ resultloy >= resulthiy) {
344+ continue;
345+ }
346+ else {
347+ break;
348+ }
349+ }
350+
351+ resultbox[0] = resultlox;
352+ resultbox[1] = resultloy;
353+ resultbox[2] = resulthix;
354+ resultbox[3] = resulthiy;
355+ return true;
356+
357+ }
358+
359+
360+ /**
361+ * This method tells the iterator that it may skip all spans
362+ * whose Y range is completely above the indicated Y coordinate.
363+ */
364+ public void skipDownTo(int y) {
365+ spanIter.skipDownTo(y);
366+ }
367+
368+ /**
369+ * This method returns a native pointer to a function block that
370+ * can be used by a native method to perform the same iteration
371+ * cycle that the above methods provide while avoiding upcalls to
372+ * the Java object.
373+ * The definition of the structure whose pointer is returned by
374+ * this method is defined in:
375+ * <pre>
376+ * src/share/native/sun/java2d/pipe/SpanIterator.h
377+ * </pre>
378+ */
379+ public long getNativeIterator() {
380+ return 0;
381+ }
382+
383+ /*
384+ * Cleans out all internal data structures.
385+ */
386+ //public native void dispose();
387+
388+ protected void finalize() {
389+ //dispose();
390+ }
391+
392+}
java/pkg/sun/java2d/pipe/RegionIterator.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/RegionIterator.java+101−0
@@ -0,0 +1,101 @@
1+/*
2+ * Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Rectangle;
29+
30+/**
31+ * This class defines the API for iterating through the bands
32+ * of a region object.
33+ */
34+public class RegionIterator {
35+ Region region;
36+ int curIndex;
37+ int numXbands;
38+
39+ RegionIterator(Region r) {
40+ region = r;
41+ }
42+
43+ /**
44+ * Returns a new RegionIterator object representing the same
45+ * iteration state as this object to allow multiple iteration
46+ * branches from the current position.
47+ */
48+ public RegionIterator createCopy() {
49+ RegionIterator r = new RegionIterator(region);
50+ r.curIndex = this.curIndex;
51+ r.numXbands = this.numXbands;
52+ return r;
53+ }
54+
55+ /**
56+ * Copies the iteration state from this RegionIterator object
57+ * into another RegionIterator object to allow multiple iteration
58+ * branches from the current position.
59+ */
60+ public void copyStateFrom(RegionIterator ri) {
61+ if (this.region != ri.region) {
62+ throw new InternalError("region mismatch");
63+ }
64+ this.curIndex = ri.curIndex;
65+ this.numXbands = ri.numXbands;
66+ }
67+
68+ /**
69+ * Moves the iteration state to the beginning of the next
70+ * Y range in the region returning true if one is found
71+ * and recording the low and high Y coordinates of the
72+ * range in the array at locations 1 and 3 respectively.
73+ */
74+ public boolean nextYRange(int range[]) {
75+ curIndex += numXbands * 2;
76+ numXbands = 0;
77+ if (curIndex >= region.endIndex) {
78+ return false;
79+ }
80+ range[1] = region.bands[curIndex++];
81+ range[3] = region.bands[curIndex++];
82+ numXbands = region.bands[curIndex++];
83+ return true;
84+ }
85+
86+ /**
87+ * Moves the iteration state to the beginning of the next
88+ * X band in the current Y range returning true if one is
89+ * found and recording the low and high X coordinates of
90+ * the range in the array at locations 0 and 2 respectively.
91+ */
92+ public boolean nextXBand(int range[]) {
93+ if (numXbands <= 0) {
94+ return false;
95+ }
96+ numXbands--;
97+ range[0] = region.bands[curIndex++];
98+ range[2] = region.bands[curIndex++];
99+ return true;
100+ }
101+}
java/pkg/sun/java2d/pipe/RegionSpanIterator.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/RegionSpanIterator.java+210−0
@@ -0,0 +1,210 @@
1+/*
2+ * Copyright (c) 1999, 2002, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+/**
29+ * This class implements the ShapeIterator interface for a Region.
30+ * This is useful as the source iterator of a device clip region
31+ * (in its native guise), and also as the result of clipping a
32+ * Region to a rectangle.
33+ */
34+public class RegionSpanIterator implements SpanIterator {
35+ // The RegionIterator that we use to do the work
36+ RegionIterator ri;
37+
38+ // Clipping bounds
39+ int lox, loy, hix, hiy;
40+
41+ // Current Y band limits
42+ int curloy, curhiy;
43+
44+ // Are we done?
45+ boolean done = false;
46+
47+ // Is the associated Region rectangular?
48+ boolean isrect;
49+
50+/*
51+ REMIND: For native implementation
52+ long pData; // Private storage of rect info
53+
54+ static {
55+ initIDs();
56+ }
57+
58+ public static native void initIDs();
59+*/
60+
61+ /**
62+ * Constructs an instance based on the given Region
63+ */
64+ public RegionSpanIterator(Region r) {
65+ int[] bounds = new int[4];
66+
67+ r.getBounds(bounds);
68+ lox = bounds[0];
69+ loy = bounds[1];
70+ hix = bounds[2];
71+ hiy = bounds[3];
72+ isrect = r.isRectangular();
73+
74+ ri = r.getIterator();
75+ }
76+
77+ /**
78+ * Gets the bbox of the available region spans.
79+ */
80+ public void getPathBox(int pathbox[]) {
81+ pathbox[0] = lox;
82+ pathbox[1] = loy;
83+ pathbox[2] = hix;
84+ pathbox[3] = hiy;
85+ }
86+
87+ /**
88+ * Intersect the box used for clipping the output spans with the
89+ * given box.
90+ */
91+ public void intersectClipBox(int clox, int cloy, int chix, int chiy) {
92+ if (clox > lox) {
93+ lox = clox;
94+ }
95+ if (cloy > loy) {
96+ loy = cloy;
97+ }
98+ if (chix < hix) {
99+ hix = chix;
100+ }
101+ if (chiy < hiy) {
102+ hiy = chiy;
103+ }
104+ done = lox >= hix || loy >= hiy;
105+ }
106+
107+ /**
108+ * Fetches the next span that needs to be operated on.
109+ * If the return value is false then there are no more spans.
110+ */
111+ public boolean nextSpan(int spanbox[]) {
112+
113+ // Quick test for end conditions
114+ if (done) {
115+ return false;
116+ }
117+
118+ // If the Region is rectangular, we store our bounds (possibly
119+ // clipped via intersectClipBox()) in spanbox and return true
120+ // so that the caller will process the single span. We set done
121+ // to true to ensure that this will be the last span processed.
122+ if (isrect) {
123+ getPathBox(spanbox);
124+ done = true;
125+ return true;
126+ }
127+
128+ // Local cache of current span's bounds
129+ int curlox, curhix;
130+ int curloy = this.curloy;
131+ int curhiy = this.curhiy;
132+
133+ while (true) {
134+ if (!ri.nextXBand(spanbox)) {
135+ if (!ri.nextYRange(spanbox)) {
136+ done = true;
137+ return false;
138+ }
139+ // Update the current y band and clip it
140+ curloy = spanbox[1];
141+ curhiy = spanbox[3];
142+ if (curloy < loy) {
143+ curloy = loy;
144+ }
145+ if (curhiy > hiy) {
146+ curhiy = hiy;
147+ }
148+ // Check for moving below the clip rect
149+ if (curloy >= hiy) {
150+ done = true;
151+ return false;
152+ }
153+ continue;
154+ }
155+ // Clip the x box
156+ curlox = spanbox[0];
157+ curhix = spanbox[2];
158+ if (curlox < lox) {
159+ curlox = lox;
160+ }
161+ if (curhix > hix) {
162+ curhix = hix;
163+ }
164+ // If it's non- box, we're done
165+ if (curlox < curhix && curloy < curhiy) {
166+ break;
167+ }
168+ }
169+
170+ // Update the result and the store y range
171+ spanbox[0] = curlox;
172+ spanbox[1] = this.curloy = curloy;
173+ spanbox[2] = curhix;
174+ spanbox[3] = this.curhiy = curhiy;
175+ return true;
176+ }
177+
178+ /**
179+ * This method tells the iterator that it may skip all spans
180+ * whose Y range is completely above the indicated Y coordinate.
181+ */
182+ public void skipDownTo(int y) {
183+ loy = y;
184+ }
185+
186+ /**
187+ * This method returns a native pointer to a function block that
188+ * can be used by a native method to perform the same iteration
189+ * cycle that the above methods provide while avoiding upcalls to
190+ * the Java object.
191+ * The definition of the structure whose pointer is returned by
192+ * this method is defined in:
193+ * <pre>
194+ * src/share/native/sun/java2d/pipe/SpanIterator.h
195+ * </pre>
196+ */
197+ public long getNativeIterator() {
198+ return 0;
199+ }
200+
201+ /*
202+ * Cleans out all internal data structures.
203+ * REMIND: Native implementation
204+ public native void dispose();
205+
206+ protected void finalize() {
207+ dispose();
208+ }
209+ */
210+}
java/pkg/sun/java2d/pipe/RenderBuffer.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/RenderBuffer.java+294−0
@@ -0,0 +1,294 @@
1+/*
2+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import sun.misc.Unsafe;
29+
30+/**
31+ * The RenderBuffer class is a simplified, high-performance, Unsafe wrapper
32+ * used for buffering rendering operations in a single-threaded rendering
33+ * environment. It's functionality is similar to the ByteBuffer and related
34+ * NIO classes. However, the methods in this class perform little to no
35+ * alignment or bounds checks for performance reasons. Therefore, it is
36+ * the caller's responsibility to ensure that all put() calls are properly
37+ * aligned and within bounds:
38+ * - int and float values must be aligned on 4-byte boundaries
39+ * - long and double values must be aligned on 8-byte boundaries
40+ *
41+ * This class only includes the bare minimum of methods to support
42+ * single-threaded rendering. For example, there is no put(double[]) method
43+ * because we currently have no need for such a method in the STR classes.
44+ */
45+public class RenderBuffer {
46+
47+ /**
48+ * These constants represent the size of various data types (in bytes).
49+ */
50+ protected static final long SIZEOF_BYTE = 1L;
51+ protected static final long SIZEOF_SHORT = 2L;
52+ protected static final long SIZEOF_INT = 4L;
53+ protected static final long SIZEOF_FLOAT = 4L;
54+ protected static final long SIZEOF_LONG = 8L;
55+ protected static final long SIZEOF_DOUBLE = 8L;
56+
57+ /**
58+ * Represents the number of elements at which we have empirically
59+ * determined that the average cost of a JNI call exceeds the expense
60+ * of an element by element copy. In other words, if the number of
61+ * elements in an array to be copied exceeds this value, then we should
62+ * use the copyFromArray() method to complete the bulk put operation.
63+ * (This value can be adjusted if the cost of JNI downcalls is reduced
64+ * in a future release.)
65+ */
66+ private static final int COPY_FROM_ARRAY_THRESHOLD = 6;
67+
68+ protected final Unsafe unsafe;
69+ protected final long baseAddress;
70+ protected final long endAddress;
71+ protected long curAddress;
72+ protected final int capacity;
73+
74+ protected RenderBuffer(int numBytes) {
75+ unsafe = Unsafe.getUnsafe();
76+ curAddress = baseAddress = unsafe.allocateMemory(numBytes);
77+ endAddress = baseAddress + numBytes;
78+ capacity = numBytes;
79+ }
80+
81+ /**
82+ * Allocates a fresh buffer using the machine endianness.
83+ */
84+ public static RenderBuffer allocate(int numBytes) {
85+ return new RenderBuffer(numBytes);
86+ }
87+
88+ /**
89+ * Returns the base address of the underlying memory buffer.
90+ */
91+ public final long getAddress() {
92+ return baseAddress;
93+ }
94+
95+ /**
96+ * The behavior (and names) of the following methods are nearly
97+ * identical to their counterparts in the various NIO Buffer classes.
98+ */
99+
100+ public final int capacity() {
101+ return capacity;
102+ }
103+
104+ public final int remaining() {
105+ return (int)(endAddress - curAddress);
106+ }
107+
108+ public final int position() {
109+ return (int)(curAddress - baseAddress);
110+ }
111+
112+ public final void position(long numBytes) {
113+ curAddress = baseAddress + numBytes;
114+ }
115+
116+ public final void clear() {
117+ curAddress = baseAddress;
118+ }
119+
120+ public final RenderBuffer skip(long numBytes) {
121+ curAddress += numBytes;
122+ return this;
123+ }
124+
125+ /**
126+ * putByte() methods...
127+ */
128+
129+ public final RenderBuffer putByte(byte x) {
130+ unsafe.putByte(curAddress, x);
131+ curAddress += SIZEOF_BYTE;
132+ return this;
133+ }
134+
135+ public RenderBuffer put(byte[] x) {
136+ return put(x, 0, x.length);
137+ }
138+
139+ public RenderBuffer put(byte[] x, int offset, int length) {
140+ if (length > COPY_FROM_ARRAY_THRESHOLD) {
141+ long offsetInBytes = offset * SIZEOF_BYTE + Unsafe.ARRAY_BYTE_BASE_OFFSET;
142+ long lengthInBytes = length * SIZEOF_BYTE;
143+ unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes);
144+ position(position() + lengthInBytes);
145+ } else {
146+ int end = offset + length;
147+ for (int i = offset; i < end; i++) {
148+ putByte(x[i]);
149+ }
150+ }
151+ return this;
152+ }
153+
154+ /**
155+ * putShort() methods...
156+ */
157+
158+ public final RenderBuffer putShort(short x) {
159+ // assert (position() % SIZEOF_SHORT == 0);
160+ unsafe.putShort(curAddress, x);
161+ curAddress += SIZEOF_SHORT;
162+ return this;
163+ }
164+
165+ public RenderBuffer put(short[] x) {
166+ return put(x, 0, x.length);
167+ }
168+
169+ public RenderBuffer put(short[] x, int offset, int length) {
170+ // assert (position() % SIZEOF_SHORT == 0);
171+ if (length > COPY_FROM_ARRAY_THRESHOLD) {
172+ long offsetInBytes = offset * SIZEOF_SHORT + Unsafe.ARRAY_SHORT_BASE_OFFSET;
173+ long lengthInBytes = length * SIZEOF_SHORT;
174+ unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes);
175+ position(position() + lengthInBytes);
176+ } else {
177+ int end = offset + length;
178+ for (int i = offset; i < end; i++) {
179+ putShort(x[i]);
180+ }
181+ }
182+ return this;
183+ }
184+
185+ /**
186+ * putInt() methods...
187+ */
188+
189+ public final RenderBuffer putInt(int pos, int x) {
190+ // assert (baseAddress + pos % SIZEOF_INT == 0);
191+ unsafe.putInt(baseAddress + pos, x);
192+ return this;
193+ }
194+
195+ public final RenderBuffer putInt(int x) {
196+ // assert (position() % SIZEOF_INT == 0);
197+ unsafe.putInt(curAddress, x);
198+ curAddress += SIZEOF_INT;
199+ return this;
200+ }
201+
202+ public RenderBuffer put(int[] x) {
203+ return put(x, 0, x.length);
204+ }
205+
206+ public RenderBuffer put(int[] x, int offset, int length) {
207+ // assert (position() % SIZEOF_INT == 0);
208+ if (length > COPY_FROM_ARRAY_THRESHOLD) {
209+ long offsetInBytes = offset * SIZEOF_INT + Unsafe.ARRAY_INT_BASE_OFFSET;
210+ long lengthInBytes = length * SIZEOF_INT;
211+ unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes);
212+ position(position() + lengthInBytes);
213+ } else {
214+ int end = offset + length;
215+ for (int i = offset; i < end; i++) {
216+ putInt(x[i]);
217+ }
218+ }
219+ return this;
220+ }
221+
222+ /**
223+ * putFloat() methods...
224+ */
225+
226+ public final RenderBuffer putFloat(float x) {
227+ // assert (position() % SIZEOF_FLOAT == 0);
228+ unsafe.putFloat(curAddress, x);
229+ curAddress += SIZEOF_FLOAT;
230+ return this;
231+ }
232+
233+ public RenderBuffer put(float[] x) {
234+ return put(x, 0, x.length);
235+ }
236+
237+ public RenderBuffer put(float[] x, int offset, int length) {
238+ // assert (position() % SIZEOF_FLOAT == 0);
239+ if (length > COPY_FROM_ARRAY_THRESHOLD) {
240+ long offsetInBytes = offset * SIZEOF_FLOAT + Unsafe.ARRAY_FLOAT_BASE_OFFSET;
241+ long lengthInBytes = length * SIZEOF_FLOAT;
242+ unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes);
243+ position(position() + lengthInBytes);
244+ } else {
245+ int end = offset + length;
246+ for (int i = offset; i < end; i++) {
247+ putFloat(x[i]);
248+ }
249+ }
250+ return this;
251+ }
252+
253+ /**
254+ * putLong() methods...
255+ */
256+
257+ public final RenderBuffer putLong(long x) {
258+ // assert (position() % SIZEOF_LONG == 0);
259+ unsafe.putLong(curAddress, x);
260+ curAddress += SIZEOF_LONG;
261+ return this;
262+ }
263+
264+ public RenderBuffer put(long[] x) {
265+ return put(x, 0, x.length);
266+ }
267+
268+ public RenderBuffer put(long[] x, int offset, int length) {
269+ // assert (position() % SIZEOF_LONG == 0);
270+ if (length > COPY_FROM_ARRAY_THRESHOLD) {
271+ long offsetInBytes = offset * SIZEOF_LONG + Unsafe.ARRAY_LONG_BASE_OFFSET;
272+ long lengthInBytes = length * SIZEOF_LONG;
273+ unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes);
274+ position(position() + lengthInBytes);
275+ } else {
276+ int end = offset + length;
277+ for (int i = offset; i < end; i++) {
278+ putLong(x[i]);
279+ }
280+ }
281+ return this;
282+ }
283+
284+ /**
285+ * putDouble() method(s)...
286+ */
287+
288+ public final RenderBuffer putDouble(double x) {
289+ // assert (position() % SIZEOF_DOUBLE == 0);
290+ unsafe.putDouble(curAddress, x);
291+ curAddress += SIZEOF_DOUBLE;
292+ return this;
293+ }
294+}
java/pkg/sun/java2d/pipe/RenderQueue.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/RenderQueue.java+223−0
@@ -0,0 +1,223 @@
1+/*
2+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.util.HashSet;
29+import java.util.Set;
30+import sun.awt.SunToolkit;
31+
32+/**
33+ * The RenderQueue class encapsulates a RenderBuffer on which rendering
34+ * operations are enqueued. Note that the RenderQueue lock must be acquired
35+ * before performing any operations on the queue (e.g. enqueuing an operation
36+ * or flushing the queue). A sample usage scenario follows:
37+ *
38+ * public void drawSomething(...) {
39+ * rq.lock();
40+ * try {
41+ * ctx.validate(...);
42+ * rq.ensureCapacity(4);
43+ * rq.getBuffer().putInt(DRAW_SOMETHING);
44+ * ...
45+ * } finally {
46+ * rq.unlock();
47+ * }
48+ * }
49+ *
50+ * If you are enqueuing an operation that involves 8-byte parameters (i.e.
51+ * long or double values), it is imperative that you ensure proper
52+ * alignment of the underlying RenderBuffer. This can be accomplished
53+ * simply by providing an offset to the first 8-byte parameter in your
54+ * operation to the ensureCapacityAndAlignment() method. For example:
55+ *
56+ * public void drawStuff(...) {
57+ * rq.lock();
58+ * try {
59+ * RenderBuffer buf = rq.getBuffer();
60+ * ctx.validate(...);
61+ * // 28 total bytes in the operation, 12 bytes to the first long
62+ * rq.ensureCapacityAndAlignment(28, 12);
63+ * buf.putInt(DRAW_STUFF);
64+ * buf.putInt(x).putInt(y);
65+ * buf.putLong(addr1);
66+ * buf.putLong(addr2);
67+ * } finally {
68+ * rq.unlock();
69+ * }
70+ * }
71+ */
72+public abstract class RenderQueue {
73+
74+ /** The size of the underlying buffer, in bytes. */
75+ private static final int BUFFER_SIZE = 32000;
76+
77+ /** The underlying buffer for this queue. */
78+ protected RenderBuffer buf;
79+
80+ /**
81+ * A Set containing hard references to Objects that must stay alive until
82+ * the queue has been completely flushed.
83+ */
84+ protected Set refSet;
85+
86+ protected RenderQueue() {
87+ refSet = new HashSet();
88+ buf = RenderBuffer.allocate(BUFFER_SIZE);
89+ }
90+
91+ /**
92+ * Locks the queue for read/write access.
93+ */
94+ public final void lock() {
95+ /*
96+ * Implementation note: In theory we should have two separate locks:
97+ * one lock to synchronize access to the RenderQueue, and then a
98+ * separate lock (the AWT lock) that only needs to be acquired when
99+ * we are about to flush the queue (using native windowing system
100+ * operations). In practice it has been difficult to enforce the
101+ * correct lock ordering; sometimes AWT will have already acquired
102+ * the AWT lock before grabbing the RQ lock (see 6253009), while the
103+ * expected order should be RQ lock and then AWT lock. Due to this
104+ * issue, using two separate locks is prone to deadlocks. Therefore,
105+ * to solve this issue we have decided to eliminate the separate RQ
106+ * lock and instead just acquire the AWT lock here. (Someday it might
107+ * be nice to go back to the old two-lock system, but that would
108+ * require potentially risky changes to AWT to ensure that it never
109+ * acquires the AWT lock before calling into 2D code that wants to
110+ * acquire the RQ lock.)
111+ */
112+ SunToolkit.awtLock();
113+ }
114+
115+ /**
116+ * Attempts to lock the queue. If successful, this method returns true,
117+ * indicating that the caller is responsible for calling
118+ * <code>unlock</code>; otherwise this method returns false.
119+ */
120+ public final boolean tryLock() {
121+ return SunToolkit.awtTryLock();
122+ }
123+
124+ /**
125+ * Unlocks the queue.
126+ */
127+ public final void unlock() {
128+ SunToolkit.awtUnlock();
129+ }
130+
131+ /**
132+ * Adds the given Object to the set of hard references, which will
133+ * prevent that Object from being disposed until the queue has been
134+ * flushed completely. This is useful in cases where some enqueued
135+ * data could become invalid if the reference Object were garbage
136+ * collected before the queue could be processed. (For example, keeping
137+ * a hard reference to a FontStrike will prevent any enqueued glyph
138+ * images associated with that strike from becoming invalid before the
139+ * queue is flushed.) The reference set will be cleared immediately
140+ * after the queue is flushed each time.
141+ */
142+ public final void addReference(Object ref) {
143+ refSet.add(ref);
144+ }
145+
146+ /**
147+ * Returns the encapsulated RenderBuffer object.
148+ */
149+ public final RenderBuffer getBuffer() {
150+ return buf;
151+ }
152+
153+ /**
154+ * Ensures that there will be enough room on the underlying buffer
155+ * for the following operation. If the operation will not fit given
156+ * the remaining space, the buffer will be flushed immediately, leaving
157+ * an empty buffer for the impending operation.
158+ *
159+ * @param opsize size (in bytes) of the following operation
160+ */
161+ public final void ensureCapacity(int opsize) {
162+ if (buf.remaining() < opsize) {
163+ flushNow();
164+ }
165+ }
166+
167+ /**
168+ * Convenience method that is equivalent to calling ensureCapacity()
169+ * followed by ensureAlignment(). The ensureCapacity() call allows for an
170+ * extra 4 bytes of space in case the ensureAlignment() method needs to
171+ * insert a NOOP token on the buffer.
172+ *
173+ * @param opsize size (in bytes) of the following operation
174+ * @param first8ByteValueOffset offset (in bytes) from the current
175+ * position to the first 8-byte value used in the following operation
176+ */
177+ public final void ensureCapacityAndAlignment(int opsize,
178+ int first8ByteValueOffset)
179+ {
180+ ensureCapacity(opsize + 4);
181+ ensureAlignment(first8ByteValueOffset);
182+ }
183+
184+ /**
185+ * Inserts a 4-byte NOOP token when necessary to ensure that all 8-byte
186+ * parameters for the following operation are added to the underlying
187+ * buffer with an 8-byte memory alignment.
188+ *
189+ * @param first8ByteValueOffset offset (in bytes) from the current
190+ * position to the first 8-byte value used in the following operation
191+ */
192+ public final void ensureAlignment(int first8ByteValueOffset) {
193+ int first8ByteValuePosition = buf.position() + first8ByteValueOffset;
194+ if ((first8ByteValuePosition & 7) != 0) {
195+ buf.putInt(BufferedOpCodes.NOOP);
196+ }
197+ }
198+
199+ /**
200+ * Immediately processes each operation currently pending on the buffer.
201+ * This method will block until the entire buffer has been flushed. The
202+ * queue lock must be acquired before calling this method.
203+ */
204+ public abstract void flushNow();
205+
206+ /**
207+ * Immediately processes each operation currently pending on the buffer,
208+ * and then invokes the provided task. This method will block until the
209+ * entire buffer has been flushed and the provided task has been executed.
210+ * The queue lock must be acquired before calling this method.
211+ */
212+ public abstract void flushAndInvokeNow(Runnable task);
213+
214+ /**
215+ * Updates the current position of the underlying buffer, and then
216+ * flushes the queue immediately. This method is useful when native code
217+ * has added data to the queue and needs to flush immediately.
218+ */
219+ public void flushNow(int position) {
220+ buf.position(position);
221+ flushNow();
222+ }
223+}
java/pkg/sun/java2d/pipe/RenderingEngine$1.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/RenderingEngine$Tracer.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/RenderingEngine.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/RenderingEngine.java+482−0
@@ -0,0 +1,482 @@
1+/*
2+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Shape;
29+import java.awt.BasicStroke;
30+import java.awt.geom.PathIterator;
31+import java.awt.geom.AffineTransform;
32+
33+import java.security.PrivilegedAction;
34+import java.security.AccessController;
35+import java.util.ServiceLoader;
36+import sun.security.action.GetPropertyAction;
37+
38+import sun.awt.geom.PathConsumer2D;
39+
40+/**
41+ * This class abstracts a number of features for which the Java 2D
42+ * implementation relies on proprietary licensed software libraries.
43+ * Access to those features is now achieved by retrieving the singleton
44+ * instance of this class and calling the appropriate methods on it.
45+ * The 3 primary features abstracted here include:
46+ * <dl>
47+ * <dt>Shape createStrokedShape(Shape, [BasicStroke attributes]);
48+ * <dd>This method implements the functionality of the method of the
49+ * same name on the {@link BasicStroke} class.
50+ * <dt>void strokeTo(Shape, [rendering parameters], PathConsumer2D);
51+ * <dd>This method performs widening of the source path on the fly
52+ * and sends the results to the given {@link PathConsumer2D} object.
53+ * This procedure avoids having to create an intermediate Shape
54+ * object to hold the results of the {@code createStrokedShape} method.
55+ * The main user of this method is the Java 2D non-antialiasing renderer.
56+ * <dt>AATileGenerator getAATileGenerator(Shape, [rendering parameters]);
57+ * <dd>This method returns an object which can iterate over the
58+ * specified bounding box and produce tiles of coverage values for
59+ * antialiased rendering. The details of the operation of the
60+ * {@link AATileGenerator} object are explained in its class comments.
61+ * </dl>
62+ * Additionally, the following informational method supplies important
63+ * data about the implementation.
64+ * <dl>
65+ * <dt>float getMinimumAAPenSize()
66+ * <dd>This method provides information on how small the BasicStroke
67+ * line width can get before dropouts occur. Rendering with a BasicStroke
68+ * is defined to never allow the line to have breaks, gaps, or dropouts
69+ * even if the width is set to 0.0f, so this information allows the
70+ * {@link SunGraphics2D} class to detect the "thin line" case and set
71+ * the rendering attributes accordingly.
72+ * </dl>
73+ * At startup the runtime will load a single instance of this class.
74+ * It searches the classpath for a registered provider of this API
75+ * and returns either the last one it finds, or the instance whose
76+ * class name matches the value supplied in the System property
77+ * {@code sun.java2d.renderer}.
78+ * Additionally, a runtime System property flag can be set to trace
79+ * all calls to methods on the {@code RenderingEngine} in use by
80+ * setting the sun.java2d.renderer.trace property to any non-null value.
81+ * <p>
82+ * Parts of the system that need to use any of the above features should
83+ * call {@code RenderingEngine.getInstance()} to obtain the properly
84+ * registered (and possibly trace-enabled) version of the RenderingEngine.
85+ */
86+public abstract class RenderingEngine {
87+ private static RenderingEngine reImpl;
88+
89+ /**
90+ * Returns an instance of {@code RenderingEngine} as determined
91+ * by the installation environment and runtime flags.
92+ * <p>
93+ * A specific instance of the {@code RenderingEngine} can be
94+ * chosen by specifying the runtime flag:
95+ * <pre>
96+ * java -Dsun.java2d.renderer=&lt;classname&gt;
97+ * </pre>
98+ *
99+ * If no specific {@code RenderingEngine} is specified on the command
100+ * or Ductus renderer is specified, it will attempt loading the
101+ * sun.dc.DuctusRenderingEngine class using Class.forName as a fastpath;
102+ * if not found, use the ServiceLoader.
103+ * If no specific {@code RenderingEngine} is specified on the command
104+ * line then the last one returned by enumerating all subclasses of
105+ * {@code RenderingEngine} known to the ServiceLoader is used.
106+ * <p>
107+ * Runtime tracing of the actions of the {@code RenderingEngine}
108+ * can be enabled by specifying the runtime flag:
109+ * <pre>
110+ * java -Dsun.java2d.renderer.trace=&lt;any string&gt;
111+ * </pre>
112+ * @return an instance of {@code RenderingEngine}
113+ * @since 1.7
114+ */
115+ public static synchronized RenderingEngine getInstance() {
116+ if (reImpl != null) {
117+ return reImpl;
118+ }
119+
120+ reImpl = (RenderingEngine)
121+ AccessController.doPrivileged(new PrivilegedAction() {
122+ public Object run() {
123+ final String ductusREClass = "sun.dc.DuctusRenderingEngine";
124+ String reClass =
125+ System.getProperty("sun.java2d.renderer", ductusREClass);
126+ if (reClass.equals(ductusREClass)) {
127+ try {
128+ Class cls = Class.forName(ductusREClass);
129+ return cls.newInstance();
130+ } catch (ClassNotFoundException x) {
131+ // not found
132+ } catch (IllegalAccessException x) {
133+ // should not reach here
134+ } catch (InstantiationException x) {
135+ // should not reach here
136+ }
137+ }
138+
139+ ServiceLoader<RenderingEngine> reLoader =
140+ ServiceLoader.loadInstalled(RenderingEngine.class);
141+
142+ RenderingEngine service = null;
143+
144+ for (RenderingEngine re : reLoader) {
145+ service = re;
146+ if (re.getClass().getName().equals(reClass)) {
147+ break;
148+ }
149+ }
150+ return service;
151+ }
152+ });
153+
154+ if (reImpl == null) {
155+ throw new InternalError("No RenderingEngine module found");
156+ }
157+
158+ GetPropertyAction gpa =
159+ new GetPropertyAction("sun.java2d.renderer.trace");
160+ String reTrace = (String) AccessController.doPrivileged(gpa);
161+ if (reTrace != null) {
162+ reImpl = new Tracer(reImpl);
163+ }
164+
165+ return reImpl;
166+ }
167+
168+ /**
169+ * Create a widened path as specified by the parameters.
170+ * <p>
171+ * The specified {@code src} {@link Shape} is widened according
172+ * to the specified attribute parameters as per the
173+ * {@link BasicStroke} specification.
174+ *
175+ * @param src the source path to be widened
176+ * @param width the width of the widened path as per {@code BasicStroke}
177+ * @param caps the end cap decorations as per {@code BasicStroke}
178+ * @param join the segment join decorations as per {@code BasicStroke}
179+ * @param miterlimit the miter limit as per {@code BasicStroke}
180+ * @param dashes the dash length array as per {@code BasicStroke}
181+ * @param dashphase the initial dash phase as per {@code BasicStroke}
182+ * @return the widened path stored in a new {@code Shape} object
183+ * @since 1.7
184+ */
185+ public abstract Shape createStrokedShape(Shape src,
186+ float width,
187+ int caps,
188+ int join,
189+ float miterlimit,
190+ float dashes[],
191+ float dashphase);
192+
193+ /**
194+ * Sends the geometry for a widened path as specified by the parameters
195+ * to the specified consumer.
196+ * <p>
197+ * The specified {@code src} {@link Shape} is widened according
198+ * to the parameters specified by the {@link BasicStroke} object.
199+ * Adjustments are made to the path as appropriate for the
200+ * {@link VALUE_STROKE_NORMALIZE} hint if the {@code normalize}
201+ * boolean parameter is true.
202+ * Adjustments are made to the path as appropriate for the
203+ * {@link VALUE_ANTIALIAS_ON} hint if the {@code antialias}
204+ * boolean parameter is true.
205+ * <p>
206+ * The geometry of the widened path is forwarded to the indicated
207+ * {@link PathConsumer2D} object as it is calculated.
208+ *
209+ * @param src the source path to be widened
210+ * @param bs the {@code BasicSroke} object specifying the
211+ * decorations to be applied to the widened path
212+ * @param normalize indicates whether stroke normalization should
213+ * be applied
214+ * @param antialias indicates whether or not adjustments appropriate
215+ * to antialiased rendering should be applied
216+ * @param consumer the {@code PathConsumer2D} instance to forward
217+ * the widened geometry to
218+ * @since 1.7
219+ */
220+ public abstract void strokeTo(Shape src,
221+ AffineTransform at,
222+ BasicStroke bs,
223+ boolean thin,
224+ boolean normalize,
225+ boolean antialias,
226+ PathConsumer2D consumer);
227+
228+ /**
229+ * Construct an antialiased tile generator for the given shape with
230+ * the given rendering attributes and store the bounds of the tile
231+ * iteration in the bbox parameter.
232+ * The {@code at} parameter specifies a transform that should affect
233+ * both the shape and the {@code BasicStroke} attributes.
234+ * The {@code clip} parameter specifies the current clip in effect
235+ * in device coordinates and can be used to prune the data for the
236+ * operation, but the renderer is not required to perform any
237+ * clipping.
238+ * If the {@code BasicStroke} parameter is null then the shape
239+ * should be filled as is, otherwise the attributes of the
240+ * {@code BasicStroke} should be used to specify a draw operation.
241+ * The {@code thin} parameter indicates whether or not the
242+ * transformed {@code BasicStroke} represents coordinates smaller
243+ * than the minimum resolution of the antialiasing rasterizer as
244+ * specified by the {@code getMinimumAAPenWidth()} method.
245+ * <p>
246+ * Upon returning, this method will fill the {@code bbox} parameter
247+ * with 4 values indicating the bounds of the iteration of the
248+ * tile generator.
249+ * The iteration order of the tiles will be as specified by the
250+ * pseudo-code:
251+ * <pre>
252+ * for (y = bbox[1]; y < bbox[3]; y += tileheight) {
253+ * for (x = bbox[0]; x < bbox[2]; x += tilewidth) {
254+ * }
255+ * }
256+ * </pre>
257+ * If there is no output to be rendered, this method may return
258+ * null.
259+ *
260+ * @param s the shape to be rendered (fill or draw)
261+ * @param at the transform to be applied to the shape and the
262+ * stroke attributes
263+ * @param clip the current clip in effect in device coordinates
264+ * @param bs if non-null, a {@code BasicStroke} whose attributes
265+ * should be applied to this operation
266+ * @param thin true if the transformed stroke attributes are smaller
267+ * than the minimum dropout pen width
268+ * @param normalize true if the {@code VALUE_STROKE_NORMALIZE}
269+ * {@code RenderingHint} is in effect
270+ * @param bbox returns the bounds of the iteration
271+ * @return the {@code AATileGenerator} instance to be consulted
272+ * for tile coverages, or null if there is no output to render
273+ * @since 1.7
274+ */
275+ public abstract AATileGenerator getAATileGenerator(Shape s,
276+ AffineTransform at,
277+ Region clip,
278+ BasicStroke bs,
279+ boolean thin,
280+ boolean normalize,
281+ int bbox[]);
282+
283+ /**
284+ * Construct an antialiased tile generator for the given parallelogram
285+ * store the bounds of the tile iteration in the bbox parameter.
286+ * The parallelogram is specified as a starting point and 2 delta
287+ * vectors that indicate the slopes of the 2 pairs of sides of the
288+ * parallelogram.
289+ * The 4 corners of the parallelogram are defined by the 4 points:
290+ * <ul>
291+ * <li> {@code x}, {@code y}
292+ * <li> {@code x+dx1}, {@code y+dy1}
293+ * <li> {@code x+dx1+dx2}, {@code y+dy1+dy2}
294+ * <li> {@code x+dx2}, {@code y+dy2}
295+ * </ul>
296+ * The {@code lw1} and {@code lw2} parameters provide a specification
297+ * for an optionally stroked parallelogram if they are positive numbers.
298+ * The {@code lw1} parameter is the ratio of the length of the {@code dx1},
299+ * {@code dx2} delta vector to half of the line width in that same
300+ * direction.
301+ * The {@code lw2} parameter provides the same ratio for the other delta
302+ * vector.
303+ * If {@code lw1} and {@code lw2} are both greater than zero, then
304+ * the parallelogram figure is doubled by both expanding and contracting
305+ * each delta vector by its corresponding {@code lw} value.
306+ * If either (@code lw1) or {@code lw2} are also greater than 1, then
307+ * the inner (contracted) parallelogram disappears and the figure is
308+ * simply a single expanded parallelogram.
309+ * The {@code clip} parameter specifies the current clip in effect
310+ * in device coordinates and can be used to prune the data for the
311+ * operation, but the renderer is not required to perform any
312+ * clipping.
313+ * <p>
314+ * Upon returning, this method will fill the {@code bbox} parameter
315+ * with 4 values indicating the bounds of the iteration of the
316+ * tile generator.
317+ * The iteration order of the tiles will be as specified by the
318+ * pseudo-code:
319+ * <pre>
320+ * for (y = bbox[1]; y < bbox[3]; y += tileheight) {
321+ * for (x = bbox[0]; x < bbox[2]; x += tilewidth) {
322+ * }
323+ * }
324+ * </pre>
325+ * If there is no output to be rendered, this method may return
326+ * null.
327+ *
328+ * @param x the X coordinate of the first corner of the parallelogram
329+ * @param y the Y coordinate of the first corner of the parallelogram
330+ * @param dx1 the X coordinate delta of the first leg of the parallelogram
331+ * @param dy1 the Y coordinate delta of the first leg of the parallelogram
332+ * @param dx2 the X coordinate delta of the second leg of the parallelogram
333+ * @param dy2 the Y coordinate delta of the second leg of the parallelogram
334+ * @param lw1 the line width ratio for the first leg of the parallelogram
335+ * @param lw2 the line width ratio for the second leg of the parallelogram
336+ * @param clip the current clip in effect in device coordinates
337+ * @param bbox returns the bounds of the iteration
338+ * @return the {@code AATileGenerator} instance to be consulted
339+ * for tile coverages, or null if there is no output to render
340+ * @since 1.7
341+ */
342+ public abstract AATileGenerator getAATileGenerator(double x, double y,
343+ double dx1, double dy1,
344+ double dx2, double dy2,
345+ double lw1, double lw2,
346+ Region clip,
347+ int bbox[]);
348+
349+ /**
350+ * Returns the minimum pen width that the antialiasing rasterizer
351+ * can represent without dropouts occuring.
352+ * @since 1.7
353+ */
354+ public abstract float getMinimumAAPenSize();
355+
356+ /**
357+ * Utility method to feed a {@link PathConsumer2D} object from a
358+ * given {@link PathIterator}.
359+ * This method deals with the details of running the iterator and
360+ * feeding the consumer a segment at a time.
361+ */
362+ public static void feedConsumer(PathIterator pi, PathConsumer2D consumer) {
363+ float coords[] = new float[6];
364+ while (!pi.isDone()) {
365+ switch (pi.currentSegment(coords)) {
366+ case PathIterator.SEG_MOVETO:
367+ consumer.moveTo(coords[0], coords[1]);
368+ break;
369+ case PathIterator.SEG_LINETO:
370+ consumer.lineTo(coords[0], coords[1]);
371+ break;
372+ case PathIterator.SEG_QUADTO:
373+ consumer.quadTo(coords[0], coords[1],
374+ coords[2], coords[3]);
375+ break;
376+ case PathIterator.SEG_CUBICTO:
377+ consumer.curveTo(coords[0], coords[1],
378+ coords[2], coords[3],
379+ coords[4], coords[5]);
380+ break;
381+ case PathIterator.SEG_CLOSE:
382+ consumer.closePath();
383+ break;
384+ }
385+ pi.next();
386+ }
387+ }
388+
389+ static class Tracer extends RenderingEngine {
390+ RenderingEngine target;
391+ String name;
392+
393+ public Tracer(RenderingEngine target) {
394+ this.target = target;
395+ name = target.getClass().getName();
396+ }
397+
398+ public Shape createStrokedShape(Shape src,
399+ float width,
400+ int caps,
401+ int join,
402+ float miterlimit,
403+ float dashes[],
404+ float dashphase)
405+ {
406+ System.out.println(name+".createStrokedShape("+
407+ src.getClass().getName()+", "+
408+ "width = "+width+", "+
409+ "caps = "+caps+", "+
410+ "join = "+join+", "+
411+ "miter = "+miterlimit+", "+
412+ "dashes = "+dashes+", "+
413+ "dashphase = "+dashphase+")");
414+ return target.createStrokedShape(src,
415+ width, caps, join, miterlimit,
416+ dashes, dashphase);
417+ }
418+
419+ public void strokeTo(Shape src,
420+ AffineTransform at,
421+ BasicStroke bs,
422+ boolean thin,
423+ boolean normalize,
424+ boolean antialias,
425+ PathConsumer2D consumer)
426+ {
427+ System.out.println(name+".strokeTo("+
428+ src.getClass().getName()+", "+
429+ at+", "+
430+ bs+", "+
431+ (thin ? "thin" : "wide")+", "+
432+ (normalize ? "normalized" : "pure")+", "+
433+ (antialias ? "AA" : "non-AA")+", "+
434+ consumer.getClass().getName()+")");
435+ target.strokeTo(src, at, bs, thin, normalize, antialias, consumer);
436+ }
437+
438+ public float getMinimumAAPenSize() {
439+ System.out.println(name+".getMinimumAAPenSize()");
440+ return target.getMinimumAAPenSize();
441+ }
442+
443+ public AATileGenerator getAATileGenerator(Shape s,
444+ AffineTransform at,
445+ Region clip,
446+ BasicStroke bs,
447+ boolean thin,
448+ boolean normalize,
449+ int bbox[])
450+ {
451+ System.out.println(name+".getAATileGenerator("+
452+ s.getClass().getName()+", "+
453+ at+", "+
454+ clip+", "+
455+ bs+", "+
456+ (thin ? "thin" : "wide")+", "+
457+ (normalize ? "normalized" : "pure")+")");
458+ return target.getAATileGenerator(s, at, clip,
459+ bs, thin, normalize,
460+ bbox);
461+ }
462+ public AATileGenerator getAATileGenerator(double x, double y,
463+ double dx1, double dy1,
464+ double dx2, double dy2,
465+ double lw1, double lw2,
466+ Region clip,
467+ int bbox[])
468+ {
469+ System.out.println(name+".getAATileGenerator("+
470+ x+", "+y+", "+
471+ dx1+", "+dy1+", "+
472+ dx2+", "+dy2+", "+
473+ lw1+", "+lw2+", "+
474+ clip+")");
475+ return target.getAATileGenerator(x, y,
476+ dx1, dy1,
477+ dx2, dy2,
478+ lw1, lw2,
479+ clip, bbox);
480+ }
481+ }
482+}
java/pkg/sun/java2d/pipe/ShapeDrawPipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/ShapeDrawPipe.java+40−0
@@ -0,0 +1,40 @@
1+/*
2+ * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Shape;
29+import sun.java2d.SunGraphics2D;
30+
31+/**
32+ * This interface defines the set of calls that pipeline objects
33+ * can use to pass on responsibility for drawing generic Shape
34+ * objects.
35+ */
36+public interface ShapeDrawPipe {
37+ public void draw(SunGraphics2D sg, Shape s);
38+
39+ public void fill(SunGraphics2D sg, Shape s);
40+}
java/pkg/sun/java2d/pipe/ShapeSpanIterator.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/ShapeSpanIterator.java+201−0
@@ -0,0 +1,201 @@
1+/*
2+ * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.geom.PathIterator;
29+import java.awt.Rectangle;
30+import sun.awt.geom.PathConsumer2D;
31+
32+/**
33+ * This class can iterate individual span elements generated by scan
34+ * converting a Shape.
35+ * This particular implementation flattens the incoming path and then
36+ * performs simple polygon tracing to calculate the spans.
37+ *
38+ * Note that this class holds pointers to native data which must be
39+ * disposed. It is not marked as finalizable since it is intended
40+ * to be very lightweight and finalization is a comparitively expensive
41+ * procedure. The caller must specifically use try{} finally{} to
42+ * manually ensure that the object is disposed after use, otherwise
43+ * native data structures might be leaked.
44+ *
45+ * Here is a code sample for using this class:
46+ *
47+ * public void fillShape(Shape s, Rectangle clipRect) {
48+ * ShapeSpanIterator ssi = new ShapeSpanIterator(false);
49+ * try {
50+ * ssi.setOutputArea(clipRect);
51+ * ssi.appendPath(s.getPathIterator(null));
52+ * int spanbox[] = new int[4];
53+ * while (ssi.nextSpan(spanbox)) {
54+ * int x = spanbox[0];
55+ * int y = spanbox[1];
56+ * int w = spanbox[2] - x;
57+ * int h = spanbox[3] - y;
58+ * fillRect(x, y, w, h);
59+ * }
60+ * } finally {
61+ * ssi.dispose();
62+ * }
63+ * }
64+ */
65+public final class ShapeSpanIterator
66+ implements SpanIterator, PathConsumer2D
67+{
68+ long pData;
69+
70+ static {
71+ initIDs();
72+ }
73+
74+ public static native void initIDs();
75+
76+ public ShapeSpanIterator(boolean adjust) {
77+ setNormalize(adjust);
78+ }
79+
80+ /*
81+ * Appends the geometry and winding rule from the indicated
82+ * path iterator.
83+ */
84+ public void appendPath(PathIterator pi) {
85+ float coords[] = new float[6];
86+
87+ setRule(pi.getWindingRule());
88+ while (!pi.isDone()) {
89+ addSegment(pi.currentSegment(coords), coords);
90+ pi.next();
91+ }
92+ pathDone();
93+ }
94+
95+ /*
96+ * Appends the geometry from the indicated set of polygon points.
97+ */
98+ public native void appendPoly(int xPoints[], int yPoints[], int nPoints,
99+ int xoff, int yoff);
100+
101+ /*
102+ * Sets the normalization flag so that incoming data is
103+ * adjusted to nearest (0.25, 0.25) subpixel position.
104+ */
105+ private native void setNormalize(boolean adjust);
106+
107+ /*
108+ * Sets the rectangle of interest for storing and returning
109+ * span segments.
110+ */
111+ public void setOutputAreaXYWH(int x, int y, int w, int h) {
112+ setOutputAreaXYXY(x, y, Region.dimAdd(x, w), Region.dimAdd(y, h));
113+ }
114+
115+ /*
116+ * Sets the rectangle of interest for storing and returning
117+ * span segments.
118+ */
119+ public native void setOutputAreaXYXY(int lox, int loy, int hix, int hiy);
120+
121+ /*
122+ * Sets the rectangle of interest for storing and returning
123+ * span segments to the specified Rectangle.
124+ */
125+ public void setOutputArea(Rectangle r) {
126+ setOutputAreaXYWH(r.x, r.y, r.width, r.height);
127+ }
128+
129+ /*
130+ * Sets the rectangle of interest for storing and returning
131+ * span segments to the bounds of the specified Region.
132+ */
133+ public void setOutputArea(Region r) {
134+ setOutputAreaXYXY(r.lox, r.loy, r.hix, r.hiy);
135+ }
136+
137+ /*
138+ * Sets the winding rule in the native data structures.
139+ */
140+ public native void setRule(int rule);
141+
142+ /*
143+ * Adds a single PathIterator segment to the internal list of
144+ * path element structures.
145+ */
146+ public native void addSegment(int type, float coords[]);
147+
148+ /*
149+ * Gets the bbox of the available path segments, clipped to the
150+ * OutputArea.
151+ */
152+ public native void getPathBox(int pathbox[]);
153+
154+ /*
155+ * Intersects the path box with the given bbox.
156+ * Returned spans are clipped to this region, or discarded
157+ * altogether if they lie outside it.
158+ */
159+ public native void intersectClipBox(int lox, int loy, int hix, int hiy);
160+
161+ /*
162+ * Fetches the next span that needs to be operated on.
163+ * If the return value is false then there are no more spans.
164+ */
165+ public native boolean nextSpan(int spanbox[]);
166+
167+ /**
168+ * This method tells the iterator that it may skip all spans
169+ * whose Y range is completely above the indicated Y coordinate.
170+ */
171+ public native void skipDownTo(int y);
172+
173+ /**
174+ * This method returns a native pointer to a function block that
175+ * can be used by a native method to perform the same iteration
176+ * cycle that the above methods provide while avoiding upcalls to
177+ * the Java object.
178+ * The definition of the structure whose pointer is returned by
179+ * this method is defined in:
180+ * <pre>
181+ * src/share/native/sun/java2d/pipe/SpanIterator.h
182+ * </pre>
183+ */
184+ public native long getNativeIterator();
185+
186+ /*
187+ * Cleans out all internal data structures.
188+ */
189+ public native void dispose();
190+
191+ public native void moveTo(float x, float y);
192+ public native void lineTo(float x, float y);
193+ public native void quadTo(float x1, float y1,
194+ float x2, float y2);
195+ public native void curveTo(float x1, float y1,
196+ float x2, float y2,
197+ float x3, float y3);
198+ public native void closePath();
199+ public native void pathDone();
200+ public native long getNativeConsumer();
201+}
java/pkg/sun/java2d/pipe/SolidTextRenderer.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/SolidTextRenderer.java+44−0
@@ -0,0 +1,44 @@
1+/*
2+ * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.font.GlyphVector;
29+import sun.awt.SunHints;
30+import sun.java2d.SunGraphics2D;
31+import sun.font.GlyphList;
32+
33+/**
34+ * A delegate pipe of SG2D for drawing text with
35+ * a solid source colour to an opaque destination.
36+ */
37+
38+public class SolidTextRenderer extends GlyphListLoopPipe
39+ implements LoopBasedPipe
40+{
41+ protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
42+ sg2d.loops.drawGlyphListLoop.DrawGlyphList(sg2d, sg2d.surfaceData, gl);
43+ }
44+}
java/pkg/sun/java2d/pipe/SpanClipRenderer$SCRcontext.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/SpanClipRenderer.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/SpanClipRenderer.java+141−0
@@ -0,0 +1,141 @@
1+/*
2+ * Copyright (c) 1998, 1999, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Rectangle;
29+import java.awt.Shape;
30+import java.awt.geom.PathIterator;
31+import sun.java2d.SunGraphics2D;
32+
33+/**
34+ * This class uses a Region iterator to modify the extents of alpha
35+ * tiles created during Shape rendering based upon a non-rectangular
36+ * clipping path.
37+ */
38+public class SpanClipRenderer implements CompositePipe
39+{
40+ CompositePipe outpipe;
41+
42+ static Class RegionClass = Region.class;
43+ static Class RegionIteratorClass = RegionIterator.class;
44+
45+ static {
46+ initIDs(RegionClass, RegionIteratorClass);
47+ }
48+
49+ static native void initIDs(Class rc, Class ric);
50+
51+ public SpanClipRenderer(CompositePipe pipe) {
52+ outpipe = pipe;
53+ }
54+
55+ class SCRcontext {
56+ RegionIterator iterator;
57+ Object outcontext;
58+ int band[];
59+ byte tile[];
60+
61+ public SCRcontext(RegionIterator ri, Object outctx) {
62+ iterator = ri;
63+ outcontext = outctx;
64+ band = new int[4];
65+ }
66+ }
67+
68+ public Object startSequence(SunGraphics2D sg, Shape s, Rectangle devR,
69+ int[] abox) {
70+ RegionIterator ri = sg.clipRegion.getIterator();
71+
72+ return new SCRcontext(ri, outpipe.startSequence(sg, s, devR, abox));
73+ }
74+
75+ public boolean needTile(Object ctx, int x, int y, int w, int h) {
76+ SCRcontext context = (SCRcontext) ctx;
77+ return (outpipe.needTile(context.outcontext, x, y, w, h));
78+ }
79+
80+ public void renderPathTile(Object ctx,
81+ byte[] atile, int offset, int tsize,
82+ int x, int y, int w, int h,
83+ ShapeSpanIterator sr) {
84+ renderPathTile(ctx, atile, offset, tsize, x, y, w, h);
85+ }
86+
87+ public void renderPathTile(Object ctx,
88+ byte[] atile, int offset, int tsize,
89+ int x, int y, int w, int h) {
90+ SCRcontext context = (SCRcontext) ctx;
91+ RegionIterator ri = context.iterator.createCopy();
92+ int[] band = context.band;
93+ band[0] = x;
94+ band[1] = y;
95+ band[2] = x + w;
96+ band[3] = y + h;
97+ if (atile == null) {
98+ int size = w * h;
99+ atile = context.tile;
100+ if (atile != null && atile.length < size) {
101+ atile = null;
102+ }
103+ if (atile == null) {
104+ atile = new byte[size];
105+ context.tile = atile;
106+ }
107+ offset = 0;
108+ tsize = w;
109+ fillTile(ri, atile, offset, tsize, band);
110+ } else {
111+ eraseTile(ri, atile, offset, tsize, band);
112+ }
113+
114+ if (band[2] > band[0] && band[3] > band[1]) {
115+ offset += (band[1] - y) * tsize + (band[0] - x);
116+ outpipe.renderPathTile(context.outcontext,
117+ atile, offset, tsize,
118+ band[0], band[1],
119+ band[2] - band[0],
120+ band[3] - band[1]);
121+ }
122+ }
123+
124+ public native void fillTile(RegionIterator ri,
125+ byte[] alpha, int offset, int tsize,
126+ int[] band);
127+
128+ public native void eraseTile(RegionIterator ri,
129+ byte[] alpha, int offset, int tsize,
130+ int[] band);
131+
132+ public void skipTile(Object ctx, int x, int y) {
133+ SCRcontext context = (SCRcontext) ctx;
134+ outpipe.skipTile(context.outcontext, x, y);
135+ }
136+
137+ public void endSequence(Object ctx) {
138+ SCRcontext context = (SCRcontext) ctx;
139+ outpipe.endSequence(context.outcontext);
140+ }
141+}
java/pkg/sun/java2d/pipe/SpanIterator.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/SpanIterator.java+95−0
@@ -0,0 +1,95 @@
1+/*
2+ * Copyright (c) 1998, 1999, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+/**
29+ * This interface defines a general method for iterating through the
30+ * rectangular "spans" that represent the interior of a filled path.
31+ * <p>
32+ * There can be many kinds of span iterators used in the rendering
33+ * pipeline, the most basic being an iterator that scan converts a
34+ * path defined by any PathIterator, or an nested iterator which
35+ * intersects another iterator's spans with a clip region.
36+ * Other iterators can be created for scan converting some of the
37+ * primitive shapes more explicitly for speed or quality.
38+ *
39+ * @author Jim Graham
40+ */
41+public interface SpanIterator {
42+ /**
43+ * This method returns the bounding box of the spans that the
44+ * iterator will be returning.
45+ * The array must be of length at least 4 and upon return, it
46+ * will be filled with the values:
47+ * <pre>
48+ * {PathMinX, PathMinY, PathMaxX, PathMaxY}.
49+ * </pre>
50+ */
51+ public void getPathBox(int pathbox[]);
52+
53+ /**
54+ * This method constrains the spans returned by nextSpan() to the
55+ * rectangle whose bounds are given.
56+ */
57+ public void intersectClipBox(int lox, int loy, int hix, int hiy);
58+
59+ /**
60+ * This method returns the next span in the shape being iterated.
61+ * The array must be of length at least 4 and upon return, it
62+ * will be filled with the values:
63+ * <pre>
64+ * {SpanMinX, SpanMinY, SpanMaxX, SpanMaxY}.
65+ * </pre>
66+ */
67+ public boolean nextSpan(int spanbox[]);
68+
69+ /**
70+ * This method tells the iterator that it may skip all spans
71+ * whose Y range is completely above the indicated Y coordinate.
72+ * This method is used to provide feedback from the caller when
73+ * clipping prevents the display of any data in a given Y range.
74+ * Typically it will only be called when this iterator has returned
75+ * a span whose MaxY coordinate is less than the indicated Y and
76+ * the calling mechanism wants to avoid unnecessary iteration work.
77+ * While this request could technically be ignored (i.e. a NOP),
78+ * doing so could potentially cause the caller to make this callback
79+ * for each span that is being skipped.
80+ */
81+ public void skipDownTo(int y);
82+
83+ /**
84+ * This method returns a native pointer to a function block that
85+ * can be used by a native method to perform the same iteration
86+ * cycle that the above methods provide while avoiding upcalls to
87+ * the Java object.
88+ * The definition of the structure whose pointer is returned by
89+ * this method is defined in:
90+ * <pre>
91+ * src/share/native/sun/java2d/pipe/SpanIterator.h
92+ * </pre>
93+ */
94+ public long getNativeIterator();
95+}
java/pkg/sun/java2d/pipe/SpanShapeRenderer$Composite.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/SpanShapeRenderer$Simple.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/SpanShapeRenderer.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/SpanShapeRenderer.java+216−0
@@ -0,0 +1,216 @@
1+/*
2+ * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import sun.java2d.SunGraphics2D;
29+import sun.java2d.SurfaceData;
30+import java.awt.Rectangle;
31+import java.awt.Shape;
32+import java.awt.BasicStroke;
33+import java.awt.geom.PathIterator;
34+import java.awt.geom.AffineTransform;
35+import java.awt.geom.Rectangle2D;
36+import sun.awt.SunHints;
37+
38+/**
39+ * This class is used to convert raw geometry into a span iterator
40+ * object using a simple flattening polygon scan converter.
41+ * The iterator can be passed on to special SpanFiller loops to
42+ * perform the actual rendering.
43+ */
44+public abstract class SpanShapeRenderer implements ShapeDrawPipe {
45+ final static RenderingEngine RenderEngine = RenderingEngine.getInstance();
46+
47+ public static class Composite extends SpanShapeRenderer {
48+ CompositePipe comppipe;
49+
50+ public Composite(CompositePipe pipe) {
51+ comppipe = pipe;
52+ }
53+
54+ public Object startSequence(SunGraphics2D sg, Shape s,
55+ Rectangle devR, int[] bbox) {
56+ return comppipe.startSequence(sg, s, devR, bbox);
57+ }
58+
59+ public void renderBox(Object ctx, int x, int y, int w, int h) {
60+ comppipe.renderPathTile(ctx, null, 0, w, x, y, w, h);
61+ }
62+
63+ public void endSequence(Object ctx) {
64+ comppipe.endSequence(ctx);
65+ }
66+ }
67+
68+ public static class Simple extends SpanShapeRenderer
69+ implements LoopBasedPipe
70+ {
71+ public Object startSequence(SunGraphics2D sg, Shape s,
72+ Rectangle devR, int[] bbox) {
73+ return sg;
74+ }
75+
76+ public void renderBox(Object ctx, int x, int y, int w, int h) {
77+ SunGraphics2D sg2d = (SunGraphics2D) ctx;
78+ SurfaceData sd = sg2d.getSurfaceData();
79+ sg2d.loops.fillRectLoop.FillRect(sg2d, sd, x, y, w, h);
80+ }
81+
82+ public void endSequence(Object ctx) {
83+ }
84+ }
85+
86+ public void draw(SunGraphics2D sg, Shape s) {
87+ if (sg.stroke instanceof BasicStroke) {
88+ ShapeSpanIterator sr = LoopPipe.getStrokeSpans(sg, s);
89+ try {
90+ renderSpans(sg, sg.getCompClip(), s, sr);
91+ } finally {
92+ sr.dispose();
93+ }
94+ } else {
95+ fill(sg, sg.stroke.createStrokedShape(s));
96+ }
97+ }
98+
99+ public static final int NON_RECTILINEAR_TRANSFORM_MASK =
100+ (AffineTransform.TYPE_GENERAL_TRANSFORM |
101+ AffineTransform.TYPE_GENERAL_ROTATION);
102+
103+ public void fill(SunGraphics2D sg, Shape s) {
104+ if (s instanceof Rectangle2D &&
105+ (sg.transform.getType() & NON_RECTILINEAR_TRANSFORM_MASK) == 0)
106+ {
107+ renderRect(sg, (Rectangle2D) s);
108+ return;
109+ }
110+
111+ Region clipRegion = sg.getCompClip();
112+ ShapeSpanIterator sr = LoopPipe.getFillSSI(sg);
113+ try {
114+ sr.setOutputArea(clipRegion);
115+ sr.appendPath(s.getPathIterator(sg.transform));
116+ renderSpans(sg, clipRegion, s, sr);
117+ } finally {
118+ sr.dispose();
119+ }
120+ }
121+
122+ public abstract Object startSequence(SunGraphics2D sg, Shape s,
123+ Rectangle devR, int[] bbox);
124+
125+ public abstract void renderBox(Object ctx, int x, int y, int w, int h);
126+
127+ public abstract void endSequence(Object ctx);
128+
129+ public void renderRect(SunGraphics2D sg, Rectangle2D r) {
130+ double corners[] = {
131+ r.getX(), r.getY(), r.getWidth(), r.getHeight(),
132+ };
133+ corners[2] += corners[0];
134+ corners[3] += corners[1];
135+ if (corners[2] <= corners[0] || corners[3] <= corners[1]) {
136+ return;
137+ }
138+ sg.transform.transform(corners, 0, corners, 0, 2);
139+ if (corners[2] < corners[0]) {
140+ double t = corners[2];
141+ corners[2] = corners[0];
142+ corners[0] = t;
143+ }
144+ if (corners[3] < corners[1]) {
145+ double t = corners[3];
146+ corners[3] = corners[1];
147+ corners[1] = t;
148+ }
149+ int abox[] = {
150+ (int) corners[0],
151+ (int) corners[1],
152+ (int) corners[2],
153+ (int) corners[3],
154+ };
155+ Rectangle devR = new Rectangle(abox[0], abox[1],
156+ abox[2] - abox[0],
157+ abox[3] - abox[1]);
158+ Region clipRegion = sg.getCompClip();
159+ clipRegion.clipBoxToBounds(abox);
160+ if (abox[0] >= abox[2] || abox[1] >= abox[3]) {
161+ return;
162+ }
163+ Object context = startSequence(sg, r, devR, abox);
164+ if (clipRegion.isRectangular()) {
165+ renderBox(context, abox[0], abox[1],
166+ abox[2] - abox[0],
167+ abox[3] - abox[1]);
168+ } else {
169+ SpanIterator sr = clipRegion.getSpanIterator(abox);
170+ while (sr.nextSpan(abox)) {
171+ renderBox(context, abox[0], abox[1],
172+ abox[2] - abox[0],
173+ abox[3] - abox[1]);
174+ }
175+ }
176+ endSequence(context);
177+ }
178+
179+ public void renderSpans(SunGraphics2D sg, Region clipRegion, Shape s,
180+ ShapeSpanIterator sr)
181+ {
182+ Object context = null;
183+ int abox[] = new int[4];
184+ try {
185+ sr.getPathBox(abox);
186+ Rectangle devR = new Rectangle(abox[0], abox[1],
187+ abox[2] - abox[0],
188+ abox[3] - abox[1]);
189+ clipRegion.clipBoxToBounds(abox);
190+ if (abox[0] >= abox[2] || abox[1] >= abox[3]) {
191+ return;
192+ }
193+ sr.intersectClipBox(abox[0], abox[1], abox[2], abox[3]);
194+ context = startSequence(sg, s, devR, abox);
195+
196+ spanClipLoop(context, sr, clipRegion, abox);
197+
198+ } finally {
199+ if (context != null) {
200+ endSequence(context);
201+ }
202+ }
203+ }
204+
205+ public void spanClipLoop(Object ctx, SpanIterator sr,
206+ Region r, int[] abox) {
207+ if (!r.isRectangular()) {
208+ sr = r.filter(sr);
209+ }
210+ while (sr.nextSpan(abox)) {
211+ int x = abox[0];
212+ int y = abox[1];
213+ renderBox(ctx, x, y, abox[2] - x, abox[3] - y);
214+ }
215+ }
216+}
java/pkg/sun/java2d/pipe/TextPipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/TextPipe.java+49−0
@@ -0,0 +1,49 @@
1+/*
2+ * Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+/*
27+ * @author Charlton Innovations, Inc.
28+ */
29+
30+package sun.java2d.pipe;
31+
32+import sun.java2d.SunGraphics2D;
33+import java.awt.font.GlyphVector;
34+import java.awt.font.TextLayout;
35+
36+/**
37+ * This interface defines the set of calls that pipeline objects
38+ * can use to pass on responsibility for drawing various text
39+ * representations.
40+ */
41+public interface TextPipe {
42+ public void drawString(SunGraphics2D g2d, String s,
43+ double x, double y);
44+ public void drawGlyphVector(SunGraphics2D g2d, GlyphVector g,
45+ float x, float y);
46+ public void drawChars(SunGraphics2D g2d,
47+ char data[], int offset, int length,
48+ int x, int y);
49+}
java/pkg/sun/java2d/pipe/TextRenderer.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/TextRenderer.java+98−0
@@ -0,0 +1,98 @@
1+/*
2+ * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Rectangle;
29+import java.awt.Shape;
30+import java.awt.Font;
31+import java.awt.font.GlyphVector;
32+import sun.java2d.SunGraphics2D;
33+import sun.java2d.loops.FontInfo;
34+import sun.font.GlyphList;
35+
36+/*
37+ * This class uses the alpha graybits arrays from a GlyphList object to
38+ * drive a CompositePipe in much the same way as the antialiasing renderer.
39+ */
40+public class TextRenderer extends GlyphListPipe {
41+
42+ CompositePipe outpipe;
43+
44+ public TextRenderer(CompositePipe pipe) {
45+ outpipe = pipe;
46+ }
47+
48+ protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
49+ int num = gl.getNumGlyphs();
50+ Region clipRegion = sg2d.getCompClip();
51+ int cx1 = clipRegion.getLoX();
52+ int cy1 = clipRegion.getLoY();
53+ int cx2 = clipRegion.getHiX();
54+ int cy2 = clipRegion.getHiY();
55+ Object ctx = null;
56+ try {
57+ int[] bounds = gl.getBounds();
58+ Rectangle r = new Rectangle(bounds[0], bounds[1],
59+ bounds[2] - bounds[0],
60+ bounds[3] - bounds[1]);
61+ Shape s = sg2d.untransformShape(r);
62+ ctx = outpipe.startSequence(sg2d, s, r, bounds);
63+ for (int i = 0; i < num; i++) {
64+ gl.setGlyphIndex(i);
65+ int metrics[] = gl.getMetrics();
66+ int gx1 = metrics[0];
67+ int gy1 = metrics[1];
68+ int w = metrics[2];
69+ int gx2 = gx1 + w;
70+ int gy2 = gy1 + metrics[3];
71+ int off = 0;
72+ if (gx1 < cx1) {
73+ off = cx1 - gx1;
74+ gx1 = cx1;
75+ }
76+ if (gy1 < cy1) {
77+ off += (cy1 - gy1) * w;
78+ gy1 = cy1;
79+ }
80+ if (gx2 > cx2) gx2 = cx2;
81+ if (gy2 > cy2) gy2 = cy2;
82+ if (gx2 > gx1 && gy2 > gy1 &&
83+ outpipe.needTile(ctx, gx1, gy1, gx2 - gx1, gy2 - gy1))
84+ {
85+ byte alpha[] = gl.getGrayBits();
86+ outpipe.renderPathTile(ctx, alpha, off, w,
87+ gx1, gy1, gx2 - gx1, gy2 - gy1);
88+ } else {
89+ outpipe.skipTile(ctx, gx1, gy1);
90+ }
91+ }
92+ } finally {
93+ if (ctx != null) {
94+ outpipe.endSequence(ctx);
95+ }
96+ }
97+ }
98+}
java/pkg/sun/java2d/pipe/ValidatePipe.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/ValidatePipe.java+241−0
@@ -0,0 +1,241 @@
1+/*
2+ * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe;
27+
28+import java.awt.Color;
29+import java.awt.Image;
30+import java.awt.Shape;
31+import java.awt.geom.AffineTransform;
32+import java.awt.image.BufferedImage;
33+import java.awt.image.BufferedImageOp;
34+import java.awt.image.ImageObserver;
35+import sun.java2d.SunGraphics2D;
36+import java.awt.font.GlyphVector;
37+
38+/**
39+ * This class is used to force a revalidation of the pipelines of
40+ * the indicated SunGraphics2D object before a draw command.
41+ * After calling SunGraphics2D.validatePipe() to force the pipeline
42+ * to be revalidated, this object redispatches the draw command to
43+ * the new valid pipe object.
44+ */
45+public class ValidatePipe
46+ implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe, TextPipe,
47+ DrawImagePipe
48+{
49+ /*
50+ * Different subclasses may override this to do various
51+ * other forms of validation and return a return code
52+ * indicating whether or not the validation was successful.
53+ */
54+ public boolean validate(SunGraphics2D sg) {
55+ sg.validatePipe();
56+ return true;
57+ }
58+
59+ public void drawLine(SunGraphics2D sg,
60+ int x1, int y1, int x2, int y2) {
61+ if (validate(sg)) {
62+ sg.drawpipe.drawLine(sg, x1, y1, x2, y2);
63+ }
64+ }
65+
66+ public void drawRect(SunGraphics2D sg,
67+ int x, int y, int width, int height) {
68+ if (validate(sg)) {
69+ sg.drawpipe.drawRect(sg, x, y, width, height);
70+ }
71+ }
72+
73+ public void fillRect(SunGraphics2D sg,
74+ int x, int y, int width, int height) {
75+ if (validate(sg)) {
76+ sg.fillpipe.fillRect(sg, x, y, width, height);
77+ }
78+ }
79+
80+ public void drawRoundRect(SunGraphics2D sg,
81+ int x, int y, int width, int height,
82+ int arcWidth, int arcHeight) {
83+ if (validate(sg)) {
84+ sg.drawpipe.drawRoundRect(sg, x, y, width, height,
85+ arcWidth, arcHeight);
86+ }
87+ }
88+
89+ public void fillRoundRect(SunGraphics2D sg,
90+ int x, int y, int width, int height,
91+ int arcWidth, int arcHeight) {
92+ if (validate(sg)) {
93+ sg.fillpipe.fillRoundRect(sg, x, y, width, height,
94+ arcWidth, arcHeight);
95+ }
96+ }
97+
98+ public void drawOval(SunGraphics2D sg,
99+ int x, int y, int width, int height) {
100+ if (validate(sg)) {
101+ sg.drawpipe.drawOval(sg, x, y, width, height);
102+ }
103+ }
104+
105+ public void fillOval(SunGraphics2D sg,
106+ int x, int y, int width, int height) {
107+ if (validate(sg)) {
108+ sg.fillpipe.fillOval(sg, x, y, width, height);
109+ }
110+ }
111+
112+ public void drawArc(SunGraphics2D sg,
113+ int x, int y, int width, int height,
114+ int startAngle, int arcAngle) {
115+ if (validate(sg)) {
116+ sg.drawpipe.drawArc(sg, x, y, width, height, startAngle, arcAngle);
117+ }
118+ }
119+
120+ public void fillArc(SunGraphics2D sg,
121+ int x, int y, int width, int height,
122+ int startAngle, int arcAngle) {
123+ if (validate(sg)) {
124+ sg.fillpipe.fillArc(sg, x, y, width, height, startAngle, arcAngle);
125+ }
126+ }
127+
128+ public void drawPolyline(SunGraphics2D sg,
129+ int xPoints[], int yPoints[],
130+ int nPoints) {
131+ if (validate(sg)) {
132+ sg.drawpipe.drawPolyline(sg, xPoints, yPoints, nPoints);
133+ }
134+ }
135+
136+ public void drawPolygon(SunGraphics2D sg,
137+ int xPoints[], int yPoints[],
138+ int nPoints) {
139+ if (validate(sg)) {
140+ sg.drawpipe.drawPolygon(sg, xPoints, yPoints, nPoints);
141+ }
142+ }
143+
144+ public void fillPolygon(SunGraphics2D sg,
145+ int xPoints[], int yPoints[],
146+ int nPoints) {
147+ if (validate(sg)) {
148+ sg.fillpipe.fillPolygon(sg, xPoints, yPoints, nPoints);
149+ }
150+ }
151+
152+ public void draw(SunGraphics2D sg, Shape s) {
153+ if (validate(sg)) {
154+ sg.shapepipe.draw(sg, s);
155+ }
156+ }
157+
158+ public void fill(SunGraphics2D sg, Shape s) {
159+ if (validate(sg)) {
160+ sg.shapepipe.fill(sg, s);
161+ }
162+ }
163+ public void drawString(SunGraphics2D sg, String s, double x, double y) {
164+ if (validate(sg)) {
165+ sg.textpipe.drawString(sg, s, x, y);
166+ }
167+ }
168+ public void drawGlyphVector(SunGraphics2D sg, GlyphVector g,
169+ float x, float y) {
170+ if (validate(sg)) {
171+ sg.textpipe.drawGlyphVector(sg, g, x, y);
172+ }
173+ }
174+ public void drawChars(SunGraphics2D sg,
175+ char data[], int offset, int length,
176+ int x, int y) {
177+ if (validate(sg)) {
178+ sg.textpipe.drawChars(sg, data, offset, length, x, y);
179+ }
180+ }
181+ public boolean copyImage(SunGraphics2D sg, Image img,
182+ int x, int y,
183+ Color bgColor,
184+ ImageObserver observer) {
185+ if (validate(sg)) {
186+ return sg.imagepipe.copyImage(sg, img, x, y, bgColor, observer);
187+ } else {
188+ return false;
189+ }
190+ }
191+ public boolean copyImage(SunGraphics2D sg, Image img,
192+ int dx, int dy, int sx, int sy, int w, int h,
193+ Color bgColor,
194+ ImageObserver observer) {
195+ if (validate(sg)) {
196+ return sg.imagepipe.copyImage(sg, img, dx, dy, sx, sy, w, h,
197+ bgColor, observer);
198+ } else {
199+ return false;
200+ }
201+ }
202+ public boolean scaleImage(SunGraphics2D sg, Image img, int x, int y,
203+ int w, int h,
204+ Color bgColor,
205+ ImageObserver observer) {
206+ if (validate(sg)) {
207+ return sg.imagepipe.scaleImage(sg, img, x, y, w, h, bgColor,
208+ observer);
209+ } else {
210+ return false;
211+ }
212+ }
213+ public boolean scaleImage(SunGraphics2D sg, Image img,
214+ int dx1, int dy1, int dx2, int dy2,
215+ int sx1, int sy1, int sx2, int sy2,
216+ Color bgColor,
217+ ImageObserver observer) {
218+ if (validate(sg)) {
219+ return sg.imagepipe.scaleImage(sg, img, dx1, dy1, dx2, dy2,
220+ sx1, sy1, sx2, sy2, bgColor,
221+ observer);
222+ } else {
223+ return false;
224+ }
225+ }
226+ public boolean transformImage(SunGraphics2D sg, Image img,
227+ AffineTransform atfm,
228+ ImageObserver observer) {
229+ if (validate(sg)) {
230+ return sg.imagepipe.transformImage(sg, img, atfm, observer);
231+ } else {
232+ return false;
233+ }
234+ }
235+ public void transformImage(SunGraphics2D sg, BufferedImage img,
236+ BufferedImageOp op, int x, int y) {
237+ if (validate(sg)) {
238+ sg.imagepipe.transformImage(sg, img, op, x, y);
239+ }
240+ }
241+}
java/pkg/sun/java2d/pipe/hw/AccelDeviceEventListener.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/hw/AccelDeviceEventListener.java+59−0
@@ -0,0 +1,59 @@
1+/*
2+ * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe.hw;
27+
28+/**
29+ * An interface for receiving notifications about imminent accelerated device's
30+ * events. Upon receiving such event appropriate actions can be taken (for
31+ * example, resources associated with the device can be freed).
32+ */
33+public interface AccelDeviceEventListener {
34+ /**
35+ * Called when the device is about to be reset.
36+ *
37+ * One must release all native resources associated with the device which
38+ * prevent the device from being reset (such as Default Pool resources for
39+ * the D3D pipeline).
40+ *
41+ * It is safe to remove the listener while in the call back.
42+ *
43+ * Note: this method is called on the rendering thread,
44+ * do not call into user code, do not take RQ lock!
45+ */
46+ public void onDeviceReset();
47+
48+ /**
49+ * Called when the device is about to be disposed of.
50+ *
51+ * One must release all native resources associated with the device.
52+ *
53+ * It is safe to remove the listener while in the call back.
54+ *
55+ * Note: this method is called on the rendering thread,
56+ * do not call into user code, do not take RQ lock!
57+ */
58+ public void onDeviceDispose();
59+}
java/pkg/sun/java2d/pipe/hw/AccelDeviceEventNotifier.java+167−0
@@ -0,0 +1,167 @@
1+/*
2+ * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe.hw;
27+
28+import java.util.Collections;
29+import java.util.HashMap;
30+import java.util.Iterator;
31+import java.util.Map;
32+import java.util.Set;
33+
34+/**
35+ * This class is used to notify listeners about accelerated device's
36+ * events such as device reset or dispose that are about to occur.
37+ */
38+public class AccelDeviceEventNotifier {
39+
40+ private static AccelDeviceEventNotifier theInstance;
41+
42+ /**
43+ * A device is about to be reset. The listeners have to release all
44+ * resources associated with the device which are required for the device
45+ * to be reset.
46+ */
47+ public static final int DEVICE_RESET = 0;
48+
49+ /**
50+ * A device is about to be disposed. The listeners have to release all
51+ * resources associated with the device.
52+ */
53+ public static final int DEVICE_DISPOSED = 1;
54+
55+ private final Map<AccelDeviceEventListener, Integer> listeners;
56+
57+ private AccelDeviceEventNotifier() {
58+ listeners = Collections.synchronizedMap(
59+ new HashMap<AccelDeviceEventListener, Integer>(1));
60+ }
61+
62+ /**
63+ * Returns a singleton of AccelDeviceEventNotifier if it exists. If the
64+ * passed boolean is false and singleton doesn't exist yet, null is
65+ * returned. If the passed boolean is {@code true} and singleton doesn't
66+ * exist it will be created and returned.
67+ *
68+ * @param create whether to create a singleton instance if doesn't yet
69+ * exist
70+ * @return a singleton instance or null
71+ */
72+ private static synchronized
73+ AccelDeviceEventNotifier getInstance(boolean create)
74+ {
75+ if (theInstance == null && create) {
76+ theInstance = new AccelDeviceEventNotifier();
77+ }
78+ return theInstance;
79+ }
80+
81+ /**
82+ * Called to indicate that a device event had occured.
83+ * If a singleton exists, the listeners (those associated with
84+ * the device) will be notified.
85+ *
86+ * @param screen a screen number of the device which is a source of
87+ * the event
88+ * @param eventType a type of the event
89+ * @see #DEVICE_DISPOSED
90+ * @see #DEVICE_RESET
91+ */
92+ public static final void eventOccured(int screen, int eventType) {
93+ AccelDeviceEventNotifier notifier = getInstance(false);
94+ if (notifier != null) {
95+ notifier.notifyListeners(eventType, screen);
96+ }
97+ }
98+
99+ /**
100+ * Adds the listener associated with a device on particular screen.
101+ *
102+ * Note: the listener must be removed as otherwise it will forever
103+ * be referenced by the notifier.
104+ *
105+ * @param l the listener
106+ * @param screen the screen number indicating which device the listener is
107+ * interested in.
108+ */
109+ public static final void addListener(AccelDeviceEventListener l,int screen){
110+ getInstance(true).add(l, screen);
111+ }
112+
113+ /**
114+ * Removes the listener.
115+ *
116+ * @param l the listener
117+ */
118+ public static final void removeListener(AccelDeviceEventListener l) {
119+ getInstance(true).remove(l);
120+ }
121+
122+ private final void add(AccelDeviceEventListener theListener, int screen) {
123+ listeners.put(theListener, screen);
124+ }
125+ private final void remove(AccelDeviceEventListener theListener) {
126+ listeners.remove(theListener);
127+ }
128+
129+ /**
130+ * Notifies the listeners associated with the screen's device about the
131+ * event.
132+ *
133+ * Implementation note: the current list of listeners is first duplicated
134+ * which allows the listeners to remove themselves during the iteration.
135+ *
136+ * @param screen a screen number with which the device which is a source of
137+ * the event is associated with
138+ * @param eventType a type of the event
139+ * @see #DEVICE_DISPOSED
140+ * @see #DEVICE_RESET
141+ */
142+ private final void notifyListeners(int deviceEventType, int screen) {
143+ HashMap<AccelDeviceEventListener, Integer> listClone;
144+ Set<AccelDeviceEventListener> cloneSet;
145+
146+ synchronized(listeners) {
147+ listClone =
148+ new HashMap<AccelDeviceEventListener, Integer>(listeners);
149+ }
150+
151+ cloneSet = listClone.keySet();
152+ Iterator<AccelDeviceEventListener> itr = cloneSet.iterator();
153+ while (itr.hasNext()) {
154+ AccelDeviceEventListener current = itr.next();
155+ Integer i = listClone.get(current);
156+ // only notify listeners which are interested in this device
157+ if (i != null && i.intValue() != screen) {
158+ continue;
159+ }
160+ if (deviceEventType == DEVICE_RESET) {
161+ current.onDeviceReset();
162+ } else if (deviceEventType == DEVICE_DISPOSED) {
163+ current.onDeviceDispose();
164+ }
165+ }
166+ }
167+}
java/pkg/sun/java2d/pipe/hw/AccelGraphicsConfig.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/hw/AccelGraphicsConfig.java+95−0
@@ -0,0 +1,95 @@
1+/*
2+ * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe.hw;
27+
28+import java.awt.image.VolatileImage;
29+
30+/**
31+ * Implementors of this interface provida a way to create a
32+ * {@code VolatileImage} whose destination surface is an
33+ * {@link AccelSurface} of specified type.
34+ *
35+ * @see AccelSurface
36+ */
37+public interface AccelGraphicsConfig extends BufferedContextProvider {
38+ /**
39+ * Returns a VolatileImage with specified width, height, transparency
40+ * and guaranteed accelerated surface type. If such image can not be created
41+ * (out of vram error, specific surface type is not supported) null
42+ * is returned.
43+ *
44+ * Note: if {@link AccelSurface#TEXTURE} type is requested, rendering
45+ * to the image will be denied by throwing
46+ * {@code UnsupportedOperationException }
47+ * from {@link java.awt.image.VolatileImage#getGraphics} and
48+ * {@link java.awt.image.VolatileImage#createGraphics}
49+ *
50+ * @param width the width of the returned {@code VolatileImage}
51+ * @param height the height of the returned {@code VolatileImage}
52+ * @param transparency the specified transparency mode
53+ * @param type requested accelerated surface type as specified by constants
54+ * in AccelSurface interface
55+ * @return a {@code VolatileImage} backed up by requested accelerated
56+ * surface type or null
57+ * @throws IllegalArgumentException if the transparency is not a valid value
58+ * @see AccelSurface#TEXTURE
59+ * @see AccelSurface#RT_PLAIN
60+ * @see AccelSurface#RT_TEXTURE
61+ */
62+ public VolatileImage createCompatibleVolatileImage(int width, int height,
63+ int transparency,
64+ int type);
65+ /**
66+ * Returns object representing capabilities of the context associated
67+ * with this {@code AccelGraphicsConfig}.
68+ *
69+ * @return ContextCapabilities object representing caps
70+ * @see ContextCapabilities
71+ */
72+ public ContextCapabilities getContextCapabilities();
73+
74+ /**
75+ * Adds an {@code AccelDeviceEventListener} to listen to accelerated
76+ * device's (which is associated with this {@code AccelGraphicsConfig})
77+ * events.
78+ *
79+ * Note: a hard link to the listener may be kept so it must be explicitly
80+ * removed via {@link #removeDeviceEventListener()}.
81+ *
82+ * @param l the listener
83+ * @see AccelDeviceEventListener
84+ */
85+ public void addDeviceEventListener(AccelDeviceEventListener l);
86+
87+ /**
88+ * Removes an {@code AccelDeviceEventListener} from the list of listeners
89+ * for this device's events.
90+ *
91+ * @param l the listener
92+ * @see AccelDeviceEventListener
93+ */
94+ public void removeDeviceEventListener(AccelDeviceEventListener l);
95+}
java/pkg/sun/java2d/pipe/hw/AccelSurface.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/hw/AccelSurface.java+136−0
@@ -0,0 +1,136 @@
1+/*
2+ * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe.hw;
27+
28+import java.awt.Rectangle;
29+import sun.java2d.Surface;
30+
31+/**
32+ * Abstraction for a hardware accelerated surface.
33+ */
34+public interface AccelSurface extends BufferedContextProvider, Surface {
35+ /**
36+ * Undefined
37+ */
38+ public static final int UNDEFINED = 0;
39+ /**
40+ * Window (or window substitute) surface
41+ */
42+ public static final int WINDOW = 1;
43+ /**
44+ * Render-To Plain surface (pbuffer for OpenGL, Render Target surface
45+ * for Direct3D)
46+ */
47+ public static final int RT_PLAIN = 2;
48+ /**
49+ * Texture surface
50+ */
51+ public static final int TEXTURE = 3;
52+ /**
53+ * A back-buffer surface (SwapChain surface for Direct3D, backbuffer for
54+ * OpenGL)
55+ */
56+ public static final int FLIP_BACKBUFFER = 4;
57+ /**
58+ * Render-To Texture surface (fbobject for OpenGL, texture with render-to
59+ * attribute for Direct3D)
60+ */
61+ public static final int RT_TEXTURE = 5;
62+
63+ /**
64+ * Returns {@code int} representing surface's type as defined by constants
65+ * in this interface.
66+ *
67+ * @return an integer representing this surface's type
68+ * @see AccelSurface#UNDEFINED
69+ * @see AccelSurface#WINDOW
70+ * @see AccelSurface#RT_PLAIN
71+ * @see AccelSurface#TEXTURE
72+ * @see AccelSurface#FLIP_BACKBUFFER
73+ * @see AccelSurface#RT_TEXTURE
74+ */
75+ public int getType();
76+
77+ /**
78+ * Returns a pointer to the native surface data associated with this
79+ * surface.
80+ * Note: this pointer is only valid on the rendering thread.
81+ *
82+ * @return pointer to the native surface's data
83+ */
84+ public long getNativeOps();
85+
86+ /**
87+ * Returns a pointer to the real native resource
88+ * of the specified type associated with this AccelSurface.
89+ * Note: this pointer is only valid on the rendering thread.
90+ *
91+ * @param resType the type of the requested resource
92+ * @return a long containing a pointer to the native resource of the
93+ * specified type or 0L if such resource doesn't exist for this surface
94+ */
95+ public long getNativeResource(int resType);
96+
97+ /**
98+ * Marks this surface dirty.
99+ */
100+ public void markDirty();
101+
102+ /**
103+ * Returns whether the pipeline considers this surface valid. A surface
104+ * may become invalid if it is disposed of, or resized.
105+ *
106+ * @return true if valid, false otherwise
107+ */
108+ public boolean isValid();
109+
110+ /**
111+ * Returns whether this surface is lost. The return value is only valid
112+ * on the render thread, meaning that even if this method returns
113+ * {@code true} it could be lost in the next moment unless it is called
114+ * on the rendering thread.
115+ *
116+ * @return true if the surface is known to be lost, false otherwise
117+ */
118+ public boolean isSurfaceLost();
119+
120+ /**
121+ * Returns the requested bounds of the destination surface. The real bounds
122+ * of the native accelerated surface may differ. Use
123+ * {@link #getNativeBounds} to get the bounds of the native surface.
124+ *
125+ * @return Rectangle representing java surface's bounds
126+ */
127+ public Rectangle getBounds();
128+
129+ /**
130+ * Returns real bounds of the native surface, which may differ from those
131+ * returned by {@link #getBounds}.
132+ *
133+ * @return Rectangle representing native surface's bounds
134+ */
135+ public Rectangle getNativeBounds();
136+}
java/pkg/sun/java2d/pipe/hw/AccelTypedVolatileImage.java+74−0
@@ -0,0 +1,74 @@
1+/*
2+ * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe.hw;
27+
28+import java.awt.Graphics;
29+import java.awt.Graphics2D;
30+import java.awt.GraphicsConfiguration;
31+import sun.awt.image.SunVolatileImage;
32+import static sun.java2d.pipe.hw.AccelSurface.*;
33+
34+/**
35+ * This is an image with forced type of the accelerated surface.
36+ */
37+public class AccelTypedVolatileImage extends SunVolatileImage {
38+
39+ /**
40+ * Creates a volatile image with specified type of accelerated surface.
41+ *
42+ * @param graphicsConfig a GraphicsConfiguration for which this image should
43+ * be created.
44+ * @param width width
45+ * @param height width
46+ * @param transparency type of {@link java.awt.Transparency transparency}
47+ * requested for the image
48+ * @param accType type of the desired accelerated surface as defined in
49+ * AccelSurface interface
50+ * @see sun.java2d.pipe.hw.AccelSurface
51+ */
52+ public AccelTypedVolatileImage(GraphicsConfiguration graphicsConfig,
53+ int width, int height, int transparency,
54+ int accType)
55+ {
56+ super(null, graphicsConfig, width, height, null, transparency,
57+ null, accType);
58+ }
59+
60+ /**
61+ * {@inheritDoc}
62+ *
63+ * This method will throw {@code UnsupportedOperationException} if it this
64+ * image's destination surface can not be rendered to.
65+ */
66+ @Override
67+ public Graphics2D createGraphics() {
68+ if (getForcedAccelSurfaceType() == TEXTURE) {
69+ throw new UnsupportedOperationException("Can't render " +
70+ "to a non-RT Texture");
71+ }
72+ return super.createGraphics();
73+ }
74+}
java/pkg/sun/java2d/pipe/hw/BufferedContextProvider.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/hw/BufferedContextProvider.java+45−0
@@ -0,0 +1,45 @@
1+/*
2+ * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe.hw;
27+
28+import sun.java2d.pipe.BufferedContext;
29+
30+/**
31+ * Classes implementing this interface can provide the {@code BufferedContext}
32+ * associated with or used by them.
33+ *
34+ * @see sun.java2d.pipe.BufferedContext
35+ */
36+public interface BufferedContextProvider {
37+ /**
38+ * Retrieves a context associated with object implementing this
39+ * interface.
40+ *
41+ * @return associated context
42+ * @see sun.java2d.pipe.BufferedContext
43+ */
44+ public BufferedContext getContext();
45+}
java/pkg/sun/java2d/pipe/hw/ContextCapabilities.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/hw/ContextCapabilities.java+128−0
@@ -0,0 +1,128 @@
1+/*
2+ * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe.hw;
27+
28+/**
29+ * Represents a set of capabilities of a BufferedContext and associated
30+ * AccelGraphicsConfig.
31+ *
32+ * @see AccelGraphicsConfig
33+ */
34+public class ContextCapabilities {
35+ /** Indicates that the context has no capabilities. */
36+ public static final int CAPS_EMPTY = (0 << 0);
37+ /** Indicates that the context supports RT surfaces with alpha channel. */
38+ public static final int CAPS_RT_PLAIN_ALPHA = (1 << 1);
39+ /** Indicates that the context supports RT textures with alpha channel. */
40+ public static final int CAPS_RT_TEXTURE_ALPHA = (1 << 2);
41+ /** Indicates that the context supports opaque RT textures. */
42+ public static final int CAPS_RT_TEXTURE_OPAQUE = (1 << 3);
43+ /** Indicates that the context supports multitexturing. */
44+ public static final int CAPS_MULTITEXTURE = (1 << 4);
45+ /** Indicates that the context supports non-pow2 texture dimensions. */
46+ public static final int CAPS_TEXNONPOW2 = (1 << 5);
47+ /** Indicates that the context supports non-square textures. */
48+ public static final int CAPS_TEXNONSQUARE = (1 << 6);
49+ /** Indicates that the context supports pixel shader 2.0 or better. */
50+ public static final int CAPS_PS20 = (1 << 7);
51+ /** Indicates that the context supports pixel shader 3.0 or better. */
52+ public static final int CAPS_PS30 = (1 << 8);
53+ /*
54+ * Pipeline contexts should use this for defining pipeline-specific
55+ * capabilities, for example:
56+ * int CAPS_D3D_1 = (FIRST_PRIVATE_CAP << 0);
57+ * int CAPS_D3D_2 = (FIRST_PRIVATE_CAP << 1);
58+ */
59+ protected static final int FIRST_PRIVATE_CAP = (1 << 16);
60+
61+ protected final int caps;
62+ protected final String adapterId;
63+
64+ /**
65+ * Constructs a {@code ContextCapabilities} object.
66+ * @param caps an {@code int} representing the capabilities
67+ * @param a {@code String} representing the name of the adapter, or null,
68+ * in which case the adapterId will be set to "unknown adapter".
69+ */
70+ protected ContextCapabilities(int caps, String adapterId) {
71+ this.caps = caps;
72+ this.adapterId = adapterId != null ? adapterId : "unknown adapter";
73+ }
74+
75+ /**
76+ * Returns a string representing the name of the graphics adapter if such
77+ * could be determined. It is guaranteed to never return {@code null}.
78+ * @return string representing adapter id
79+ */
80+ public String getAdapterId() {
81+ return adapterId;
82+ }
83+
84+ /**
85+ * Returns an {@code int} with capabilities (OR-ed constants defined in
86+ * this class and its pipeline-specific subclasses).
87+ * @return capabilities as {@code int}
88+ */
89+ public int getCaps() {
90+ return caps;
91+ }
92+
93+ @Override
94+ public String toString() {
95+ StringBuffer buf =
96+ new StringBuffer("ContextCapabilities: adapter=" +
97+ adapterId+", caps=");
98+ if (caps == CAPS_EMPTY) {
99+ buf.append("CAPS_EMPTY");
100+ } else {
101+ if ((caps & CAPS_RT_PLAIN_ALPHA) != 0) {
102+ buf.append("CAPS_RT_PLAIN_ALPHA|");
103+ }
104+ if ((caps & CAPS_RT_TEXTURE_ALPHA) != 0) {
105+ buf.append("CAPS_RT_TEXTURE_ALPHA|");
106+ }
107+ if ((caps & CAPS_RT_TEXTURE_OPAQUE) != 0) {
108+ buf.append("CAPS_RT_TEXTURE_OPAQUE|");
109+ }
110+ if ((caps & CAPS_MULTITEXTURE) != 0) {
111+ buf.append("CAPS_MULTITEXTURE|");
112+ }
113+ if ((caps & CAPS_TEXNONPOW2) != 0) {
114+ buf.append("CAPS_TEXNONPOW2|");
115+ }
116+ if ((caps & CAPS_TEXNONSQUARE) != 0) {
117+ buf.append("CAPS_TEXNONSQUARE|");
118+ }
119+ if ((caps & CAPS_PS20) != 0) {
120+ buf.append("CAPS_PS20|");
121+ }
122+ if ((caps & CAPS_PS30) != 0) {
123+ buf.append("CAPS_PS30|");
124+ }
125+ }
126+ return buf.toString();
127+ }
128+}
java/pkg/sun/java2d/pipe/hw/ExtendedBufferCapabilities$VSyncType.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/hw/ExtendedBufferCapabilities.class+0−0

Binary file not shown.

java/pkg/sun/java2d/pipe/hw/ExtendedBufferCapabilities.java+154−0
@@ -0,0 +1,154 @@
1+/*
2+ * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.java2d.pipe.hw;
27+
28+import java.awt.BufferCapabilities;
29+import java.awt.ImageCapabilities;
30+
31+/**
32+ * Provides extended BufferStrategy capabilities, allowing to specify
33+ * the type of vertical refresh synchronization for a buffer strategy.
34+ *
35+ * This BS capability is always page flipping because v-sync is only relevant
36+ * to flipping buffer strategies.
37+ *
38+ * Note that asking for a v-synced BS doesn't necessarily guarantee that it will
39+ * be v-synced since the vsync capability may be disabled in the driver, or
40+ * there may be other restriction (like a number of v-synced buffer strategies
41+ * allowed per vm). Because of this {@code createBufferStrategy} doesn't
42+ * throw {@code AWTException} when a v-synced BS could not be created when
43+ * requested.
44+ *
45+ * @see java.awt.Canvas#createBufferStrategy(int, BufferCapabilities)
46+ * @see java.awt.Window#createBufferStrategy(int, BufferCapabilities)
47+ */
48+public class ExtendedBufferCapabilities extends BufferCapabilities {
49+
50+ /**
51+ * Type of synchronization on vertical retrace.
52+ */
53+ public static enum VSyncType {
54+ /**
55+ * Use the default v-sync mode appropriate for given BufferStrategy
56+ * and situation.
57+ */
58+ VSYNC_DEFAULT(0),
59+
60+ /**
61+ * Synchronize flip on vertical retrace.
62+ */
63+ VSYNC_ON(1),
64+
65+ /**
66+ * Do not synchronize flip on vertical retrace.
67+ */
68+ VSYNC_OFF(2);
69+
70+ /**
71+ * Used to identify the v-sync type (independent of the constants
72+ * order as opposed to {@code ordinal()}).
73+ */
74+ public int id() {
75+ return id;
76+ }
77+
78+ private VSyncType(int id) {
79+ this.id = id;
80+ }
81+ private int id;
82+ }
83+
84+ private VSyncType vsync;
85+
86+ /**
87+ * Creates an ExtendedBufferCapabilities object with front/back/flip caps
88+ * from the passed cap, and VSYNC_DEFAULT v-sync mode.
89+ */
90+ public ExtendedBufferCapabilities(BufferCapabilities caps) {
91+ super(caps.getFrontBufferCapabilities(),
92+ caps.getBackBufferCapabilities(),
93+ caps.getFlipContents());
94+
95+ this.vsync = VSyncType.VSYNC_DEFAULT;
96+ }
97+
98+ /**
99+ * Creates an ExtendedBufferCapabilities instance with front/back/flip caps
100+ * from the passed caps, and VSYNC_DEFAULT v-sync mode.
101+ */
102+ public ExtendedBufferCapabilities(ImageCapabilities front,
103+ ImageCapabilities back, FlipContents flip)
104+ {
105+ super(front, back, flip);
106+
107+ this.vsync = VSyncType.VSYNC_DEFAULT;
108+ }
109+
110+ /**
111+ * Creates an ExtendedBufferCapabilities instance with front/back/flip caps
112+ * from the passed image/flip caps, and the v-sync type.
113+ */
114+ public ExtendedBufferCapabilities(ImageCapabilities front,
115+ ImageCapabilities back, FlipContents flip,
116+ VSyncType t)
117+ {
118+ super(front, back, flip);
119+
120+ this.vsync = t;
121+ }
122+
123+ /**
124+ * Creates an ExtendedBufferCapabilities instance with front/back/flip caps
125+ * from the passed cap, and the passed v-sync mode.
126+ */
127+ public ExtendedBufferCapabilities(BufferCapabilities caps, VSyncType t) {
128+ super(caps.getFrontBufferCapabilities(),
129+ caps.getBackBufferCapabilities(),
130+ caps.getFlipContents());
131+
132+ this.vsync = t;
133+ }
134+
135+ /**
136+ * Creates an ExtendedBufferCapabilities instance with front/back/flip caps
137+ * from the object, and passed v-sync mode.
138+ */
139+ public ExtendedBufferCapabilities derive(VSyncType t) {
140+ return new ExtendedBufferCapabilities(this, t);
141+ }
142+
143+ /**
144+ * Returns the type of v-sync requested by this capabilities instance.
145+ */
146+ public VSyncType getVSync() {
147+ return vsync;
148+ }
149+
150+ @Override
151+ public final boolean isPageFlipping() {
152+ return true;
153+ }
154+}
java/pkg/sun/java2d/pipe/hw/mkfile+15−0
@@ -0,0 +1,15 @@
1+<../../../../../../mkconfig
2+
3+TARG=\
4+ AccelDeviceEventListener.dis\
5+ AccelDeviceEventNotifier.dis\
6+ AccelGraphicsConfig.dis\
7+ AccelSurface.dis\
8+ AccelTypedVolatileImage.dis\
9+ BufferedContextProvider.dis\
10+ ContextCapabilities.dis\
11+ ExtendedBufferCapabilities.dis\
12+
13+DISBIN=$ROOT/java/dis/java/java/sun/java2d/pipe/hw
14+
15+<$ROOT/mkfiles/mkjava
java/pkg/sun/java2d/pipe/mkfile+56−0
@@ -0,0 +1,56 @@
1+<../../../../../mkconfig
2+
3+DIRS=\
4+ hw\
5+
6+TARG=\
7+ AAShapePipe.dis\
8+ AATextRenderer.dis\
9+ AATileGenerator.dis\
10+ AlphaColorPipe.dis\
11+ AlphaPaintPipe.dis\
12+ BufferedBufImgOps.dis\
13+ BufferedContext.dis\
14+ BufferedMaskBlit.dis\
15+ BufferedMaskFill.dis\
16+ BufferedOpCodes.dis\
17+ BufferedPaints.dis\
18+ BufferedRenderPipe.dis\
19+ BufferedTextPipe.dis\
20+ CompositePipe.dis\
21+ DrawImage.dis\
22+ DrawImagePipe.dis\
23+ GeneralCompositePipe.dis\
24+ GlyphListLoopPipe.dis\
25+ GlyphListPipe.dis\
26+ LCDTextRenderer.dis\
27+ LoopBasedPipe.dis\
28+ LoopPipe.dis\
29+ NullPipe.dis\
30+ OutlineTextRenderer.dis\
31+ ParallelogramPipe.dis\
32+ PixelDrawPipe.dis\
33+ PixelFillPipe.dis\
34+ PixelToParallelogramConverter.dis\
35+ PixelToShapeConverter.dis\
36+ Region.dis\
37+ RegionClipSpanIterator.dis\
38+ RegionIterator.dis\
39+ RegionSpanIterator.dis\
40+ RenderBuffer.dis\
41+ RenderingEngine.dis\
42+ RenderQueue.dis\
43+ ShapeDrawPipe.dis\
44+ ShapeSpanIterator.dis\
45+ SolidTextRenderer.dis\
46+ SpanClipRenderer.dis\
47+ SpanIterator.dis\
48+ SpanShapeRenderer.dis\
49+ TextPipe.dis\
50+ TextRenderer.dis\
51+ ValidatePipe.dis\
52+
53+DISBIN=$ROOT/java/dis/java/java/sun/java2d/pipe
54+
55+<$ROOT/mkfiles/mkjava
56+<$ROOT/mkfiles/mksubdirs