Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/java2d/xr/XRRenderer.java
32288 views
/*1* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.java2d.xr;2627import java.awt.*;28import java.awt.geom.*;29import sun.awt.SunToolkit;30import sun.java2d.InvalidPipeException;31import sun.java2d.SunGraphics2D;32import sun.java2d.loops.*;33import sun.java2d.pipe.Region;34import sun.java2d.pipe.PixelDrawPipe;35import sun.java2d.pipe.PixelFillPipe;36import sun.java2d.pipe.ShapeDrawPipe;37import sun.java2d.pipe.SpanIterator;38import sun.java2d.pipe.ShapeSpanIterator;39import sun.java2d.pipe.LoopPipe;4041import static sun.java2d.xr.XRUtils.clampToShort;42import static sun.java2d.xr.XRUtils.clampToUShort;4344/**45* XRender provides only accalerated rectangles. To emulate higher "order"46* geometry we have to pass everything else to DoPath/FillSpans.47*48* TODO: DrawRect could be instrified49*50* @author Clemens Eisserer51*/5253public class XRRenderer implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe {54XRDrawHandler drawHandler;55MaskTileManager tileManager;56XRDrawLine lineGen;57GrowableRectArray rectBuffer;5859public XRRenderer(MaskTileManager tileManager) {60this.tileManager = tileManager;61this.rectBuffer = tileManager.getMainTile().getRects();6263this.drawHandler = new XRDrawHandler();64this.lineGen = new XRDrawLine();65}6667/**68* Common validate method, used by all XRRender functions to validate the69* destination context.70*/71private final void validateSurface(SunGraphics2D sg2d) {72XRSurfaceData xrsd;73try {74xrsd = (XRSurfaceData) sg2d.surfaceData;75} catch (ClassCastException e) {76throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);77}78xrsd.validateAsDestination(sg2d, sg2d.getCompClip());79xrsd.maskBuffer.validateCompositeState(sg2d.composite, sg2d.transform,80sg2d.paint, sg2d);81}8283public void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2) {84Region compClip = sg2d.getCompClip();85int transX1 = Region.clipAdd(x1, sg2d.transX);86int transY1 = Region.clipAdd(y1, sg2d.transY);87int transX2 = Region.clipAdd(x2, sg2d.transX);88int transY2 = Region.clipAdd(y2, sg2d.transY);8990SunToolkit.awtLock();91try {92validateSurface(sg2d);93lineGen.rasterizeLine(rectBuffer, transX1, transY1,94transX2, transY2, compClip.getLoX(), compClip.getLoY(),95compClip.getHiX(), compClip.getHiY(), true, true);96tileManager.fillMask((XRSurfaceData) sg2d.surfaceData);97} finally {98SunToolkit.awtUnlock();99}100}101102public void drawRect(SunGraphics2D sg2d,103int x, int y, int width, int height) {104draw(sg2d, new Rectangle2D.Float(x, y, width, height));105}106107public void drawPolyline(SunGraphics2D sg2d,108int xpoints[], int ypoints[], int npoints) {109Path2D.Float p2d = new Path2D.Float();110if (npoints > 1) {111p2d.moveTo(xpoints[0], ypoints[0]);112for (int i = 1; i < npoints; i++) {113p2d.lineTo(xpoints[i], ypoints[i]);114}115}116117draw(sg2d, p2d);118}119120public void drawPolygon(SunGraphics2D sg2d,121int xpoints[], int ypoints[], int npoints) {122draw(sg2d, new Polygon(xpoints, ypoints, npoints));123}124125public void fillRect(SunGraphics2D sg2d, int x, int y, int width, int height) {126x = Region.clipAdd(x, sg2d.transX);127y = Region.clipAdd(y, sg2d.transY);128129/*130* Limit x/y to signed short, width/height to unsigned short,131* to match the X11 coordinate limits for rectangles.132* Correct width/height in case x/y have been modified by clipping.133*/134if (x > Short.MAX_VALUE || y > Short.MAX_VALUE) {135return;136}137138int x2 = Region.dimAdd(x, width);139int y2 = Region.dimAdd(y, height);140141if (x2 < Short.MIN_VALUE || y2 < Short.MIN_VALUE) {142return;143}144145x = clampToShort(x);146y = clampToShort(y);147width = clampToUShort(x2 - x);148height = clampToUShort(y2 - y);149150if (width == 0 || height == 0) {151return;152}153154SunToolkit.awtLock();155try {156validateSurface(sg2d);157rectBuffer.pushRectValues(x, y, width, height);158tileManager.fillMask((XRSurfaceData) sg2d.surfaceData);159} finally {160SunToolkit.awtUnlock();161}162}163164public void fillPolygon(SunGraphics2D sg2d,165int xpoints[], int ypoints[], int npoints) {166fill(sg2d, new Polygon(xpoints, ypoints, npoints));167}168169public void drawRoundRect(SunGraphics2D sg2d,170int x, int y, int width, int height,171int arcWidth, int arcHeight) {172draw(sg2d, new RoundRectangle2D.Float(x, y, width, height,173arcWidth, arcHeight));174}175176public void fillRoundRect(SunGraphics2D sg2d, int x, int y,177int width, int height,178int arcWidth, int arcHeight) {179fill(sg2d, new RoundRectangle2D.Float(x, y, width, height,180arcWidth, arcHeight));181}182183public void drawOval(SunGraphics2D sg2d,184int x, int y, int width, int height) {185draw(sg2d, new Ellipse2D.Float(x, y, width, height));186}187188public void fillOval(SunGraphics2D sg2d,189int x, int y, int width, int height) {190fill(sg2d, new Ellipse2D.Float(x, y, width, height));191}192193public void drawArc(SunGraphics2D sg2d,194int x, int y, int width, int height,195int startAngle, int arcAngle) {196draw(sg2d, new Arc2D.Float(x, y, width, height,197startAngle, arcAngle, Arc2D.OPEN));198}199200public void fillArc(SunGraphics2D sg2d,201int x, int y, int width, int height,202int startAngle, int arcAngle) {203fill(sg2d, new Arc2D.Float(x, y, width, height,204startAngle, arcAngle, Arc2D.PIE));205}206207private class XRDrawHandler extends ProcessPath.DrawHandler {208DirtyRegion region;209210XRDrawHandler() {211// these are bogus values; the caller will use validate()212// to ensure that they are set properly prior to each usage213super(0, 0, 0, 0);214this.region = new DirtyRegion();215}216217/**218* This method needs to be called prior to each draw/fillPath()219* operation to ensure the clip bounds are up to date.220*/221void validate(SunGraphics2D sg2d) {222Region clip = sg2d.getCompClip();223setBounds(clip.getLoX(), clip.getLoY(),224clip.getHiX(), clip.getHiY(), sg2d.strokeHint);225validateSurface(sg2d);226}227228public void drawLine(int x1, int y1, int x2, int y2) {229region.setDirtyLineRegion(x1, y1, x2, y2);230int xDiff = region.x2 - region.x;231int yDiff = region.y2 - region.y;232233if (xDiff == 0 || yDiff == 0) {234// horizontal / diagonal lines can be represented by a single235// rectangle236rectBuffer.pushRectValues(region.x, region.y, region.x2 - region.x237+ 1, region.y2 - region.y + 1);238} else if (xDiff == 1 && yDiff == 1) {239// fast path for pattern commonly generated by240// ProcessPath.DrawHandler241rectBuffer.pushRectValues(x1, y1, 1, 1);242rectBuffer.pushRectValues(x2, y2, 1, 1);243} else {244lineGen.rasterizeLine(rectBuffer, x1, y1, x2, y2, 0, 0,2450, 0, false, false);246}247}248249public void drawPixel(int x, int y) {250rectBuffer.pushRectValues(x, y, 1, 1);251}252253public void drawScanline(int x1, int x2, int y) {254rectBuffer.pushRectValues(x1, y, x2 - x1 + 1, 1);255}256}257258protected void drawPath(SunGraphics2D sg2d, Path2D.Float p2df,259int transx, int transy) {260SunToolkit.awtLock();261try {262validateSurface(sg2d);263drawHandler.validate(sg2d);264ProcessPath.drawPath(drawHandler, p2df, transx, transy);265tileManager.fillMask(((XRSurfaceData) sg2d.surfaceData));266} finally {267SunToolkit.awtUnlock();268}269}270271protected void fillPath(SunGraphics2D sg2d, Path2D.Float p2df,272int transx, int transy) {273SunToolkit.awtLock();274try {275validateSurface(sg2d);276drawHandler.validate(sg2d);277ProcessPath.fillPath(drawHandler, p2df, transx, transy);278tileManager.fillMask(((XRSurfaceData) sg2d.surfaceData));279} finally {280SunToolkit.awtUnlock();281}282}283284protected void fillSpans(SunGraphics2D sg2d, SpanIterator si,285int transx, int transy) {286SunToolkit.awtLock();287try {288validateSurface(sg2d);289int[] spanBox = new int[4];290while (si.nextSpan(spanBox)) {291rectBuffer.pushRectValues(spanBox[0] + transx,292spanBox[1] + transy,293spanBox[2] - spanBox[0],294spanBox[3] - spanBox[1]);295}296tileManager.fillMask(((XRSurfaceData) sg2d.surfaceData));297} finally {298SunToolkit.awtUnlock();299}300}301302public void draw(SunGraphics2D sg2d, Shape s) {303if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) {304Path2D.Float p2df;305int transx, transy;306if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {307if (s instanceof Path2D.Float) {308p2df = (Path2D.Float) s;309} else {310p2df = new Path2D.Float(s);311}312transx = sg2d.transX;313transy = sg2d.transY;314} else {315p2df = new Path2D.Float(s, sg2d.transform);316transx = 0;317transy = 0;318}319drawPath(sg2d, p2df, transx, transy);320} else if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM) {321ShapeSpanIterator si = LoopPipe.getStrokeSpans(sg2d, s);322try {323fillSpans(sg2d, si, 0, 0);324} finally {325si.dispose();326}327} else {328fill(sg2d, sg2d.stroke.createStrokedShape(s));329}330}331332public void fill(SunGraphics2D sg2d, Shape s) {333int transx, transy;334335if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) {336// Here we are able to use fillPath() for337// high-quality fills.338Path2D.Float p2df;339if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {340if (s instanceof Path2D.Float) {341p2df = (Path2D.Float) s;342} else {343p2df = new Path2D.Float(s);344}345transx = sg2d.transX;346transy = sg2d.transY;347} else {348p2df = new Path2D.Float(s, sg2d.transform);349transx = 0;350transy = 0;351}352fillPath(sg2d, p2df, transx, transy);353return;354}355356AffineTransform at;357if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {358// Transform (translation) will be done by FillSpans359at = null;360transx = sg2d.transX;361transy = sg2d.transY;362} else {363// Transform will be done by the PathIterator364at = sg2d.transform;365transx = transy = 0;366}367368ShapeSpanIterator ssi = LoopPipe.getFillSSI(sg2d);369try {370// Subtract transx/y from the SSI clip to match the371// (potentially untranslated) geometry fed to it372Region clip = sg2d.getCompClip();373ssi.setOutputAreaXYXY(clip.getLoX() - transx,374clip.getLoY() - transy,375clip.getHiX() - transx,376clip.getHiY() - transy);377ssi.appendPath(s.getPathIterator(at));378fillSpans(sg2d, ssi, transx, transy);379} finally {380ssi.dispose();381}382}383}384385386