Path: blob/master/src/java.desktop/share/classes/sun/java2d/pipe/AAShapePipe.java
41159 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 sun.awt.SunHints;31import sun.java2d.ReentrantContext;32import sun.java2d.ReentrantContextProvider;33import sun.java2d.ReentrantContextProviderTL;34import sun.java2d.SunGraphics2D;3536/**37* This class is used to convert raw geometry into 8-bit alpha tiles38* using an AATileGenerator for application by the next stage of39* the pipeline.40* This class sets up the Generator and computes the alpha tiles41* and then passes them on to a CompositePipe object for painting.42*/43public final class AAShapePipe44implements ShapeDrawPipe, ParallelogramPipe45{46static final RenderingEngine RDR_ENGINE = RenderingEngine.getInstance();4748// Per-thread TileState (~1K very small so do not use any Weak Reference)49private static final ReentrantContextProvider<TileState> TILE_STATE_PROVIDER =50new ReentrantContextProviderTL<TileState>(51ReentrantContextProvider.REF_HARD)52{53@Override54protected TileState newContext() {55return new TileState();56}57};5859final CompositePipe outpipe;6061public AAShapePipe(CompositePipe pipe) {62outpipe = pipe;63}6465@Override66public void draw(SunGraphics2D sg, Shape s) {67final BasicStroke bs;6869if (sg.stroke instanceof BasicStroke) {70bs = (BasicStroke) sg.stroke;71} else {72s = sg.stroke.createStrokedShape(s);73bs = null;74}7576renderPath(sg, s, bs);77}7879@Override80public void fill(SunGraphics2D sg, Shape s) {81renderPath(sg, s, null);82}8384@Override85public void fillParallelogram(SunGraphics2D sg,86double ux1, double uy1,87double ux2, double uy2,88double x, double y,89double dx1, double dy1,90double dx2, double dy2)91{92final TileState ts = TILE_STATE_PROVIDER.acquire();93try {94final int[] abox = ts.abox;9596final AATileGenerator aatg =97RDR_ENGINE.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0,98sg.getCompClip(), abox);99if (aatg != null) {100renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2),101aatg, abox, ts);102}103} finally {104TILE_STATE_PROVIDER.release(ts);105}106}107108@Override109public void drawParallelogram(SunGraphics2D sg,110double ux1, double uy1,111double ux2, double uy2,112double x, double y,113double dx1, double dy1,114double dx2, double dy2,115double lw1, double lw2)116{117final TileState ts = TILE_STATE_PROVIDER.acquire();118try {119final int[] abox = ts.abox;120121final AATileGenerator aatg =122RDR_ENGINE.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1,123lw2, sg.getCompClip(), abox);124if (aatg != null) {125// Note that bbox is of the original shape, not the wide path.126// This is appropriate for handing to Paint methods...127renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2),128aatg, abox, ts);129}130} finally {131TILE_STATE_PROVIDER.release(ts);132}133}134135public void renderPath(SunGraphics2D sg, Shape s, BasicStroke bs) {136final boolean adjust = (bs != null &&137sg.strokeHint != SunHints.INTVAL_STROKE_PURE);138final boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED);139140final TileState ts = TILE_STATE_PROVIDER.acquire();141try {142final int[] abox = ts.abox;143144final AATileGenerator aatg =145RDR_ENGINE.getAATileGenerator(s, sg.transform, sg.getCompClip(),146bs, thin, adjust, abox);147if (aatg != null) {148renderTiles(sg, s, aatg, abox, ts);149}150} finally {151TILE_STATE_PROVIDER.release(ts);152}153}154155public void renderTiles(SunGraphics2D sg, Shape s,156final AATileGenerator aatg,157final int[] abox, final TileState ts)158{159Object context = null;160try {161// reentrance: outpipe may also use AAShapePipe:162context = outpipe.startSequence(sg, s,163ts.computeDevBox(abox),164abox);165166// copy of int[] abox as local variables for performance:167final int x0 = abox[0];168final int y0 = abox[1];169final int x1 = abox[2];170final int y1 = abox[3];171172final int tw = aatg.getTileWidth();173final int th = aatg.getTileHeight();174175// get tile from thread local storage:176final byte[] alpha = ts.getAlphaTile(tw * th);177byte[] atile;178179for (int y = y0; y < y1; y += th) {180final int h = Math.min(th, y1 - y);181182for (int x = x0; x < x1; x += tw) {183final int w = Math.min(tw, x1 - x);184185final int a = aatg.getTypicalAlpha();186187if (a == 0x00 || !outpipe.needTile(context, x, y, w, h)) {188aatg.nextTile();189outpipe.skipTile(context, x, y);190continue;191}192if (a == 0xff) {193atile = null;194aatg.nextTile();195} else {196atile = alpha;197aatg.getAlpha(alpha, 0, tw);198}199200outpipe.renderPathTile(context, atile, 0, tw, x, y, w, h);201}202}203} finally {204aatg.dispose();205if (context != null) {206outpipe.endSequence(context);207}208}209}210211// Tile state used by AAShapePipe212static final class TileState extends ReentrantContext {213// cached tile (32 x 32 tile by default)214private byte[] theTile = new byte[32 * 32];215// dirty aabox array216final int[] abox = new int[4];217// dirty bbox rectangle218private final Rectangle dev = new Rectangle();219// dirty bbox rectangle2D.Double220private final Rectangle2D.Double bbox2D = new Rectangle2D.Double();221222byte[] getAlphaTile(int len) {223byte[] t = theTile;224if (t.length < len) {225// create a larger tile and may free current theTile (too small)226theTile = t = new byte[len];227}228return t;229}230231Rectangle computeDevBox(final int[] abox) {232final Rectangle box = this.dev;233box.x = abox[0];234box.y = abox[1];235box.width = abox[2] - abox[0];236box.height = abox[3] - abox[1];237return box;238}239240Rectangle2D computeBBox(double ux1, double uy1,241double ux2, double uy2)242{243if ((ux2 -= ux1) < 0.0) {244ux1 += ux2;245ux2 = -ux2;246}247if ((uy2 -= uy1) < 0.0) {248uy1 += uy2;249uy2 = -uy2;250}251final Rectangle2D.Double box = this.bbox2D;252box.x = ux1;253box.y = uy1;254box.width = ux2;255box.height = uy2;256return box;257}258}259}260261262