| /* |
| * Copyright (c) 2000, 2006, 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.x11; |
| |
| import java.awt.Polygon; |
| import java.awt.Shape; |
| import java.awt.geom.AffineTransform; |
| import java.awt.geom.PathIterator; |
| import java.awt.geom.Path2D; |
| import java.awt.geom.IllegalPathStateException; |
| import sun.awt.SunToolkit; |
| import sun.java2d.SunGraphics2D; |
| import sun.java2d.SurfaceData; |
| import sun.java2d.loops.GraphicsPrimitive; |
| 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.pipe.ShapeSpanIterator; |
| import sun.java2d.pipe.LoopPipe; |
| |
| public class X11Renderer implements |
| PixelDrawPipe, |
| PixelFillPipe, |
| ShapeDrawPipe |
| { |
| public static X11Renderer getInstance() { |
| return (GraphicsPrimitive.tracingEnabled() |
| ? new X11TracingRenderer() |
| : new X11Renderer()); |
| } |
| |
| private final long validate(SunGraphics2D sg2d) { |
| // NOTE: getCompClip() will revalidateAll() if the |
| // surfaceData is invalid. This should ensure that |
| // the clip and pixel that we are validating against |
| // are the most current. |
| // |
| // The assumption is that the pipeline after that |
| // revalidation will either be another X11 pipe |
| // (because the drawable format never changes on X11) |
| // or a null pipeline if the surface is disposed. |
| // |
| // Since we do not get the ops structure of the SurfaceData |
| // until the actual call down to the native level we will |
| // pick up the most recently validated copy. |
| // Note that if the surface is disposed, a NullSurfaceData |
| // (with null native data structure) will be set in |
| // sg2d, so we have to protect against it in native code. |
| |
| X11SurfaceData x11sd = (X11SurfaceData)sg2d.surfaceData; |
| return x11sd.getRenderGC(sg2d.getCompClip(), |
| sg2d.compositeState, sg2d.composite, |
| sg2d.pixel); |
| } |
| |
| native void XDrawLine(long pXSData, long xgc, |
| int x1, int y1, int x2, int y2); |
| |
| public void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2) { |
| SunToolkit.awtLock(); |
| try { |
| long xgc = validate(sg2d); |
| int transx = sg2d.transX; |
| int transy = sg2d.transY; |
| XDrawLine(sg2d.surfaceData.getNativeOps(), xgc, |
| x1+transx, y1+transy, x2+transx, y2+transy); |
| } finally { |
| SunToolkit.awtUnlock(); |
| } |
| } |
| |
| native void XDrawRect(long pXSData, long xgc, |
| int x, int y, int w, int h); |
| |
| public void drawRect(SunGraphics2D sg2d, |
| int x, int y, int width, int height) |
| { |
| SunToolkit.awtLock(); |
| try { |
| long xgc = validate(sg2d); |
| XDrawRect(sg2d.surfaceData.getNativeOps(), xgc, |
| x+sg2d.transX, y+sg2d.transY, width, height); |
| } finally { |
| SunToolkit.awtUnlock(); |
| } |
| } |
| |
| native void XDrawRoundRect(long pXSData, long xgc, |
| int x, int y, int w, int h, |
| int arcW, int arcH); |
| |
| public void drawRoundRect(SunGraphics2D sg2d, |
| int x, int y, int width, int height, |
| int arcWidth, int arcHeight) |
| { |
| SunToolkit.awtLock(); |
| try { |
| long xgc = validate(sg2d); |
| XDrawRoundRect(sg2d.surfaceData.getNativeOps(), xgc, |
| x+sg2d.transX, y+sg2d.transY, width, height, |
| arcWidth, arcHeight); |
| } finally { |
| SunToolkit.awtUnlock(); |
| } |
| } |
| |
| native void XDrawOval(long pXSData, long xgc, |
| int x, int y, int w, int h); |
| |
| public void drawOval(SunGraphics2D sg2d, |
| int x, int y, int width, int height) |
| { |
| SunToolkit.awtLock(); |
| try { |
| long xgc = validate(sg2d); |
| XDrawOval(sg2d.surfaceData.getNativeOps(), xgc, |
| x+sg2d.transX, y+sg2d.transY, width, height); |
| } finally { |
| SunToolkit.awtUnlock(); |
| } |
| } |
| |
| native void XDrawArc(long pXSData, long xgc, |
| int x, int y, int w, int h, |
| int angleStart, int angleExtent); |
| |
| public void drawArc(SunGraphics2D sg2d, |
| int x, int y, int width, int height, |
| int startAngle, int arcAngle) |
| { |
| SunToolkit.awtLock(); |
| try { |
| long xgc = validate(sg2d); |
| XDrawArc(sg2d.surfaceData.getNativeOps(), xgc, |
| x+sg2d.transX, y+sg2d.transY, width, height, |
| startAngle, arcAngle); |
| } finally { |
| SunToolkit.awtUnlock(); |
| } |
| } |
| |
| native void XDrawPoly(long pXSData, long xgc, |
| int transx, int transy, |
| int[] xpoints, int[] ypoints, |
| int npoints, boolean isclosed); |
| |
| public void drawPolyline(SunGraphics2D sg2d, |
| int xpoints[], int ypoints[], |
| int npoints) |
| { |
| SunToolkit.awtLock(); |
| try { |
| long xgc = validate(sg2d); |
| XDrawPoly(sg2d.surfaceData.getNativeOps(), xgc, |
| sg2d.transX, sg2d.transY, |
| xpoints, ypoints, npoints, false); |
| } finally { |
| SunToolkit.awtUnlock(); |
| } |
| } |
| |
| public void drawPolygon(SunGraphics2D sg2d, |
| int xpoints[], int ypoints[], |
| int npoints) |
| { |
| SunToolkit.awtLock(); |
| try { |
| long xgc = validate(sg2d); |
| XDrawPoly(sg2d.surfaceData.getNativeOps(), xgc, |
| sg2d.transX, sg2d.transY, |
| xpoints, ypoints, npoints, true); |
| } finally { |
| SunToolkit.awtUnlock(); |
| } |
| } |
| |
| native void XFillRect(long pXSData, long xgc, |
| int x, int y, int w, int h); |
| |
| public void fillRect(SunGraphics2D sg2d, |
| int x, int y, int width, int height) |
| { |
| SunToolkit.awtLock(); |
| try { |
| long xgc = validate(sg2d); |
| XFillRect(sg2d.surfaceData.getNativeOps(), xgc, |
| x+sg2d.transX, y+sg2d.transY, width, height); |
| } finally { |
| SunToolkit.awtUnlock(); |
| } |
| } |
| |
| native void XFillRoundRect(long pXSData, long xgc, |
| int x, int y, int w, int h, |
| int arcW, int arcH); |
| |
| public void fillRoundRect(SunGraphics2D sg2d, |
| int x, int y, int width, int height, |
| int arcWidth, int arcHeight) |
| { |
| SunToolkit.awtLock(); |
| try { |
| long xgc = validate(sg2d); |
| XFillRoundRect(sg2d.surfaceData.getNativeOps(), xgc, |
| x+sg2d.transX, y+sg2d.transY, width, height, |
| arcWidth, arcHeight); |
| } finally { |
| SunToolkit.awtUnlock(); |
| } |
| } |
| |
| native void XFillOval(long pXSData, long xgc, |
| int x, int y, int w, int h); |
| |
| public void fillOval(SunGraphics2D sg2d, |
| int x, int y, int width, int height) |
| { |
| SunToolkit.awtLock(); |
| try { |
| long xgc = validate(sg2d); |
| XFillOval(sg2d.surfaceData.getNativeOps(), xgc, |
| x+sg2d.transX, y+sg2d.transY, width, height); |
| } finally { |
| SunToolkit.awtUnlock(); |
| } |
| } |
| |
| native void XFillArc(long pXSData, long xgc, |
| int x, int y, int w, int h, |
| int angleStart, int angleExtent); |
| |
| public void fillArc(SunGraphics2D sg2d, |
| int x, int y, int width, int height, |
| int startAngle, int arcAngle) |
| { |
| SunToolkit.awtLock(); |
| try { |
| long xgc = validate(sg2d); |
| XFillArc(sg2d.surfaceData.getNativeOps(), xgc, |
| x+sg2d.transX, y+sg2d.transY, width, height, |
| startAngle, arcAngle); |
| } finally { |
| SunToolkit.awtUnlock(); |
| } |
| } |
| |
| native void XFillPoly(long pXSData, long xgc, |
| int transx, int transy, |
| int[] xpoints, int[] ypoints, |
| int npoints); |
| |
| public void fillPolygon(SunGraphics2D sg2d, |
| int xpoints[], int ypoints[], |
| int npoints) |
| { |
| SunToolkit.awtLock(); |
| try { |
| long xgc = validate(sg2d); |
| XFillPoly(sg2d.surfaceData.getNativeOps(), xgc, |
| sg2d.transX, sg2d.transY, xpoints, ypoints, npoints); |
| } finally { |
| SunToolkit.awtUnlock(); |
| } |
| } |
| |
| native void XFillSpans(long pXSData, long xgc, |
| SpanIterator si, long iterator, |
| int transx, int transy); |
| |
| native void XDoPath(SunGraphics2D sg2d, long pXSData, long xgc, |
| int transX, int transY, Path2D.Float p2df, |
| boolean isFill); |
| |
| private void doPath(SunGraphics2D sg2d, Shape s, boolean isFill) { |
| Path2D.Float p2df; |
| int transx, transy; |
| if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) { |
| if (s instanceof Path2D.Float) { |
| p2df = (Path2D.Float)s; |
| } else { |
| p2df = new Path2D.Float(s); |
| } |
| transx = sg2d.transX; |
| transy = sg2d.transY; |
| } else { |
| p2df = new Path2D.Float(s, sg2d.transform); |
| transx = 0; |
| transy = 0; |
| } |
| SunToolkit.awtLock(); |
| try { |
| long xgc = validate(sg2d); |
| XDoPath(sg2d, sg2d.surfaceData.getNativeOps(), xgc, |
| transx, transy, p2df, isFill); |
| } finally { |
| SunToolkit.awtUnlock(); |
| } |
| } |
| |
| public void draw(SunGraphics2D sg2d, Shape s) { |
| if (sg2d.strokeState == sg2d.STROKE_THIN) { |
| // Delegate to drawPolygon() if possible... |
| if (s instanceof Polygon && |
| sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE) |
| { |
| Polygon p = (Polygon) s; |
| drawPolygon(sg2d, p.xpoints, p.ypoints, p.npoints); |
| return; |
| } |
| |
| // Otherwise we will use drawPath() for |
| // high-quality thin paths. |
| doPath(sg2d, s, false); |
| } else if (sg2d.strokeState < sg2d.STROKE_CUSTOM) { |
| // REMIND: X11 can handle uniform scaled wide lines |
| // and dashed lines itself if we set the appropriate |
| // XGC attributes (TBD). |
| ShapeSpanIterator si = LoopPipe.getStrokeSpans(sg2d, s); |
| try { |
| SunToolkit.awtLock(); |
| try { |
| long xgc = validate(sg2d); |
| XFillSpans(sg2d.surfaceData.getNativeOps(), xgc, |
| si, si.getNativeIterator(), |
| 0, 0); |
| } finally { |
| SunToolkit.awtUnlock(); |
| } |
| } finally { |
| si.dispose(); |
| } |
| } else { |
| fill(sg2d, sg2d.stroke.createStrokedShape(s)); |
| } |
| } |
| |
| public void fill(SunGraphics2D sg2d, Shape s) { |
| if (sg2d.strokeState == sg2d.STROKE_THIN) { |
| // Delegate to fillPolygon() if possible... |
| if (s instanceof Polygon && |
| sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE) |
| { |
| Polygon p = (Polygon) s; |
| fillPolygon(sg2d, p.xpoints, p.ypoints, p.npoints); |
| return; |
| } |
| |
| // Otherwise we will use fillPath() for |
| // high-quality fills. |
| doPath(sg2d, s, true); |
| return; |
| } |
| |
| AffineTransform at; |
| int transx, transy; |
| if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE) { |
| // Transform (translation) will be done by XFillSpans |
| 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)); |
| SunToolkit.awtLock(); |
| try { |
| long xgc = validate(sg2d); |
| XFillSpans(sg2d.surfaceData.getNativeOps(), xgc, |
| ssi, ssi.getNativeIterator(), |
| transx, transy); |
| } finally { |
| SunToolkit.awtUnlock(); |
| } |
| } finally { |
| ssi.dispose(); |
| } |
| } |
| |
| native void devCopyArea(long sdOps, long xgc, |
| int srcx, int srcy, |
| int dstx, int dsty, |
| int w, int h); |
| |
| public static class X11TracingRenderer extends X11Renderer { |
| void XDrawLine(long pXSData, long xgc, |
| int x1, int y1, int x2, int y2) |
| { |
| GraphicsPrimitive.tracePrimitive("X11DrawLine"); |
| super.XDrawLine(pXSData, xgc, x1, y1, x2, y2); |
| } |
| void XDrawRect(long pXSData, long xgc, |
| int x, int y, int w, int h) |
| { |
| GraphicsPrimitive.tracePrimitive("X11DrawRect"); |
| super.XDrawRect(pXSData, xgc, x, y, w, h); |
| } |
| void XDrawRoundRect(long pXSData, long xgc, |
| int x, int y, int w, int h, |
| int arcW, int arcH) |
| { |
| GraphicsPrimitive.tracePrimitive("X11DrawRoundRect"); |
| super.XDrawRoundRect(pXSData, xgc, x, y, w, h, arcW, arcH); |
| } |
| void XDrawOval(long pXSData, long xgc, |
| int x, int y, int w, int h) |
| { |
| GraphicsPrimitive.tracePrimitive("X11DrawOval"); |
| super.XDrawOval(pXSData, xgc, x, y, w, h); |
| } |
| void XDrawArc(long pXSData, long xgc, |
| int x, int y, int w, int h, |
| int angleStart, int angleExtent) |
| { |
| GraphicsPrimitive.tracePrimitive("X11DrawArc"); |
| super.XDrawArc(pXSData, xgc, |
| x, y, w, h, angleStart, angleExtent); |
| } |
| void XDrawPoly(long pXSData, long xgc, |
| int transx, int transy, |
| int[] xpoints, int[] ypoints, |
| int npoints, boolean isclosed) |
| { |
| GraphicsPrimitive.tracePrimitive("X11DrawPoly"); |
| super.XDrawPoly(pXSData, xgc, transx, transy, |
| xpoints, ypoints, npoints, isclosed); |
| } |
| void XDoPath(SunGraphics2D sg2d, long pXSData, long xgc, |
| int transX, int transY, Path2D.Float p2df, |
| boolean isFill) |
| { |
| GraphicsPrimitive.tracePrimitive(isFill ? |
| "X11FillPath" : |
| "X11DrawPath"); |
| super.XDoPath(sg2d, pXSData, xgc, transX, transY, p2df, isFill); |
| } |
| void XFillRect(long pXSData, long xgc, |
| int x, int y, int w, int h) |
| { |
| GraphicsPrimitive.tracePrimitive("X11FillRect"); |
| super.XFillRect(pXSData, xgc, x, y, w, h); |
| } |
| void XFillRoundRect(long pXSData, long xgc, |
| int x, int y, int w, int h, |
| int arcW, int arcH) |
| { |
| GraphicsPrimitive.tracePrimitive("X11FillRoundRect"); |
| super.XFillRoundRect(pXSData, xgc, x, y, w, h, arcW, arcH); |
| } |
| void XFillOval(long pXSData, long xgc, |
| int x, int y, int w, int h) |
| { |
| GraphicsPrimitive.tracePrimitive("X11FillOval"); |
| super.XFillOval(pXSData, xgc, x, y, w, h); |
| } |
| void XFillArc(long pXSData, long xgc, |
| int x, int y, int w, int h, |
| int angleStart, int angleExtent) |
| { |
| GraphicsPrimitive.tracePrimitive("X11FillArc"); |
| super.XFillArc(pXSData, xgc, |
| x, y, w, h, angleStart, angleExtent); |
| } |
| void XFillPoly(long pXSData, long xgc, |
| int transx, int transy, |
| int[] xpoints, int[] ypoints, |
| int npoints) |
| { |
| GraphicsPrimitive.tracePrimitive("X11FillPoly"); |
| super.XFillPoly(pXSData, xgc, |
| transx, transy, xpoints, ypoints, npoints); |
| } |
| void XFillSpans(long pXSData, long xgc, |
| SpanIterator si, long iterator, int transx, int transy) |
| { |
| GraphicsPrimitive.tracePrimitive("X11FillSpans"); |
| super.XFillSpans(pXSData, xgc, |
| si, iterator, transx, transy); |
| } |
| void devCopyArea(long sdOps, long xgc, |
| int srcx, int srcy, |
| int dstx, int dsty, |
| int w, int h) |
| { |
| GraphicsPrimitive.tracePrimitive("X11CopyArea"); |
| super.devCopyArea(sdOps, xgc, srcx, srcy, dstx, dsty, w, h); |
| } |
| } |
| } |