001: /*
002: * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.java2d.pipe;
027:
028: import sun.java2d.SunGraphics2D;
029: import sun.java2d.SurfaceData;
030: import java.awt.Rectangle;
031: import java.awt.Shape;
032: import java.awt.BasicStroke;
033: import java.awt.geom.PathIterator;
034: import java.awt.geom.AffineTransform;
035: import java.awt.geom.Rectangle2D;
036: import sun.awt.SunHints;
037:
038: /**
039: * This class is used to convert raw geometry into a span iterator
040: * object using a simple flattening polygon scan converter.
041: * The iterator can be passed on to special SpanFiller loops to
042: * perform the actual rendering.
043: */
044: public abstract class SpanShapeRenderer implements ShapeDrawPipe {
045: final static RenderingEngine RenderEngine = RenderingEngine
046: .getInstance();
047:
048: public static class Composite extends SpanShapeRenderer {
049: CompositePipe comppipe;
050:
051: public Composite(CompositePipe pipe) {
052: comppipe = pipe;
053: }
054:
055: public Object startSequence(SunGraphics2D sg, Shape s,
056: Rectangle devR, int[] bbox) {
057: return comppipe.startSequence(sg, s, devR, bbox);
058: }
059:
060: public void renderBox(Object ctx, int x, int y, int w, int h) {
061: comppipe.renderPathTile(ctx, null, 0, w, x, y, w, h);
062: }
063:
064: public void endSequence(Object ctx) {
065: comppipe.endSequence(ctx);
066: }
067: }
068:
069: public static class Simple extends SpanShapeRenderer {
070: public Object startSequence(SunGraphics2D sg, Shape s,
071: Rectangle devR, int[] bbox) {
072: return sg;
073: }
074:
075: public void renderBox(Object ctx, int x, int y, int w, int h) {
076: SunGraphics2D sg2d = (SunGraphics2D) ctx;
077: SurfaceData sd = sg2d.getSurfaceData();
078: sg2d.loops.fillRectLoop.FillRect(sg2d, sd, x, y, w, h);
079: }
080:
081: public void endSequence(Object ctx) {
082: }
083: }
084:
085: public void draw(SunGraphics2D sg, Shape s) {
086: if (sg.stroke instanceof BasicStroke) {
087: ShapeSpanIterator sr = new ShapeSpanIterator(sg, true);
088: try {
089: drawBasicStroke(sg, s, sr);
090: } finally {
091: sr.dispose();
092: }
093: } else {
094: renderPath(sg, sg.stroke.createStrokedShape(s));
095: }
096: }
097:
098: public void drawBasicStroke(SunGraphics2D sg, Shape s,
099: ShapeSpanIterator sr) {
100: Region clipRegion = sg.getCompClip();
101: sr.setOutputArea(clipRegion);
102: sr.setRule(PathIterator.WIND_NON_ZERO);
103:
104: BasicStroke bs = (BasicStroke) sg.stroke;
105: boolean thin = (sg.strokeState <= sg.STROKE_THINDASHED);
106: boolean normalize = (sg.strokeHint != SunHints.INTVAL_STROKE_PURE);
107:
108: RenderEngine.strokeTo(s, sg.transform, bs, thin, normalize,
109: false, sr);
110:
111: renderSpans(sg, clipRegion, s, sr);
112: }
113:
114: public static final int NON_RECTILINEAR_TRANSFORM_MASK = (AffineTransform.TYPE_GENERAL_TRANSFORM | AffineTransform.TYPE_GENERAL_ROTATION);
115:
116: public void fill(SunGraphics2D sg, Shape s) {
117: if (s instanceof Rectangle2D
118: && (sg.transform.getType() & NON_RECTILINEAR_TRANSFORM_MASK) == 0) {
119: renderRect(sg, (Rectangle2D) s);
120: return;
121: }
122: renderPath(sg, s);
123: }
124:
125: public abstract Object startSequence(SunGraphics2D sg, Shape s,
126: Rectangle devR, int[] bbox);
127:
128: public abstract void renderBox(Object ctx, int x, int y, int w,
129: int h);
130:
131: public abstract void endSequence(Object ctx);
132:
133: public void renderRect(SunGraphics2D sg, Rectangle2D r) {
134: double corners[] = { r.getX(), r.getY(), r.getWidth(),
135: r.getHeight(), };
136: corners[2] += corners[0];
137: corners[3] += corners[1];
138: if (corners[2] <= corners[0] || corners[3] <= corners[1]) {
139: return;
140: }
141: sg.transform.transform(corners, 0, corners, 0, 2);
142: if (corners[2] < corners[0]) {
143: double t = corners[2];
144: corners[2] = corners[0];
145: corners[0] = t;
146: }
147: if (corners[3] < corners[1]) {
148: double t = corners[3];
149: corners[3] = corners[1];
150: corners[1] = t;
151: }
152: int abox[] = { (int) corners[0], (int) corners[1],
153: (int) corners[2], (int) corners[3], };
154: Rectangle devR = new Rectangle(abox[0], abox[1], abox[2]
155: - abox[0], abox[3] - abox[1]);
156: Region clipRegion = sg.getCompClip();
157: clipRegion.clipBoxToBounds(abox);
158: if (abox[0] >= abox[2] || abox[1] >= abox[3]) {
159: return;
160: }
161: Object context = startSequence(sg, r, devR, abox);
162: if (clipRegion.isRectangular()) {
163: renderBox(context, abox[0], abox[1], abox[2] - abox[0],
164: abox[3] - abox[1]);
165: } else {
166: SpanIterator sr = clipRegion.getSpanIterator(abox);
167: while (sr.nextSpan(abox)) {
168: renderBox(context, abox[0], abox[1], abox[2] - abox[0],
169: abox[3] - abox[1]);
170: }
171: }
172: endSequence(context);
173: }
174:
175: public void renderPath(SunGraphics2D sg, Shape s) {
176: Region clipRegion = sg.getCompClip();
177:
178: ShapeSpanIterator sr = new ShapeSpanIterator(sg, false);
179: try {
180: sr.setOutputArea(clipRegion);
181: sr.appendPath(s.getPathIterator(sg.transform));
182: renderSpans(sg, clipRegion, s, sr);
183: } finally {
184: sr.dispose();
185: }
186: }
187:
188: public void renderSpans(SunGraphics2D sg, Region clipRegion,
189: Shape s, ShapeSpanIterator sr) {
190: Object context = null;
191: int abox[] = new int[4];
192: try {
193: sr.getPathBox(abox);
194: Rectangle devR = new Rectangle(abox[0], abox[1], abox[2]
195: - abox[0], abox[3] - abox[1]);
196: clipRegion.clipBoxToBounds(abox);
197: if (abox[0] >= abox[2] || abox[1] >= abox[3]) {
198: return;
199: }
200: sr.intersectClipBox(abox[0], abox[1], abox[2], abox[3]);
201: context = startSequence(sg, s, devR, abox);
202:
203: spanClipLoop(context, sr, clipRegion, abox);
204:
205: } finally {
206: if (context != null) {
207: endSequence(context);
208: }
209: }
210: }
211:
212: public void spanClipLoop(Object ctx, SpanIterator sr, Region r,
213: int[] abox) {
214: if (!r.isRectangular()) {
215: sr = r.filter(sr);
216: }
217: while (sr.nextSpan(abox)) {
218: int x = abox[0];
219: int y = abox[1];
220: renderBox(ctx, x, y, abox[2] - x, abox[3] - y);
221: }
222: }
223: }
|