Path: blob/master/src/java.desktop/share/classes/sun/java2d/pipe/LoopPipe.java
41159 views
/*1* Copyright (c) 1999, 2021, 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.pipe;2627import java.awt.Shape;28import java.awt.BasicStroke;29import java.awt.geom.AffineTransform;30import java.awt.geom.PathIterator;31import java.awt.geom.RoundRectangle2D;32import java.awt.geom.Ellipse2D;33import java.awt.geom.Arc2D;34import java.awt.geom.Path2D;35import sun.java2d.SunGraphics2D;36import sun.java2d.SurfaceData;37import sun.java2d.loops.FillParallelogram;38import sun.java2d.loops.DrawParallelogram;39import sun.awt.SunHints;4041public class LoopPipe42implements PixelDrawPipe,43PixelFillPipe,44ParallelogramPipe,45ShapeDrawPipe,46LoopBasedPipe47{48static final RenderingEngine RenderEngine = RenderingEngine.getInstance();4950public void drawLine(SunGraphics2D sg2d,51int x1, int y1, int x2, int y2)52{53int tX = sg2d.transX;54int tY = sg2d.transY;55sg2d.loops.drawLineLoop.DrawLine(sg2d, sg2d.getSurfaceData(),56x1 + tX, y1 + tY,57x2 + tX, y2 + tY);58}5960public void drawRect(SunGraphics2D sg2d,61int x, int y, int width, int height)62{63sg2d.loops.drawRectLoop.DrawRect(sg2d, sg2d.getSurfaceData(),64x + sg2d.transX,65y + sg2d.transY,66width, height);67}6869public void drawRoundRect(SunGraphics2D sg2d,70int x, int y, int width, int height,71int arcWidth, int arcHeight)72{73sg2d.shapepipe.draw(sg2d,74new RoundRectangle2D.Float(x, y, width, height,75arcWidth, arcHeight));76}7778public void drawOval(SunGraphics2D sg2d,79int x, int y, int width, int height)80{81sg2d.shapepipe.draw(sg2d, new Ellipse2D.Float(x, y, width, height));82}8384public void drawArc(SunGraphics2D sg2d,85int x, int y, int width, int height,86int startAngle, int arcAngle)87{88sg2d.shapepipe.draw(sg2d, new Arc2D.Float(x, y, width, height,89startAngle, arcAngle,90Arc2D.OPEN));91}9293public void drawPolyline(SunGraphics2D sg2d,94int[] xPoints, int[] yPoints,95int nPoints)96{97int[] nPointsArray = { nPoints };98sg2d.loops.drawPolygonsLoop.DrawPolygons(sg2d, sg2d.getSurfaceData(),99xPoints, yPoints,100nPointsArray, 1,101sg2d.transX, sg2d.transY,102false);103}104105public void drawPolygon(SunGraphics2D sg2d,106int[] xPoints, int[] yPoints,107int nPoints)108{109int[] nPointsArray = { nPoints };110sg2d.loops.drawPolygonsLoop.DrawPolygons(sg2d, sg2d.getSurfaceData(),111xPoints, yPoints,112nPointsArray, 1,113sg2d.transX, sg2d.transY,114true);115}116117public void fillRect(SunGraphics2D sg2d,118int x, int y, int width, int height)119{120sg2d.loops.fillRectLoop.FillRect(sg2d, sg2d.getSurfaceData(),121x + sg2d.transX,122y + sg2d.transY,123width, height);124}125126public void fillRoundRect(SunGraphics2D sg2d,127int x, int y, int width, int height,128int arcWidth, int arcHeight)129{130sg2d.shapepipe.fill(sg2d,131new RoundRectangle2D.Float(x, y, width, height,132arcWidth, arcHeight));133}134135public void fillOval(SunGraphics2D sg2d,136int x, int y, int width, int height)137{138sg2d.shapepipe.fill(sg2d, new Ellipse2D.Float(x, y, width, height));139}140141public void fillArc(SunGraphics2D sg2d,142int x, int y, int width, int height,143int startAngle, int arcAngle)144{145sg2d.shapepipe.fill(sg2d, new Arc2D.Float(x, y, width, height,146startAngle, arcAngle,147Arc2D.PIE));148}149150public void fillPolygon(SunGraphics2D sg2d,151int[] xPoints, int[] yPoints,152int nPoints)153{154ShapeSpanIterator sr = getFillSSI(sg2d);155156try {157sr.setOutputArea(sg2d.getCompClip());158sr.appendPoly(xPoints, yPoints, nPoints, sg2d.transX, sg2d.transY);159fillSpans(sg2d, sr);160} finally {161sr.dispose();162}163}164165166public void draw(SunGraphics2D sg2d, Shape s) {167if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) {168Path2D.Float p2df;169int transX;170int transY;171if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {172if (s instanceof Path2D.Float) {173p2df = (Path2D.Float)s;174} else {175p2df = new Path2D.Float(s);176}177transX = sg2d.transX;178transY = sg2d.transY;179} else {180p2df = new Path2D.Float(s, sg2d.transform);181transX = 0;182transY = 0;183}184sg2d.loops.drawPathLoop.DrawPath(sg2d, sg2d.getSurfaceData(),185transX, transY, p2df);186return;187}188189if (sg2d.strokeState == SunGraphics2D.STROKE_CUSTOM) {190fill(sg2d, sg2d.stroke.createStrokedShape(s));191return;192}193194ShapeSpanIterator sr = getStrokeSpans(sg2d, s);195196try {197fillSpans(sg2d, sr);198} finally {199sr.dispose();200}201}202203/**204* Return a ShapeSpanIterator instance that normalizes as205* appropriate for a fill operation as per the settings in206* the specified SunGraphics2D object.207*208* The ShapeSpanIterator will be newly constructed and ready209* to start taking in geometry.210*211* Note that the caller is responsible for calling dispose()212* on the returned ShapeSpanIterator inside a try/finally block:213* <pre>214* ShapeSpanIterator ssi = LoopPipe.getFillSSI(sg2d);215* try {216* ssi.setOutputArea(clip);217* ssi.appendPath(...); // or appendPoly218* // iterate the spans from ssi and operate on them219* } finally {220* ssi.dispose();221* }222* </pre>223*/224public static ShapeSpanIterator getFillSSI(SunGraphics2D sg2d) {225boolean adjust = ((sg2d.stroke instanceof BasicStroke) &&226sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE);227return new ShapeSpanIterator(adjust);228}229230/*231* Return a ShapeSpanIterator ready to iterate the spans of the wide232* outline of Shape s using the attributes of the SunGraphics2D233* object.234*235* The ShapeSpanIterator returned will be fully constructed236* and filled with the geometry from the Shape widened by the237* appropriate BasicStroke and normalization parameters taken238* from the SunGraphics2D object and be ready to start returning239* spans.240*241* Note that the caller is responsible for calling dispose()242* on the returned ShapeSpanIterator inside a try/finally block.243* <pre>244* ShapeSpanIterator ssi = LoopPipe.getStrokeSpans(sg2d, s);245* try {246* // iterate the spans from ssi and operate on them247* } finally {248* ssi.dispose();249* }250* </pre>251*252* REMIND: This should return a SpanIterator interface object253* but the caller needs to dispose() the object and that method254* is only on ShapeSpanIterator.255* TODO: Add a dispose() method to the SpanIterator interface.256*/257public static ShapeSpanIterator getStrokeSpans(SunGraphics2D sg2d,258Shape s)259{260ShapeSpanIterator sr = new ShapeSpanIterator(false);261262try {263final Region clip = sg2d.getCompClip();264sr.setOutputArea(clip);265sr.setRule(PathIterator.WIND_NON_ZERO);266267BasicStroke bs = (BasicStroke) sg2d.stroke;268boolean thin = (sg2d.strokeState <= SunGraphics2D.STROKE_THINDASHED);269boolean normalize =270(sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE);271272RenderEngine.strokeTo(s,273sg2d.transform, clip, bs,274thin, normalize, false, sr);275} catch (Throwable t) {276sr.dispose();277sr = null;278throw new InternalError("Unable to Stroke shape ("+279t.getMessage()+")", t);280}281return sr;282}283284public void fill(SunGraphics2D sg2d, Shape s) {285if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) {286Path2D.Float p2df;287int transX;288int transY;289if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {290if (s instanceof Path2D.Float) {291p2df = (Path2D.Float)s;292} else {293p2df = new Path2D.Float(s);294}295transX = sg2d.transX;296transY = sg2d.transY;297} else {298p2df = new Path2D.Float(s, sg2d.transform);299transX = 0;300transY = 0;301}302sg2d.loops.fillPathLoop.FillPath(sg2d, sg2d.getSurfaceData(),303transX, transY, p2df);304return;305}306307ShapeSpanIterator sr = getFillSSI(sg2d);308try {309sr.setOutputArea(sg2d.getCompClip());310AffineTransform at =311((sg2d.transformState == SunGraphics2D.TRANSFORM_ISIDENT)312? null313: sg2d.transform);314sr.appendPath(s.getPathIterator(at));315fillSpans(sg2d, sr);316} finally {317sr.dispose();318}319}320321private static void fillSpans(SunGraphics2D sg2d, SpanIterator si) {322// REMIND: Eventually, the plan is that it will not be possible for323// fs to be null since the FillSpans loop will be the fundamental324// loop implemented for any destination type...325if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {326si = sg2d.clipRegion.filter(si);327// REMIND: Region.filter produces a Java-only iterator328// with no native counterpart...329} else {330sun.java2d.loops.FillSpans fs = sg2d.loops.fillSpansLoop;331if (fs != null) {332fs.FillSpans(sg2d, sg2d.getSurfaceData(), si);333return;334}335}336int[] spanbox = new int[4];337SurfaceData sd = sg2d.getSurfaceData();338while (si.nextSpan(spanbox)) {339int x = spanbox[0];340int y = spanbox[1];341int w = spanbox[2] - x;342int h = spanbox[3] - y;343sg2d.loops.fillRectLoop.FillRect(sg2d, sd, x, y, w, h);344}345}346347public void fillParallelogram(SunGraphics2D sg2d,348double ux1, double uy1,349double ux2, double uy2,350double x, double y,351double dx1, double dy1,352double dx2, double dy2)353{354FillParallelogram fp = sg2d.loops.fillParallelogramLoop;355fp.FillParallelogram(sg2d, sg2d.getSurfaceData(),356x, y, dx1, dy1, dx2, dy2);357}358359public void drawParallelogram(SunGraphics2D sg2d,360double ux1, double uy1,361double ux2, double uy2,362double x, double y,363double dx1, double dy1,364double dx2, double dy2,365double lw1, double lw2)366{367DrawParallelogram dp = sg2d.loops.drawParallelogramLoop;368dp.DrawParallelogram(sg2d, sg2d.getSurfaceData(),369x, y, dx1, dy1, dx2, dy2, lw1, lw2);370}371}372373374