601 lines · 20.4 KB · Java
RawDownload
/* * Copyright (c) 2005, 2008, 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.pipe; import java.awt.BasicStroke;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.Path2D;import java.awt.geom.IllegalPathStateException;import java.awt.geom.PathIterator;import java.awt.geom.Rectangle2D;import java.awt.geom.RoundRectangle2D;import sun.java2d.SunGraphics2D;import sun.java2d.loops.ProcessPath;import static sun.java2d.pipe.BufferedOpCodes.*; /** * Base class for enqueuing rendering operations in a single-threaded * rendering environment.  Instead of each operation being rendered * immediately by the underlying graphics library, the operation will be * added to the provided RenderQueue, which will be processed at a later * time by a single thread. * * This class provides implementations of drawLine(), drawRect(), drawPoly(), * fillRect(), draw(Shape), and fill(Shape), which are useful for a * hardware-accelerated renderer.  The other draw*() and fill*() methods * simply delegate to draw(Shape) and fill(Shape), respectively. */public abstract class BufferedRenderPipe    implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe, ParallelogramPipe{    ParallelogramPipe aapgrampipe = new AAParallelogramPipe();     static final int BYTES_PER_POLY_POINT = 8;    static final int BYTES_PER_SCANLINE = 12;    static final int BYTES_PER_SPAN = 16;     protected RenderQueue rq;    protected RenderBuffer buf;    private BufferedDrawHandler drawHandler;     public BufferedRenderPipe(RenderQueue rq) {        this.rq = rq;        this.buf = rq.getBuffer();        this.drawHandler = new BufferedDrawHandler();    }     public ParallelogramPipe getAAParallelogramPipe() {        return aapgrampipe;    }     /**     * Validates the state in the provided SunGraphics2D object and sets up     * any special resources for this operation (e.g. enabling gradient     * shading).     */    protected abstract void validateContext(SunGraphics2D sg2d);    protected abstract void validateContextAA(SunGraphics2D sg2d);     public void drawLine(SunGraphics2D sg2d,                         int x1, int y1, int x2, int y2)    {        int transx = sg2d.transX;        int transy = sg2d.transY;        rq.lock();        try {            validateContext(sg2d);            rq.ensureCapacity(20);            buf.putInt(DRAW_LINE);            buf.putInt(x1 + transx);            buf.putInt(y1 + transy);            buf.putInt(x2 + transx);            buf.putInt(y2 + transy);        } finally {            rq.unlock();        }    }     public void drawRect(SunGraphics2D sg2d,                         int x, int y, int width, int height)    {        rq.lock();        try {            validateContext(sg2d);            rq.ensureCapacity(20);            buf.putInt(DRAW_RECT);            buf.putInt(x + sg2d.transX);            buf.putInt(y + sg2d.transY);            buf.putInt(width);            buf.putInt(height);        } finally {            rq.unlock();        }    }     public void fillRect(SunGraphics2D sg2d,                         int x, int y, int width, int height)    {        rq.lock();        try {            validateContext(sg2d);            rq.ensureCapacity(20);            buf.putInt(FILL_RECT);            buf.putInt(x + sg2d.transX);            buf.putInt(y + sg2d.transY);            buf.putInt(width);            buf.putInt(height);        } finally {            rq.unlock();        }    }     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));    }     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));    }     public void drawOval(SunGraphics2D sg2d,                         int x, int y, int width, int height)    {        draw(sg2d, new Ellipse2D.Float(x, y, width, height));    }     public void fillOval(SunGraphics2D sg2d,                         int x, int y, int width, int height)    {        fill(sg2d, new Ellipse2D.Float(x, y, width, height));    }     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));    }     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));    }     protected void drawPoly(final SunGraphics2D sg2d,                            final int[] xPoints, final int[] yPoints,                            final int nPoints, final boolean isClosed)    {        if (xPoints == null || yPoints == null) {            throw new NullPointerException("coordinate array");        }        if (xPoints.length < nPoints || yPoints.length < nPoints) {            throw new ArrayIndexOutOfBoundsException("coordinate array");        }         if (nPoints < 2) {            // render nothing            return;        } else if (nPoints == 2 && !isClosed) {            // render a simple line            drawLine(sg2d, xPoints[0], yPoints[0], xPoints[1], yPoints[1]);            return;        }         rq.lock();        try {            validateContext(sg2d);             int pointBytesRequired = nPoints * BYTES_PER_POLY_POINT;            int totalBytesRequired = 20 + pointBytesRequired;             if (totalBytesRequired <= buf.capacity()) {                if (totalBytesRequired > buf.remaining()) {                    // process the queue first and then enqueue the points                    rq.flushNow();                }                buf.putInt(DRAW_POLY);                // enqueue parameters                buf.putInt(nPoints);                buf.putInt(isClosed ? 1 : 0);                buf.putInt(sg2d.transX);                buf.putInt(sg2d.transY);                // enqueue the points                buf.put(xPoints, 0, nPoints);                buf.put(yPoints, 0, nPoints);            } else {                // queue is too small to accomodate all points; perform the                // operation directly on the queue flushing thread                rq.flushAndInvokeNow(new Runnable() {                    public void run() {                        drawPoly(xPoints, yPoints,                                 nPoints, isClosed,                                 sg2d.transX, sg2d.transY);                    }                });            }        } finally {            rq.unlock();        }    }     protected abstract void drawPoly(int[] xPoints, int[] yPoints,                                     int nPoints, boolean isClosed,                                     int transX, int transY);     public void drawPolyline(SunGraphics2D sg2d,                             int[] xPoints, int[] yPoints,                             int nPoints)    {        drawPoly(sg2d, xPoints, yPoints, nPoints, false);    }     public void drawPolygon(SunGraphics2D sg2d,                            int[] xPoints, int[] yPoints,                            int nPoints)    {        drawPoly(sg2d, xPoints, yPoints, nPoints, true);    }     public void fillPolygon(SunGraphics2D sg2d,                            int[] xPoints, int[] yPoints,                            int nPoints)    {        fill(sg2d, new Polygon(xPoints, yPoints, nPoints));    }     private class BufferedDrawHandler        extends ProcessPath.DrawHandler    {        BufferedDrawHandler() {            // these are bogus values; the caller will use validate()            // to ensure that they are set properly prior to each usage            super(0, 0, 0, 0);        }         /**         * This method needs to be called prior to each draw/fillPath()         * operation to ensure the clip bounds are up to date.         */        void validate(SunGraphics2D sg2d) {            Region clip = sg2d.getCompClip();            setBounds(clip.getLoX(), clip.getLoY(),                      clip.getHiX(), clip.getHiY(),                      sg2d.strokeHint);        }         /**         * drawPath() support...         */         public void drawLine(int x1, int y1, int x2, int y2) {            // assert rq.lock.isHeldByCurrentThread();            rq.ensureCapacity(20);            buf.putInt(DRAW_LINE);            buf.putInt(x1);            buf.putInt(y1);            buf.putInt(x2);            buf.putInt(y2);        }         public void drawPixel(int x, int y) {            // assert rq.lock.isHeldByCurrentThread();            rq.ensureCapacity(12);            buf.putInt(DRAW_PIXEL);            buf.putInt(x);            buf.putInt(y);        }         /**         * fillPath() support...         */         private int scanlineCount;        private int scanlineCountIndex;        private int remainingScanlines;         private void resetFillPath() {            buf.putInt(DRAW_SCANLINES);            scanlineCountIndex = buf.position();            buf.putInt(0);            scanlineCount = 0;            remainingScanlines = buf.remaining() / BYTES_PER_SCANLINE;        }         private void updateScanlineCount() {            buf.putInt(scanlineCountIndex, scanlineCount);        }         /**         * Called from fillPath() to indicate that we are about to         * start issuing drawScanline() calls.         */        public void startFillPath() {            rq.ensureCapacity(20); // to ensure room for at least a scanline            resetFillPath();        }         public void drawScanline(int x1, int x2, int y) {            if (remainingScanlines == 0) {                updateScanlineCount();                rq.flushNow();                resetFillPath();            }            buf.putInt(x1);            buf.putInt(x2);            buf.putInt(y);            scanlineCount++;            remainingScanlines--;        }         /**         * Called from fillPath() to indicate that we are done         * issuing drawScanline() calls.         */        public void endFillPath() {            updateScanlineCount();        }    }     protected void drawPath(SunGraphics2D sg2d,                            Path2D.Float p2df, int transx, int transy)    {        rq.lock();        try {            validateContext(sg2d);            drawHandler.validate(sg2d);            ProcessPath.drawPath(drawHandler, p2df, transx, transy);        } finally {            rq.unlock();        }    }     protected void fillPath(SunGraphics2D sg2d,                            Path2D.Float p2df, int transx, int transy)    {        rq.lock();        try {            validateContext(sg2d);            drawHandler.validate(sg2d);            drawHandler.startFillPath();            ProcessPath.fillPath(drawHandler, p2df, transx, transy);            drawHandler.endFillPath();        } finally {            rq.unlock();        }    }     private native int fillSpans(RenderQueue rq, long buf,                                 int pos, int limit,                                 SpanIterator si, long iterator,                                 int transx, int transy);     protected void fillSpans(SunGraphics2D sg2d, SpanIterator si,                             int transx, int transy)    {        rq.lock();        try {            validateContext(sg2d);            rq.ensureCapacity(24); // so that we have room for at least a span            int newpos = fillSpans(rq, buf.getAddress(),                                   buf.position(), buf.capacity(),                                   si, si.getNativeIterator(),                                   transx, transy);            buf.position(newpos);        } finally {            rq.unlock();        }    }     public void fillParallelogram(SunGraphics2D sg2d,                                  double ux1, double uy1,                                  double ux2, double uy2,                                  double x, double y,                                  double dx1, double dy1,                                  double dx2, double dy2)    {        rq.lock();        try {            validateContext(sg2d);            rq.ensureCapacity(28);            buf.putInt(FILL_PARALLELOGRAM);            buf.putFloat((float) x);            buf.putFloat((float) y);            buf.putFloat((float) dx1);            buf.putFloat((float) dy1);            buf.putFloat((float) dx2);            buf.putFloat((float) dy2);        } finally {            rq.unlock();        }    }     public void drawParallelogram(SunGraphics2D sg2d,                                  double ux1, double uy1,                                  double ux2, double uy2,                                  double x, double y,                                  double dx1, double dy1,                                  double dx2, double dy2,                                  double lw1, double lw2)    {        rq.lock();        try {            validateContext(sg2d);            rq.ensureCapacity(36);            buf.putInt(DRAW_PARALLELOGRAM);            buf.putFloat((float) x);            buf.putFloat((float) y);            buf.putFloat((float) dx1);            buf.putFloat((float) dy1);            buf.putFloat((float) dx2);            buf.putFloat((float) dy2);            buf.putFloat((float) lw1);            buf.putFloat((float) lw2);        } finally {            rq.unlock();        }    }     private class AAParallelogramPipe implements ParallelogramPipe {        public void fillParallelogram(SunGraphics2D sg2d,                                      double ux1, double uy1,                                      double ux2, double uy2,                                      double x, double y,                                      double dx1, double dy1,                                      double dx2, double dy2)        {            rq.lock();            try {                validateContextAA(sg2d);                rq.ensureCapacity(28);                buf.putInt(FILL_AAPARALLELOGRAM);                buf.putFloat((float) x);                buf.putFloat((float) y);                buf.putFloat((float) dx1);                buf.putFloat((float) dy1);                buf.putFloat((float) dx2);                buf.putFloat((float) dy2);            } finally {                rq.unlock();            }        }         public void drawParallelogram(SunGraphics2D sg2d,                                      double ux1, double uy1,                                      double ux2, double uy2,                                      double x, double y,                                      double dx1, double dy1,                                      double dx2, double dy2,                                      double lw1, double lw2)        {            rq.lock();            try {                validateContextAA(sg2d);                rq.ensureCapacity(36);                buf.putInt(DRAW_AAPARALLELOGRAM);                buf.putFloat((float) x);                buf.putFloat((float) y);                buf.putFloat((float) dx1);                buf.putFloat((float) dy1);                buf.putFloat((float) dx2);

Lines 1–500 of 601.