001: /*
002: * Copyright 1999-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 java.awt.Font;
029: import java.awt.Shape;
030: import java.awt.BasicStroke;
031: import java.awt.Polygon;
032: import java.awt.geom.AffineTransform;
033: import java.awt.geom.PathIterator;
034: import java.awt.geom.RoundRectangle2D;
035: import java.awt.geom.Ellipse2D;
036: import java.awt.geom.Arc2D;
037: import java.awt.geom.IllegalPathStateException;
038: import java.awt.geom.Path2D;
039: import java.awt.font.GlyphVector;
040: import sun.java2d.SunGraphics2D;
041: import sun.java2d.SurfaceData;
042: import sun.java2d.loops.FontInfo;
043: import sun.java2d.loops.DrawPolygons;
044: import sun.awt.SunHints;
045:
046: public class LoopPipe implements PixelDrawPipe, PixelFillPipe,
047: ShapeDrawPipe {
048: final static RenderingEngine RenderEngine = RenderingEngine
049: .getInstance();
050:
051: public void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2,
052: int y2) {
053: int tX = sg2d.transX;
054: int tY = sg2d.transY;
055: sg2d.loops.drawLineLoop.DrawLine(sg2d, sg2d.getSurfaceData(),
056: x1 + tX, y1 + tY, x2 + tX, y2 + tY);
057: }
058:
059: public void drawRect(SunGraphics2D sg2d, int x, int y, int width,
060: int height) {
061: sg2d.loops.drawRectLoop.DrawRect(sg2d, sg2d.getSurfaceData(), x
062: + sg2d.transX, y + sg2d.transY, width, height);
063: }
064:
065: public void drawRoundRect(SunGraphics2D sg2d, int x, int y,
066: int width, int height, int arcWidth, int arcHeight) {
067: sg2d.shapepipe.draw(sg2d, new RoundRectangle2D.Float(x, y,
068: width, height, arcWidth, arcHeight));
069: }
070:
071: public void drawOval(SunGraphics2D sg2d, int x, int y, int width,
072: int height) {
073: sg2d.shapepipe.draw(sg2d, new Ellipse2D.Float(x, y, width,
074: height));
075: }
076:
077: public void drawArc(SunGraphics2D sg2d, int x, int y, int width,
078: int height, int startAngle, int arcAngle) {
079: sg2d.shapepipe.draw(sg2d, new Arc2D.Float(x, y, width, height,
080: startAngle, arcAngle, Arc2D.OPEN));
081: }
082:
083: public void drawPolyline(SunGraphics2D sg2d, int xPoints[],
084: int yPoints[], int nPoints) {
085: int nPointsArray[] = { nPoints };
086: sg2d.loops.drawPolygonsLoop.DrawPolygons(sg2d, sg2d
087: .getSurfaceData(), xPoints, yPoints, nPointsArray, 1,
088: sg2d.transX, sg2d.transY, false);
089: }
090:
091: public void drawPolygon(SunGraphics2D sg2d, int xPoints[],
092: int yPoints[], int nPoints) {
093: int nPointsArray[] = { nPoints };
094: sg2d.loops.drawPolygonsLoop.DrawPolygons(sg2d, sg2d
095: .getSurfaceData(), xPoints, yPoints, nPointsArray, 1,
096: sg2d.transX, sg2d.transY, true);
097: }
098:
099: public void fillRect(SunGraphics2D sg2d, int x, int y, int width,
100: int height) {
101: sg2d.loops.fillRectLoop.FillRect(sg2d, sg2d.getSurfaceData(), x
102: + sg2d.transX, y + sg2d.transY, width, height);
103: }
104:
105: public void fillRoundRect(SunGraphics2D sg2d, int x, int y,
106: int width, int height, int arcWidth, int arcHeight) {
107: sg2d.shapepipe.fill(sg2d, new RoundRectangle2D.Float(x, y,
108: width, height, arcWidth, arcHeight));
109: }
110:
111: public void fillOval(SunGraphics2D sg2d, int x, int y, int width,
112: int height) {
113: sg2d.shapepipe.fill(sg2d, new Ellipse2D.Float(x, y, width,
114: height));
115: }
116:
117: public void fillArc(SunGraphics2D sg2d, int x, int y, int width,
118: int height, int startAngle, int arcAngle) {
119: sg2d.shapepipe.fill(sg2d, new Arc2D.Float(x, y, width, height,
120: startAngle, arcAngle, Arc2D.PIE));
121: }
122:
123: public void fillPolygon(SunGraphics2D sg2d, int xPoints[],
124: int yPoints[], int nPoints) {
125: ShapeSpanIterator sr = new ShapeSpanIterator(sg2d, false);
126:
127: try {
128: sr.setOutputArea(sg2d.getCompClip());
129: sr.appendPoly(xPoints, yPoints, nPoints, sg2d.transX,
130: sg2d.transY);
131: fillSpans(sg2d, sr);
132: } finally {
133: sr.dispose();
134: }
135: }
136:
137: public void draw(SunGraphics2D sg2d, Shape s) {
138: if (sg2d.strokeState == sg2d.STROKE_THIN) {
139: Path2D.Float p2df;
140: int transX;
141: int transY;
142: if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) {
143: if (s instanceof Path2D.Float) {
144: p2df = (Path2D.Float) s;
145: } else {
146: p2df = new Path2D.Float(s);
147: }
148: transX = sg2d.transX;
149: transY = sg2d.transY;
150: } else {
151: p2df = new Path2D.Float(s, sg2d.transform);
152: transX = 0;
153: transY = 0;
154: }
155: sg2d.loops.drawPathLoop.DrawPath(sg2d, sg2d
156: .getSurfaceData(), transX, transY, p2df);
157: return;
158: }
159:
160: if (sg2d.strokeState == sg2d.STROKE_CUSTOM) {
161: fill(sg2d, sg2d.stroke.createStrokedShape(s));
162: return;
163: }
164:
165: ShapeSpanIterator sr = getStrokeSpans(sg2d, s);
166:
167: try {
168: fillSpans(sg2d, sr);
169: } finally {
170: sr.dispose();
171: }
172: }
173:
174: /*
175: * Return a ShapeSpanIterator to iterate the spans of the wide
176: * outline of Shape s using the attributes of the SunGraphics2D
177: * object.
178: * REMIND: This should return a SpanIterator interface object
179: * but the caller needs to dispose() the object and that method
180: * is only on ShapeSpanIterator.
181: * TODO: Add a dispose() method to the SpanIterator interface.
182: */
183: public static ShapeSpanIterator getStrokeSpans(SunGraphics2D sg2d,
184: Shape s) {
185: ShapeSpanIterator sr = new ShapeSpanIterator(sg2d, true);
186:
187: try {
188: sr.setOutputArea(sg2d.getCompClip());
189: sr.setRule(PathIterator.WIND_NON_ZERO);
190:
191: BasicStroke bs = (BasicStroke) sg2d.stroke;
192: boolean thin = (sg2d.strokeState <= sg2d.STROKE_THINDASHED);
193: boolean normalize = (sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE);
194:
195: RenderEngine.strokeTo(s, sg2d.transform, bs, thin,
196: normalize, false, sr);
197: } catch (Throwable t) {
198: sr.dispose();
199: sr = null;
200: t.printStackTrace();
201: throw new InternalError("Unable to Stroke shape ("
202: + t.getMessage() + ")");
203: }
204: return sr;
205: }
206:
207: public void fill(SunGraphics2D sg2d, Shape s) {
208: if (sg2d.strokeState == sg2d.STROKE_THIN) {
209: Path2D.Float p2df;
210: int transX;
211: int transY;
212: if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) {
213: if (s instanceof Path2D.Float) {
214: p2df = (Path2D.Float) s;
215: } else {
216: p2df = new Path2D.Float(s);
217: }
218: transX = sg2d.transX;
219: transY = sg2d.transY;
220: } else {
221: p2df = new Path2D.Float(s, sg2d.transform);
222: transX = 0;
223: transY = 0;
224: }
225: sg2d.loops.fillPathLoop.FillPath(sg2d, sg2d
226: .getSurfaceData(), transX, transY, p2df);
227: return;
228: }
229:
230: ShapeSpanIterator sr = new ShapeSpanIterator(sg2d, false);
231: try {
232: sr.setOutputArea(sg2d.getCompClip());
233: AffineTransform at = ((sg2d.transformState == sg2d.TRANSFORM_ISIDENT) ? null
234: : sg2d.transform);
235: sr.appendPath(s.getPathIterator(at));
236: fillSpans(sg2d, sr);
237: } finally {
238: sr.dispose();
239: }
240: }
241:
242: private static void fillSpans(SunGraphics2D sg2d, SpanIterator si) {
243: // REMIND: Eventually, the plan is that it will not be possible for
244: // fs to be null since the FillSpans loop will be the fundamental
245: // loop implemented for any destination type...
246: if (sg2d.clipState == sg2d.CLIP_SHAPE) {
247: si = sg2d.clipRegion.filter(si);
248: // REMIND: Region.filter produces a Java-only iterator
249: // with no native counterpart...
250: } else {
251: sun.java2d.loops.FillSpans fs = sg2d.loops.fillSpansLoop;
252: if (fs != null) {
253: fs.FillSpans(sg2d, sg2d.getSurfaceData(), si);
254: return;
255: }
256: }
257: int spanbox[] = new int[4];
258: SurfaceData sd = sg2d.getSurfaceData();
259: while (si.nextSpan(spanbox)) {
260: int x = spanbox[0];
261: int y = spanbox[1];
262: int w = spanbox[2] - x;
263: int h = spanbox[3] - y;
264: sg2d.loops.fillRectLoop.FillRect(sg2d, sd, x, y, w, h);
265: }
266: }
267: }
|