blob: 2715a28bdf68a9d95a8ba2e0c83ea6250418aa36 [file] [log] [blame]
/*
* Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.java2d.pipe;
import sun.java2d.SunGraphics2D;
import sun.java2d.SurfaceData;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.BasicStroke;
import java.awt.geom.PathIterator;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import sun.awt.SunHints;
/**
* This class is used to convert raw geometry into a span iterator
* object using a simple flattening polygon scan converter.
* The iterator can be passed on to special SpanFiller loops to
* perform the actual rendering.
*/
public abstract class SpanShapeRenderer implements ShapeDrawPipe {
final static RenderingEngine RenderEngine = RenderingEngine.getInstance();
public static class Composite extends SpanShapeRenderer {
CompositePipe comppipe;
public Composite(CompositePipe pipe) {
comppipe = pipe;
}
public Object startSequence(SunGraphics2D sg, Shape s,
Rectangle devR, int[] bbox) {
return comppipe.startSequence(sg, s, devR, bbox);
}
public void renderBox(Object ctx, int x, int y, int w, int h) {
comppipe.renderPathTile(ctx, null, 0, w, x, y, w, h);
}
public void endSequence(Object ctx) {
comppipe.endSequence(ctx);
}
}
public static class Simple extends SpanShapeRenderer
implements LoopBasedPipe
{
public Object startSequence(SunGraphics2D sg, Shape s,
Rectangle devR, int[] bbox) {
return sg;
}
public void renderBox(Object ctx, int x, int y, int w, int h) {
SunGraphics2D sg2d = (SunGraphics2D) ctx;
SurfaceData sd = sg2d.getSurfaceData();
sg2d.loops.fillRectLoop.FillRect(sg2d, sd, x, y, w, h);
}
public void endSequence(Object ctx) {
}
}
public void draw(SunGraphics2D sg, Shape s) {
if (sg.stroke instanceof BasicStroke) {
ShapeSpanIterator sr = LoopPipe.getStrokeSpans(sg, s);
try {
renderSpans(sg, sg.getCompClip(), s, sr);
} finally {
sr.dispose();
}
} else {
fill(sg, sg.stroke.createStrokedShape(s));
}
}
public static final int NON_RECTILINEAR_TRANSFORM_MASK =
(AffineTransform.TYPE_GENERAL_TRANSFORM |
AffineTransform.TYPE_GENERAL_ROTATION);
public void fill(SunGraphics2D sg, Shape s) {
if (s instanceof Rectangle2D &&
(sg.transform.getType() & NON_RECTILINEAR_TRANSFORM_MASK) == 0)
{
renderRect(sg, (Rectangle2D) s);
return;
}
Region clipRegion = sg.getCompClip();
ShapeSpanIterator sr = LoopPipe.getFillSSI(sg);
try {
sr.setOutputArea(clipRegion);
sr.appendPath(s.getPathIterator(sg.transform));
renderSpans(sg, clipRegion, s, sr);
} finally {
sr.dispose();
}
}
public abstract Object startSequence(SunGraphics2D sg, Shape s,
Rectangle devR, int[] bbox);
public abstract void renderBox(Object ctx, int x, int y, int w, int h);
public abstract void endSequence(Object ctx);
public void renderRect(SunGraphics2D sg, Rectangle2D r) {
double corners[] = {
r.getX(), r.getY(), r.getWidth(), r.getHeight(),
};
corners[2] += corners[0];
corners[3] += corners[1];
if (corners[2] <= corners[0] || corners[3] <= corners[1]) {
return;
}
sg.transform.transform(corners, 0, corners, 0, 2);
if (corners[2] < corners[0]) {
double t = corners[2];
corners[2] = corners[0];
corners[0] = t;
}
if (corners[3] < corners[1]) {
double t = corners[3];
corners[3] = corners[1];
corners[1] = t;
}
int abox[] = {
(int) corners[0],
(int) corners[1],
(int) corners[2],
(int) corners[3],
};
Rectangle devR = new Rectangle(abox[0], abox[1],
abox[2] - abox[0],
abox[3] - abox[1]);
Region clipRegion = sg.getCompClip();
clipRegion.clipBoxToBounds(abox);
if (abox[0] >= abox[2] || abox[1] >= abox[3]) {
return;
}
Object context = startSequence(sg, r, devR, abox);
if (clipRegion.isRectangular()) {
renderBox(context, abox[0], abox[1],
abox[2] - abox[0],
abox[3] - abox[1]);
} else {
SpanIterator sr = clipRegion.getSpanIterator(abox);
while (sr.nextSpan(abox)) {
renderBox(context, abox[0], abox[1],
abox[2] - abox[0],
abox[3] - abox[1]);
}
}
endSequence(context);
}
public void renderSpans(SunGraphics2D sg, Region clipRegion, Shape s,
ShapeSpanIterator sr)
{
Object context = null;
int abox[] = new int[4];
try {
sr.getPathBox(abox);
Rectangle devR = new Rectangle(abox[0], abox[1],
abox[2] - abox[0],
abox[3] - abox[1]);
clipRegion.clipBoxToBounds(abox);
if (abox[0] >= abox[2] || abox[1] >= abox[3]) {
return;
}
sr.intersectClipBox(abox[0], abox[1], abox[2], abox[3]);
context = startSequence(sg, s, devR, abox);
spanClipLoop(context, sr, clipRegion, abox);
} finally {
if (context != null) {
endSequence(context);
}
}
}
public void spanClipLoop(Object ctx, SpanIterator sr,
Region r, int[] abox) {
if (!r.isRectangular()) {
sr = r.filter(sr);
}
while (sr.nextSpan(abox)) {
int x = abox[0];
int y = abox[1];
renderBox(ctx, x, y, abox[2] - x, abox[3] - y);
}
}
}