Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/java2d/pipe/AAShapePipe.java
38918 views
/*1* Copyright (c) 1997, 2016, 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*/24package sun.java2d.pipe;2526import java.awt.BasicStroke;27import java.awt.Rectangle;28import java.awt.Shape;29import java.awt.geom.Rectangle2D;30import java.util.concurrent.ConcurrentLinkedQueue;31import sun.awt.SunHints;32import sun.java2d.ReentrantContext;33import sun.java2d.ReentrantContextProvider;34import sun.java2d.ReentrantContextProviderTL;35import sun.java2d.SunGraphics2D;3637/**38* This class is used to convert raw geometry into 8-bit alpha tiles39* using an AATileGenerator for application by the next stage of40* the pipeline.41* This class sets up the Generator and computes the alpha tiles42* and then passes them on to a CompositePipe object for painting.43*/44public final class AAShapePipe45implements ShapeDrawPipe, ParallelogramPipe46{47static final RenderingEngine renderengine = RenderingEngine.getInstance();4849// Per-thread TileState (~1K very small so do not use any Weak Reference)50private static final ReentrantContextProvider<TileState> tileStateProvider =51new ReentrantContextProviderTL<TileState>(52ReentrantContextProvider.REF_HARD)53{54@Override55protected TileState newContext() {56return new TileState();57}58};5960final CompositePipe outpipe;6162public AAShapePipe(CompositePipe pipe) {63outpipe = pipe;64}6566@Override67public void draw(SunGraphics2D sg, Shape s) {68final BasicStroke bs;6970if (sg.stroke instanceof BasicStroke) {71bs = (BasicStroke) sg.stroke;72} else {73s = sg.stroke.createStrokedShape(s);74bs = null;75}7677renderPath(sg, s, bs);78}7980@Override81public void fill(SunGraphics2D sg, Shape s) {82renderPath(sg, s, null);83}8485@Override86public void fillParallelogram(SunGraphics2D sg,87double ux1, double uy1,88double ux2, double uy2,89double x, double y,90double dx1, double dy1,91double dx2, double dy2)92{93final TileState ts = tileStateProvider.acquire();94try {95final int[] abox = ts.abox;9697final AATileGenerator aatg =98renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0,99sg.getCompClip(), abox);100if (aatg != null) {101renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2),102aatg, abox, ts);103}104} finally {105tileStateProvider.release(ts);106}107}108109@Override110public void drawParallelogram(SunGraphics2D sg,111double ux1, double uy1,112double ux2, double uy2,113double x, double y,114double dx1, double dy1,115double dx2, double dy2,116double lw1, double lw2)117{118final TileState ts = tileStateProvider.acquire();119try {120final int[] abox = ts.abox;121122final AATileGenerator aatg =123renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1,124lw2, sg.getCompClip(), abox);125if (aatg != null) {126// Note that bbox is of the original shape, not the wide path.127// This is appropriate for handing to Paint methods...128renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2),129aatg, abox, ts);130}131} finally {132tileStateProvider.release(ts);133}134}135136public void renderPath(SunGraphics2D sg, Shape s, BasicStroke bs) {137final boolean adjust = (bs != null &&138sg.strokeHint != SunHints.INTVAL_STROKE_PURE);139final boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED);140141final TileState ts = tileStateProvider.acquire();142try {143final int[] abox = ts.abox;144145final AATileGenerator aatg =146renderengine.getAATileGenerator(s, sg.transform, sg.getCompClip(),147bs, thin, adjust, abox);148if (aatg != null) {149renderTiles(sg, s, aatg, abox, ts);150}151} finally {152tileStateProvider.release(ts);153}154}155156public void renderTiles(SunGraphics2D sg, Shape s,157final AATileGenerator aatg,158final int[] abox, final TileState ts)159{160Object context = null;161try {162// reentrance: outpipe may also use AAShapePipe:163context = outpipe.startSequence(sg, s,164ts.computeDevBox(abox),165abox);166167// copy of int[] abox as local variables for performance:168final int x0 = abox[0];169final int y0 = abox[1];170final int x1 = abox[2];171final int y1 = abox[3];172173final int tw = aatg.getTileWidth();174final int th = aatg.getTileHeight();175176// get tile from thread local storage:177final byte[] alpha = ts.getAlphaTile(tw * th);178byte[] atile;179180for (int y = y0; y < y1; y += th) {181final int h = Math.min(th, y1 - y);182183for (int x = x0; x < x1; x += tw) {184final int w = Math.min(tw, x1 - x);185186final int a = aatg.getTypicalAlpha();187188if (a == 0x00 || !outpipe.needTile(context, x, y, w, h)) {189aatg.nextTile();190outpipe.skipTile(context, x, y);191continue;192}193if (a == 0xff) {194atile = null;195aatg.nextTile();196} else {197atile = alpha;198aatg.getAlpha(alpha, 0, tw);199}200201outpipe.renderPathTile(context, atile, 0, tw, x, y, w, h);202}203}204} finally {205aatg.dispose();206if (context != null) {207outpipe.endSequence(context);208}209}210}211212// Tile state used by AAShapePipe213static final class TileState extends ReentrantContext {214// cached tile (32 x 32 tile by default)215private byte[] theTile = new byte[32 * 32];216// dirty aabox array217final int[] abox = new int[4];218// dirty bbox rectangle219private final Rectangle dev = new Rectangle();220// dirty bbox rectangle2D.Double221private final Rectangle2D.Double bbox2D = new Rectangle2D.Double();222223byte[] getAlphaTile(int len) {224byte[] t = theTile;225if (t.length < len) {226// create a larger tile and may free current theTile (too small)227theTile = t = new byte[len];228}229return t;230}231232Rectangle computeDevBox(final int[] abox) {233final Rectangle box = this.dev;234box.x = abox[0];235box.y = abox[1];236box.width = abox[2] - abox[0];237box.height = abox[3] - abox[1];238return box;239}240241Rectangle2D computeBBox(double ux1, double uy1,242double ux2, double uy2)243{244if ((ux2 -= ux1) < 0.0) {245ux1 += ux2;246ux2 = -ux2;247}248if ((uy2 -= uy1) < 0.0) {249uy1 += uy2;250uy2 = -uy2;251}252final Rectangle2D.Double box = this.bbox2D;253box.x = ux1;254box.y = uy1;255box.width = ux2;256box.height = uy2;257return box;258}259}260}261262263