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 static final 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 }