/* * 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); } } }