2370N/A/*
2685N/A * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2370N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2370N/A *
2370N/A * This code is free software; you can redistribute it and/or modify it
2370N/A * under the terms of the GNU General Public License version 2 only, as
2685N/A * published by the Free Software Foundation. Oracle designates this
2370N/A * particular file as subject to the "Classpath" exception as provided
2685N/A * by Oracle in the LICENSE file that accompanied this code.
2370N/A *
2370N/A * This code is distributed in the hope that it will be useful, but WITHOUT
2370N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2370N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2370N/A * version 2 for more details (a copy is included in the LICENSE file that
2370N/A * accompanied this code).
2370N/A *
2370N/A * You should have received a copy of the GNU General Public License version
2370N/A * 2 along with this work; if not, write to the Free Software Foundation,
2370N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2370N/A *
2685N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2685N/A * or visit www.oracle.com if you need additional information or have any
2685N/A * questions.
2370N/A */
2370N/A
2370N/Apackage sun.java2d.xr;
2370N/A
2370N/Aimport java.awt.*;
2370N/Aimport java.awt.geom.*;
2370N/A
2370N/Aimport sun.awt.SunToolkit;
2370N/Aimport sun.java2d.SunGraphics2D;
2370N/Aimport sun.java2d.loops.*;
2370N/Aimport sun.java2d.pipe.Region;
2370N/Aimport sun.java2d.pipe.PixelDrawPipe;
2370N/Aimport sun.java2d.pipe.PixelFillPipe;
2370N/Aimport sun.java2d.pipe.ShapeDrawPipe;
2370N/Aimport sun.java2d.pipe.SpanIterator;
2370N/Aimport sun.java2d.pipe.ShapeSpanIterator;
2370N/Aimport sun.java2d.pipe.LoopPipe;
2370N/A
2370N/A/**
2370N/A * XRender provides only accalerated rectangles. To emulate higher "order"
2370N/A * geometry we have to pass everything else to DoPath/FillSpans.
2370N/A *
2370N/A * TODO: DrawRect could be instrified
2370N/A *
2370N/A * @author Clemens Eisserer
2370N/A */
2370N/A
2370N/Apublic class XRRenderer implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe {
2370N/A XRDrawHandler drawHandler;
2370N/A MaskTileManager tileManager;
2370N/A
2370N/A public XRRenderer(MaskTileManager tileManager) {
2370N/A this.tileManager = tileManager;
2370N/A this.drawHandler = new XRDrawHandler();
2370N/A }
2370N/A
2370N/A /**
2370N/A * Common validate method, used by all XRRender functions to validate the
2370N/A * destination context.
2370N/A */
2370N/A private final void validateSurface(SunGraphics2D sg2d) {
2370N/A XRSurfaceData xrsd = (XRSurfaceData) sg2d.surfaceData;
2370N/A xrsd.validateAsDestination(sg2d, sg2d.getCompClip());
2370N/A xrsd.maskBuffer.validateCompositeState(sg2d.composite, sg2d.transform,
2370N/A sg2d.paint, sg2d);
2370N/A }
2370N/A
2370N/A public void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2) {
2370N/A try {
2370N/A SunToolkit.awtLock();
2370N/A
2370N/A validateSurface(sg2d);
2370N/A int transx = sg2d.transX;
2370N/A int transy = sg2d.transY;
2370N/A
2370N/A XRSurfaceData xrsd = (XRSurfaceData) sg2d.surfaceData;
2370N/A
2370N/A tileManager.addLine(x1 + transx, y1 + transy,
2370N/A x2 + transx, y2 + transy);
2370N/A tileManager.fillMask(xrsd);
2370N/A } finally {
2370N/A SunToolkit.awtUnlock();
2370N/A }
2370N/A }
2370N/A
2370N/A public void drawRect(SunGraphics2D sg2d,
2370N/A int x, int y, int width, int height) {
2370N/A draw(sg2d, new Rectangle2D.Float(x, y, width, height));
2370N/A }
2370N/A
2370N/A public void drawPolyline(SunGraphics2D sg2d,
2370N/A int xpoints[], int ypoints[], int npoints) {
2370N/A Path2D.Float p2d = new Path2D.Float();
2370N/A if (npoints > 1) {
2370N/A p2d.moveTo(xpoints[0], ypoints[0]);
2370N/A for (int i = 1; i < npoints; i++) {
2370N/A p2d.lineTo(xpoints[i], ypoints[i]);
2370N/A }
2370N/A }
2370N/A
2370N/A draw(sg2d, p2d);
2370N/A }
2370N/A
2370N/A public void drawPolygon(SunGraphics2D sg2d,
2370N/A int xpoints[], int ypoints[], int npoints) {
2370N/A draw(sg2d, new Polygon(xpoints, ypoints, npoints));
2370N/A }
2370N/A
2370N/A public synchronized void fillRect(SunGraphics2D sg2d,
2370N/A int x, int y, int width, int height) {
2370N/A SunToolkit.awtLock();
2370N/A try {
2370N/A validateSurface(sg2d);
2370N/A
2370N/A XRSurfaceData xrsd = (XRSurfaceData) sg2d.surfaceData;
2370N/A
2370N/A x += sg2d.transform.getTranslateX();
2370N/A y += sg2d.transform.getTranslateY();
2370N/A
2370N/A tileManager.addRect(x, y, width, height);
2370N/A tileManager.fillMask(xrsd);
2370N/A
2370N/A } finally {
2370N/A SunToolkit.awtUnlock();
2370N/A }
2370N/A }
2370N/A
2370N/A public void fillPolygon(SunGraphics2D sg2d,
2370N/A int xpoints[], int ypoints[], int npoints) {
2370N/A fill(sg2d, new Polygon(xpoints, ypoints, npoints));
2370N/A }
2370N/A
2370N/A public void drawRoundRect(SunGraphics2D sg2d,
2370N/A int x, int y, int width, int height,
2370N/A int arcWidth, int arcHeight) {
2370N/A draw(sg2d, new RoundRectangle2D.Float(x, y, width, height,
2370N/A arcWidth, arcHeight));
2370N/A }
2370N/A
2370N/A public void fillRoundRect(SunGraphics2D sg2d, int x, int y,
2370N/A int width, int height,
2370N/A int arcWidth, int arcHeight) {
2370N/A fill(sg2d, new RoundRectangle2D.Float(x, y, width, height,
2370N/A arcWidth, arcHeight));
2370N/A }
2370N/A
2370N/A public void drawOval(SunGraphics2D sg2d,
2370N/A int x, int y, int width, int height) {
2370N/A draw(sg2d, new Ellipse2D.Float(x, y, width, height));
2370N/A }
2370N/A
2370N/A public void fillOval(SunGraphics2D sg2d,
2370N/A int x, int y, int width, int height) {
2370N/A fill(sg2d, new Ellipse2D.Float(x, y, width, height));
2370N/A }
2370N/A
2370N/A public void drawArc(SunGraphics2D sg2d,
2370N/A int x, int y, int width, int height,
2370N/A int startAngle, int arcAngle) {
2370N/A draw(sg2d, new Arc2D.Float(x, y, width, height,
2370N/A startAngle, arcAngle, Arc2D.OPEN));
2370N/A }
2370N/A
2370N/A public void fillArc(SunGraphics2D sg2d,
2370N/A int x, int y, int width, int height,
2370N/A int startAngle, int arcAngle) {
2370N/A fill(sg2d, new Arc2D.Float(x, y, width, height,
2370N/A startAngle, arcAngle, Arc2D.PIE));
2370N/A }
2370N/A
2370N/A private class XRDrawHandler extends ProcessPath.DrawHandler {
2370N/A
2370N/A XRDrawHandler() {
2370N/A // these are bogus values; the caller will use validate()
2370N/A // to ensure that they are set properly prior to each usage
2370N/A super(0, 0, 0, 0);
2370N/A }
2370N/A
2370N/A /**
2370N/A * This method needs to be called prior to each draw/fillPath()
2370N/A * operation to ensure the clip bounds are up to date.
2370N/A */
2370N/A void validate(SunGraphics2D sg2d) {
2370N/A Region clip = sg2d.getCompClip();
2370N/A setBounds(clip.getLoX(), clip.getLoY(),
2370N/A clip.getHiX(), clip.getHiY(), sg2d.strokeHint);
2370N/A validateSurface(sg2d);
2370N/A }
2370N/A
2370N/A public void drawLine(int x1, int y1, int x2, int y2) {
2370N/A tileManager.addLine(x1, y1, x2, y2);
2370N/A }
2370N/A
2370N/A public void drawPixel(int x, int y) {
2370N/A tileManager.addRect(x, y, 1, 1);
2370N/A }
2370N/A
2370N/A public void drawScanline(int x1, int x2, int y) {
2370N/A tileManager.addRect(x1, y, x2 - x1 + 1, 1);
2370N/A }
2370N/A }
2370N/A
2370N/A protected void drawPath(SunGraphics2D sg2d, Path2D.Float p2df,
2370N/A int transx, int transy) {
2370N/A SunToolkit.awtLock();
2370N/A try {
2370N/A validateSurface(sg2d);
2370N/A drawHandler.validate(sg2d);
2370N/A ProcessPath.drawPath(drawHandler, p2df, transx, transy);
2370N/A tileManager.fillMask(((XRSurfaceData) sg2d.surfaceData));
2370N/A } finally {
2370N/A SunToolkit.awtUnlock();
2370N/A }
2370N/A }
2370N/A
2370N/A protected void fillPath(SunGraphics2D sg2d, Path2D.Float p2df,
2370N/A int transx, int transy) {
2370N/A SunToolkit.awtLock();
2370N/A try {
2370N/A validateSurface(sg2d);
2370N/A drawHandler.validate(sg2d);
2370N/A ProcessPath.fillPath(drawHandler, p2df, transx, transy);
2370N/A tileManager.fillMask(((XRSurfaceData) sg2d.surfaceData));
2370N/A } finally {
2370N/A SunToolkit.awtUnlock();
2370N/A }
2370N/A }
2370N/A
2370N/A protected void fillSpans(SunGraphics2D sg2d, SpanIterator si,
2370N/A int transx, int transy) {
2370N/A SunToolkit.awtLock();
2370N/A try {
2370N/A validateSurface(sg2d);
2370N/A int[] spanBox = new int[4];
2370N/A while (si.nextSpan(spanBox)) {
2370N/A tileManager.addRect(spanBox[0] + transx,
2370N/A spanBox[1] + transy,
2370N/A spanBox[2] - spanBox[0],
2370N/A spanBox[3] - spanBox[1]);
2370N/A }
2370N/A tileManager.fillMask(((XRSurfaceData) sg2d.surfaceData));
2370N/A } finally {
2370N/A SunToolkit.awtUnlock();
2370N/A }
2370N/A }
2370N/A
2370N/A public void draw(SunGraphics2D sg2d, Shape s) {
2370N/A if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) {
2370N/A Path2D.Float p2df;
2370N/A int transx, transy;
2370N/A if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {
2370N/A if (s instanceof Path2D.Float) {
2370N/A p2df = (Path2D.Float) s;
2370N/A } else {
2370N/A p2df = new Path2D.Float(s);
2370N/A }
2370N/A transx = sg2d.transX;
2370N/A transy = sg2d.transY;
2370N/A } else {
2370N/A p2df = new Path2D.Float(s, sg2d.transform);
2370N/A transx = 0;
2370N/A transy = 0;
2370N/A }
2370N/A drawPath(sg2d, p2df, transx, transy);
2370N/A } else if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM) {
2370N/A ShapeSpanIterator si = LoopPipe.getStrokeSpans(sg2d, s);
2370N/A try {
2370N/A fillSpans(sg2d, si, 0, 0);
2370N/A } finally {
2370N/A si.dispose();
2370N/A }
2370N/A } else {
2370N/A fill(sg2d, sg2d.stroke.createStrokedShape(s));
2370N/A }
2370N/A }
2370N/A
2370N/A public void fill(SunGraphics2D sg2d, Shape s) {
2370N/A int transx, transy;
2370N/A
2370N/A if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) {
2370N/A // Here we are able to use fillPath() for
2370N/A // high-quality fills.
2370N/A Path2D.Float p2df;
2370N/A if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {
2370N/A if (s instanceof Path2D.Float) {
2370N/A p2df = (Path2D.Float) s;
2370N/A } else {
2370N/A p2df = new Path2D.Float(s);
2370N/A }
2370N/A transx = sg2d.transX;
2370N/A transy = sg2d.transY;
2370N/A } else {
2370N/A p2df = new Path2D.Float(s, sg2d.transform);
2370N/A transx = 0;
2370N/A transy = 0;
2370N/A }
2370N/A fillPath(sg2d, p2df, transx, transy);
2370N/A return;
2370N/A }
2370N/A
2370N/A AffineTransform at;
2370N/A if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {
2370N/A // Transform (translation) will be done by FillSpans
2370N/A at = null;
2370N/A transx = sg2d.transX;
2370N/A transy = sg2d.transY;
2370N/A } else {
2370N/A // Transform will be done by the PathIterator
2370N/A at = sg2d.transform;
2370N/A transx = transy = 0;
2370N/A }
2370N/A
2370N/A ShapeSpanIterator ssi = LoopPipe.getFillSSI(sg2d);
2370N/A try {
2370N/A // Subtract transx/y from the SSI clip to match the
2370N/A // (potentially untranslated) geometry fed to it
2370N/A Region clip = sg2d.getCompClip();
2370N/A ssi.setOutputAreaXYXY(clip.getLoX() - transx,
2370N/A clip.getLoY() - transy,
2370N/A clip.getHiX() - transx,
2370N/A clip.getHiY() - transy);
2370N/A ssi.appendPath(s.getPathIterator(at));
2370N/A fillSpans(sg2d, ssi, transx, transy);
2370N/A } finally {
2370N/A ssi.dispose();
2370N/A }
2370N/A }
2370N/A}