/* * Copyright 2000-2006 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.windows; import java.awt.Composite; import java.awt.Shape; import java.awt.geom.Path2D; import java.awt.geom.PathIterator; import sun.java2d.SunGraphics2D; import sun.java2d.SurfaceData; import sun.java2d.pipe.Region; import sun.java2d.pipe.PixelDrawPipe; import sun.java2d.pipe.PixelFillPipe; import sun.java2d.pipe.ShapeDrawPipe; import sun.java2d.pipe.SpanIterator; import sun.java2d.loops.GraphicsPrimitive; /** * DDRenderer * * This class accelerates rendering to a surface of type * WinOffScreenSurfaceData. The renderers in here are simply java wrappers * around native methods that do the real work. */ public class DDRenderer extends GDIRenderer { // // Native implementations // native void doDrawLineDD(SurfaceData sData, int color, int x1, int y1, int x2, int y2); native void doFillRectDD(SurfaceData sData, int color, int left, int top, int right, int bottom); native void doDrawRectDD(SurfaceData sData, int color, int x, int y, int w, int h); // // Internal Java methods for rendering // /** * Clip the given line to the clip bounds in sg2d. * Assume that the line passed in is given in the order of * x1 <= x2, y1 <= y2 */ private void clipAndDrawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2) { // If any of these are true, the line lies outside of the // clip bounds Region clip = sg2d.getCompClip(); int cx1 = clip.getLoX(); int cy1 = clip.getLoY(); int cx2 = clip.getHiX(); int cy2 = clip.getHiY(); // For each edge, clip the appropriate coordinate against // that edge. We are only dealing with horizontal or vertical lines // for now, so there is no interpolation between points to // the proper clip coordinate. if (x1 < cx1) x1 = cx1; if (y1 < cy1) y1 = cy1; if (x2 >= cx2) x2 = cx2 - 1; if (y2 >= cy2) y2 = cy2 - 1; // If the start moved past the end (or vice versa), // then we are outside the clip. if (x1 <= x2 && y1 <= y2) { doDrawLineDD(sg2d.surfaceData, sg2d.pixel, x1, y1, x2, y2); } } // REMIND: This is just a hack to get WIDE lines to honor the // necessary hinted pixelization rules. This should be replaced // by a native FillSpans method or a getHintedStrokeGeneralPath() // method that could be filled by the doShape method more quickly. public void doFillSpans(SunGraphics2D sg2d, SpanIterator si) { int box[] = new int[4]; SurfaceData sd = sg2d.surfaceData; while (si.nextSpan(box)) { doFillRectDD(sd, sg2d.pixel, box[0], box[1], box[2], box[3]); } } // // Java wrappers for the primitive renderers // /** * drawLine draws a line between the pixel at x1, y1 and the * pixel at x2, y2 (including the last pixel). */ public void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2) { // Note that we only handle horizontal or vertical lines through // this renderer. This is because the implementation uses a fill // Blt through DirectDraw, which only works for rectangle shapes. if (x1 == x2 || y1 == y2) { int transx1 = x1 + sg2d.transX; int transy1 = y1 + sg2d.transY; int transx2 = x2 + sg2d.transX; int transy2 = y2 + sg2d.transY; int t; // First, set the ordering of the line coordinates; // clipAndDrawLine() expects x1 < x2 and y1 < y2 if (transx1 > transx2) { t = transx1; transx1 = transx2; transx2 = t; } if (transy1 > transy2) { t = transy1; transy1 = transy2; transy2 = t; } clipAndDrawLine(sg2d, transx1, transy1, transx2, transy2); } else { // Punt to our superclass renderer to render diagonal lines super.drawLine(sg2d, x1, y1, x2, y2); } } /** * fillRect filles a rect from the pixel at x, y to (but not including) * the pixel at (x + width), (y + height) */ public void fillRect(SunGraphics2D sg2d, int x, int y, int width, int height) { int clipLeft, clipTop, clipRight, clipBottom; // REMIND: This check should probably go in SunGraphics2D instead. if (width <= 0 || height <= 0) { return; } // Here we clip the fill rect to the size of the clip bounds in sg2d. // The native code can then assume that it receives a non-empty, post- // clipped primitive. clipLeft = x + sg2d.transX; clipTop = y + sg2d.transY; clipRight = clipLeft + width; clipBottom = clipTop + height; Region clip = sg2d.getCompClip(); // Clip each edge of the rect to the appropriate edge of the clip // bounds. if (clipLeft < clip.getLoX()) clipLeft = clip.getLoX(); if (clipTop < clip.getLoY()) clipTop = clip.getLoY(); if (clipRight > clip.getHiX()) clipRight = clip.getHiX(); if (clipBottom > clip.getHiY()) clipBottom = clip.getHiY(); if (clipRight > clipLeft && clipBottom > clipTop) { doFillRectDD(sg2d.surfaceData, sg2d.pixel, clipLeft, clipTop, clipRight, clipBottom); } } /** * draw a rectangle outline starting at x, y and going to the pixel * at (x + width), (y + width) (including the lower right pixel) */ public void drawRect(SunGraphics2D sg2d, int x, int y, int width, int height) { if (width < 2 || height < 2) { fillRect(sg2d, x, y, width+1, height+1); return; } int transx = x + sg2d.transX; int transy = y + sg2d.transY; Region clip = sg2d.getCompClip(); if (!clip.encompassesXYWH(transx, transy, width+1, height+1)) { // Rect needs clipping - draw each edge separately, clipping // as we go. // Prefer longer horizontal lines if possible. clipAndDrawLine(sg2d, transx, transy, transx + width, transy); clipAndDrawLine(sg2d, transx, transy + 1, transx, transy + height - 1); clipAndDrawLine(sg2d, transx + width, transy + 1, transx + width, transy + height - 1); clipAndDrawLine(sg2d, transx, transy + height, transx + width, transy + height); } else { // No clipping needed - just call native method which draws // all edges in one method doDrawRectDD(sg2d.surfaceData, sg2d.pixel, transx, transy, width, height); } } @Override public native void devCopyArea(SurfaceData sData, int srcx, int srcy, int dx, int dy, int w, int h); public DDRenderer traceWrapDD() { return new Tracer(); } public static class Tracer extends DDRenderer { void doDrawLine(SurfaceData sData, Region clip, Composite comp, int color, int x1, int y1, int x2, int y2) { GraphicsPrimitive.tracePrimitive("GDIDrawLine"); super.doDrawLine(sData, clip, comp, color, x1, y1, x2, y2); } void doDrawRect(SurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h) { GraphicsPrimitive.tracePrimitive("GDIDrawRect"); super.doDrawRect(sData, clip, comp, color, x, y, w, h); } void doDrawRoundRect(SurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, int arcW, int arcH) { GraphicsPrimitive.tracePrimitive("GDIDrawRoundRect"); super.doDrawRoundRect(sData, clip, comp, color, x, y, w, h, arcW, arcH); } void doDrawOval(SurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h) { GraphicsPrimitive.tracePrimitive("GDIDrawOval"); super.doDrawOval(sData, clip, comp, color, x, y, w, h); } void doDrawArc(SurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, int angleStart, int angleExtent) { GraphicsPrimitive.tracePrimitive("GDIDrawArc"); super.doDrawArc(sData, clip, comp, color, x, y, w, h, angleStart, angleExtent); } void doDrawPoly(SurfaceData sData, Region clip, Composite comp, int color, int transx, int transy, int[] xpoints, int[] ypoints, int npoints, boolean isclosed) { GraphicsPrimitive.tracePrimitive("GDIDrawPoly"); super.doDrawPoly(sData, clip, comp, color, transx, transy, xpoints, ypoints, npoints, isclosed); } void doFillRect(SurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h) { GraphicsPrimitive.tracePrimitive("GDIFillRect"); super.doFillRect(sData, clip, comp, color, x, y, w, h); } void doFillRoundRect(SurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, int arcW, int arcH) { GraphicsPrimitive.tracePrimitive("GDIFillRoundRect"); super.doFillRoundRect(sData, clip, comp, color, x, y, w, h, arcW, arcH); } void doFillOval(SurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h) { GraphicsPrimitive.tracePrimitive("GDIFillOval"); super.doFillOval(sData, clip, comp, color, x, y, w, h); } void doFillArc(SurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, int angleStart, int angleExtent) { GraphicsPrimitive.tracePrimitive("GDIFillArc"); super.doFillArc(sData, clip, comp, color, x, y, w, h, angleStart, angleExtent); } void doFillPoly(SurfaceData sData, Region clip, Composite comp, int color, int transx, int transy, int[] xpoints, int[] ypoints, int npoints) { GraphicsPrimitive.tracePrimitive("GDIFillPoly"); super.doFillPoly(sData, clip, comp, color, transx, transy, xpoints, ypoints, npoints); } void doShape(SurfaceData sData, Region clip, Composite comp, int color, int transX, int transY, Path2D.Float p2df, boolean isfill) { GraphicsPrimitive.tracePrimitive(isfill ? "GDIFillShape" : "GDIDrawShape"); super.doShape(sData, clip, comp, color, transX, transY, p2df, isfill); } 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); } void doDrawLineDD(SurfaceData sData, int color, int x1, int y1, int x2, int y2) { GraphicsPrimitive.tracePrimitive("DXDrawLine"); super.doDrawLineDD(sData, color, x1, y1, x2, y2); } void doFillRectDD(SurfaceData sData, int color, int left, int top, int right, int bottom) { GraphicsPrimitive.tracePrimitive("DXFillRect"); super.doFillRectDD(sData, color, left, top, right, bottom); } void doDrawRectDD(SurfaceData sData, int color, int x, int y, int w, int h) { GraphicsPrimitive.tracePrimitive("DXDrawRect"); super.doDrawRectDD(sData, color, x, y, w, h); } } }