blob: c56cd7b0802615db59ae3cfdb2fb04bd8ab52e82 [file] [log] [blame]
/*
* Copyright 2002-2005 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.java2d.d3d;
import java.awt.Composite;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.IllegalPathStateException;
import java.awt.geom.PathIterator;
import java.awt.geom.RoundRectangle2D;
import sun.java2d.SunGraphics2D;
import sun.java2d.pipe.Region;
import sun.java2d.SurfaceData;
import sun.java2d.loops.GraphicsPrimitive;
import sun.java2d.pipe.LoopPipe;
import sun.java2d.pipe.ShapeSpanIterator;
import sun.java2d.pipe.SpanIterator;
import static sun.java2d.d3d.D3DContext.*;
import sun.java2d.windows.DDRenderer;
public class D3DRenderer extends DDRenderer {
native boolean doDrawLineD3D(long pData, long pCtx,
int x1, int y1, int x2, int y2);
native boolean doDrawRectD3D(long pData, long pCtx,
int x, int y, int w, int h);
native boolean doFillRectD3D(long pData, long pCtx, int x, int y,
int width, int height);
native void doDrawPoly(long pData, long pCtx, int transx, int transy,
int[] xpoints, int[] ypoints,
int npoints, boolean isclosed);
native void devFillSpans(long pData, long pCtx, SpanIterator si,
long iterator, int transx, int transy);
private long getContext(SunGraphics2D sg2d) {
AffineTransform at =
sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE ?
null : sg2d.transform;
int ctxflags = (sg2d.eargb >>> 24) == 0xff ?
SRC_IS_OPAQUE : NO_CONTEXT_FLAGS;
return D3DContext.getContext(null, sg2d.surfaceData,
sg2d.getCompClip(),
sg2d.getComposite(),
at,
sg2d.eargb,
ctxflags);
}
@Override
public void drawLine(SunGraphics2D sg2d,
int x1, int y1, int x2, int y2)
{
synchronized (D3DContext.LOCK) {
doDrawLineD3D(sg2d.surfaceData.getNativeOps(),
getContext(sg2d),
x1 + sg2d.transX, y1 + sg2d.transY,
x2 + sg2d.transX, y2 + sg2d.transY);
}
}
@Override
public void fillRect(SunGraphics2D sg2d,
int x, int y, int width, int height)
{
synchronized (D3DContext.LOCK) {
doFillRectD3D(sg2d.surfaceData.getNativeOps(),
getContext(sg2d),
sg2d.transX + x, sg2d.transY + y, width, height);
}
}
@Override
public void drawRect(SunGraphics2D sg2d,
int x, int y, int width, int height)
{
synchronized (D3DContext.LOCK) {
doDrawRectD3D(sg2d.surfaceData.getNativeOps(),
getContext(sg2d),
x + sg2d.transX, sg2d.transY + y, width, height);
}
}
@Override
public void drawPolyline(SunGraphics2D sg2d,
int xpoints[], int ypoints[], int npoints)
{
synchronized (D3DContext.LOCK) {
doDrawPoly(sg2d.surfaceData.getNativeOps(),
getContext(sg2d),
sg2d.transX, sg2d.transY,
xpoints, ypoints, npoints, false);
}
}
@Override
public void drawPolygon(SunGraphics2D sg2d,
int xpoints[], int ypoints[], int npoints)
{
synchronized (D3DContext.LOCK) {
doDrawPoly(sg2d.surfaceData.getNativeOps(),
getContext(sg2d),
sg2d.transX, sg2d.transY,
xpoints, ypoints, npoints, true);
}
}
@Override
public void drawRoundRect(SunGraphics2D sg2d,
int x, int y, int width, int height,
int arcWidth, int arcHeight)
{
draw(sg2d, new RoundRectangle2D.Float(x, y, width, height,
arcWidth, arcHeight));
}
@Override
public void drawOval(SunGraphics2D sg2d,
int x, int y, int width, int height)
{
draw(sg2d, new Ellipse2D.Float(x, y, width, height));
}
@Override
public void drawArc(SunGraphics2D sg2d,
int x, int y, int width, int height,
int startAngle, int arcAngle)
{
draw(sg2d, new Arc2D.Float(x, y, width, height,
startAngle, arcAngle,
Arc2D.OPEN));
}
@Override
public void fillRoundRect(SunGraphics2D sg2d,
int x, int y, int width, int height,
int arcWidth, int arcHeight)
{
fill(sg2d, new RoundRectangle2D.Float(x, y, width, height,
arcWidth, arcHeight));
}
@Override
public void fillOval(SunGraphics2D sg2d,
int x, int y, int width, int height)
{
fill(sg2d, new Ellipse2D.Float(x, y, width, height));
}
@Override
public void fillArc(SunGraphics2D sg2d,
int x, int y, int width, int height,
int startAngle, int arcAngle)
{
fill(sg2d, new Arc2D.Float(x, y, width, height,
startAngle, arcAngle, Arc2D.PIE));
}
@Override
public void fillPolygon(SunGraphics2D sg2d,
int xpoints[], int ypoints[],
int npoints)
{
fill(sg2d, new Polygon(xpoints, ypoints, npoints));
}
@Override
public void draw(SunGraphics2D sg2d, Shape s)
{
if (sg2d.strokeState == sg2d.STROKE_THIN) {
Polygon p;
if (s instanceof Polygon) {
p = (Polygon) s;
drawPolygon(sg2d, p.xpoints, p.ypoints, p.npoints);
return;
}
// we're letting d3d handle the transforms
PathIterator pi = s.getPathIterator(null, 0.5f);
p = new Polygon();
float coords[] = new float[2];
while (!pi.isDone()) {
switch (pi.currentSegment(coords)) {
case PathIterator.SEG_MOVETO:
if (p.npoints > 1) {
drawPolyline(sg2d, p.xpoints, p.ypoints, p.npoints);
}
p.reset();
p.addPoint((int) Math.floor(coords[0]),
(int) Math.floor(coords[1]));
break;
case PathIterator.SEG_LINETO:
if (p.npoints == 0) {
throw new IllegalPathStateException
("missing initial moveto in path definition");
}
p.addPoint((int) Math.floor(coords[0]),
(int) Math.floor(coords[1]));
break;
case PathIterator.SEG_CLOSE:
if (p.npoints > 0) {
p.addPoint(p.xpoints[0], p.ypoints[0]);
}
break;
default:
throw new
IllegalPathStateException("path not flattened");
}
pi.next();
}
if (p.npoints > 1) {
drawPolyline(sg2d, p.xpoints, p.ypoints, p.npoints);
}
} else if (sg2d.strokeState < sg2d.STROKE_CUSTOM) {
ShapeSpanIterator si = LoopPipe.getStrokeSpans(sg2d, s);
try {
synchronized (D3DContext.LOCK) {
int ctxflags = (sg2d.eargb >>> 24) == 0xff ?
SRC_IS_OPAQUE : NO_CONTEXT_FLAGS;
// in this case the spans will be pre-transformed, so we
// pass null transform to getContext
long pCtx = D3DContext.getContext(null, sg2d.surfaceData,
sg2d.getCompClip(),
sg2d.getComposite(),
null /*transform*/,
sg2d.eargb/*pixel*/,
ctxflags);
devFillSpans(sg2d.surfaceData.getNativeOps(), pCtx, si,
si.getNativeIterator(), 0, 0);
}
} finally {
si.dispose();
}
} else {
fill(sg2d, sg2d.stroke.createStrokedShape(s));
}
}
@Override
public void fill(SunGraphics2D sg2d, Shape s) {
AffineTransform at;
int transx, transy;
if ( sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE) {
// Transform (translation) will be done by devFillSpans
at = null;
transx = sg2d.transX;
transy = sg2d.transY;
} else {
// Transform will be done by the PathIterator
at = sg2d.transform;
transx = transy = 0;
}
ShapeSpanIterator ssi = LoopPipe.getFillSSI(sg2d);
try {
// Subtract transx/y from the SSI clip to match the
// (potentially untranslated) geometry fed to it
Region clip = sg2d.getCompClip();
ssi.setOutputAreaXYXY(clip.getLoX() - transx,
clip.getLoY() - transy,
clip.getHiX() - transx,
clip.getHiY() - transy);
ssi.appendPath(s.getPathIterator(at));
synchronized (D3DContext.LOCK) {
int ctxflags = (sg2d.eargb >>> 24) == 0xff ?
SRC_IS_OPAQUE : NO_CONTEXT_FLAGS;
long pCtx = D3DContext.getContext(null, sg2d.surfaceData,
sg2d.getCompClip(),
sg2d.getComposite(),
null/*transform*/,
sg2d.eargb/*pixel*/,
ctxflags);
devFillSpans(sg2d.surfaceData.getNativeOps(), pCtx, ssi,
ssi.getNativeIterator(),
transx, transy);
}
} finally {
ssi.dispose();
}
}
D3DRenderer traceWrapD3D() {
return new Tracer();
}
private class Tracer extends D3DRenderer {
@Override
public void drawLine(SunGraphics2D sg2d,
int x1, int y1, int x2, int y2)
{
GraphicsPrimitive.tracePrimitive("D3DDrawLine");
super.drawLine(sg2d, x1, y1, x2, y2);
}
@Override
public void drawRect(SunGraphics2D sg2d, int x, int y, int w, int h) {
GraphicsPrimitive.tracePrimitive("D3DDrawRect");
super.drawRect(sg2d, x, y, w, h);
}
@Override
public void drawPolyline(SunGraphics2D sg2d,
int[] xPoints, int[] yPoints,
int nPoints)
{
GraphicsPrimitive.tracePrimitive("D3DDrawPolyline");
super.drawPolyline(sg2d, xPoints, yPoints, nPoints);
}
@Override
public void drawPolygon(SunGraphics2D sg2d,
int[] xPoints, int[] yPoints,
int nPoints)
{
GraphicsPrimitive.tracePrimitive("D3DDrawPolygon");
super.drawPolygon(sg2d, xPoints, yPoints, nPoints);
}
@Override
public void fillRect(SunGraphics2D sg2d, int x, int y, int w, int h) {
GraphicsPrimitive.tracePrimitive("D3DFillRect");
super.fillRect(sg2d, x, y, w, h);
}
@Override
void devFillSpans(long pData, long pCtx, SpanIterator si, long iterator,
int transx, int transy)
{
GraphicsPrimitive.tracePrimitive("D3DFillSpans");
super.devFillSpans(pData, pCtx, si, iterator, transx, transy);
}
@Override
public void devCopyArea(SurfaceData sData,
int srcx, int srcy,
int dx, int dy,
int w, int h)
{
GraphicsPrimitive.tracePrimitive("DXCopyArea");
super.devCopyArea(sData, srcx, srcy, dx, dy, w, h);
}
}
}