src/java.desktop/share/classes/sun/java2d/pipe/AAShapePipe.java

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 1997, 2013, 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 --- 1,7 ---- /* ! * Copyright (c) 1997, 2015, 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
*** 20,37 **** * * 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.Rectangle; import java.awt.Shape; import java.awt.geom.Rectangle2D; - import java.awt.geom.PathIterator; import sun.awt.SunHints; import sun.java2d.SunGraphics2D; /** * This class is used to convert raw geometry into 8-bit alpha tiles --- 20,35 ----
*** 43,52 **** --- 41,59 ---- public class AAShapePipe implements ShapeDrawPipe, ParallelogramPipe { static RenderingEngine renderengine = RenderingEngine.getInstance(); + // Per-thread TileState (~1K very small so do not use any Weak Reference) + private static final ThreadLocal<TileState> tileStateThreadLocal = + new ThreadLocal<TileState>() { + @Override + protected TileState initialValue() { + return new TileState(); + } + }; + CompositePipe outpipe; public AAShapePipe(CompositePipe pipe) { outpipe = pipe; }
*** 66,107 **** public void fill(SunGraphics2D sg, Shape s) { renderPath(sg, s, null); } - private static Rectangle2D computeBBox(double ux1, double uy1, - double ux2, double uy2) - { - if ((ux2 -= ux1) < 0) { - ux1 += ux2; - ux2 = -ux2; - } - if ((uy2 -= uy1) < 0) { - uy1 += uy2; - uy2 = -uy2; - } - return new Rectangle2D.Double(ux1, uy1, ux2, uy2); - } - public void fillParallelogram(SunGraphics2D sg, double ux1, double uy1, double ux2, double uy2, double x, double y, double dx1, double dy1, double dx2, double dy2) { Region clip = sg.getCompClip(); ! int abox[] = new int[4]; AATileGenerator aatg = renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0, clip, abox); if (aatg == null) { // Nothing to render return; } ! renderTiles(sg, computeBBox(ux1, uy1, ux2, uy2), aatg, abox); } public void drawParallelogram(SunGraphics2D sg, double ux1, double uy1, double ux2, double uy2, --- 73,102 ---- public void fill(SunGraphics2D sg, Shape s) { renderPath(sg, s, null); } public void fillParallelogram(SunGraphics2D sg, double ux1, double uy1, double ux2, double uy2, double x, double y, double dx1, double dy1, double dx2, double dy2) { Region clip = sg.getCompClip(); ! final TileState ts = tileStateThreadLocal.get(); ! final int[] abox = ts.abox; ! AATileGenerator aatg = renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0, clip, abox); if (aatg == null) { // Nothing to render return; } ! renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), aatg, abox, ts); } public void drawParallelogram(SunGraphics2D sg, double ux1, double uy1, double ux2, double uy2,
*** 109,188 **** double dx1, double dy1, double dx2, double dy2, double lw1, double lw2) { Region clip = sg.getCompClip(); ! int abox[] = new int[4]; AATileGenerator aatg = renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1, lw2, clip, abox); if (aatg == null) { // Nothing to render return; } // Note that bbox is of the original shape, not the wide path. // This is appropriate for handing to Paint methods... ! renderTiles(sg, computeBBox(ux1, uy1, ux2, uy2), aatg, abox); ! } ! ! private static byte[] theTile; ! ! private static synchronized byte[] getAlphaTile(int len) { ! byte[] t = theTile; ! if (t == null || t.length < len) { ! t = new byte[len]; ! } else { ! theTile = null; ! } ! return t; ! } ! ! private static synchronized void dropAlphaTile(byte[] t) { ! theTile = t; } public void renderPath(SunGraphics2D sg, Shape s, BasicStroke bs) { boolean adjust = (bs != null && sg.strokeHint != SunHints.INTVAL_STROKE_PURE); boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED); Region clip = sg.getCompClip(); ! int abox[] = new int[4]; AATileGenerator aatg = renderengine.getAATileGenerator(s, sg.transform, clip, bs, thin, adjust, abox); if (aatg == null) { // Nothing to render return; } ! renderTiles(sg, s, aatg, abox); } public void renderTiles(SunGraphics2D sg, Shape s, ! AATileGenerator aatg, int abox[]) { Object context = null; - byte alpha[] = null; try { context = outpipe.startSequence(sg, s, ! new Rectangle(abox[0], abox[1], ! abox[2] - abox[0], ! abox[3] - abox[1]), abox); ! int tw = aatg.getTileWidth(); ! int th = aatg.getTileHeight(); ! alpha = getAlphaTile(tw * th); byte[] atile; for (int y = abox[1]; y < abox[3]; y += th) { for (int x = abox[0]; x < abox[2]; x += tw) { int w = Math.min(tw, abox[2] - x); - int h = Math.min(th, abox[3] - y); int a = aatg.getTypicalAlpha(); if (a == 0x00 || outpipe.needTile(context, x, y, w, h) == false) { --- 104,170 ---- double dx1, double dy1, double dx2, double dy2, double lw1, double lw2) { Region clip = sg.getCompClip(); ! final TileState ts = tileStateThreadLocal.get(); ! final int[] abox = ts.abox; ! AATileGenerator aatg = renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1, lw2, clip, abox); if (aatg == null) { // Nothing to render return; } // Note that bbox is of the original shape, not the wide path. // This is appropriate for handing to Paint methods... ! renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), aatg, abox, ts); } public void renderPath(SunGraphics2D sg, Shape s, BasicStroke bs) { boolean adjust = (bs != null && sg.strokeHint != SunHints.INTVAL_STROKE_PURE); boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED); Region clip = sg.getCompClip(); ! final TileState ts = tileStateThreadLocal.get(); ! final int[] abox = ts.abox; ! AATileGenerator aatg = renderengine.getAATileGenerator(s, sg.transform, clip, bs, thin, adjust, abox); if (aatg == null) { // Nothing to render return; } ! renderTiles(sg, s, aatg, abox, ts); } public void renderTiles(SunGraphics2D sg, Shape s, ! AATileGenerator aatg, int abox[], TileState ts) { Object context = null; try { context = outpipe.startSequence(sg, s, ! ts.computeDevBox(abox), abox); ! final int tw = aatg.getTileWidth(); ! final int th = aatg.getTileHeight(); + // get tile from thread local storage: + final byte[] alpha = ts.getAlphaTile(tw * th); byte[] atile; for (int y = abox[1]; y < abox[3]; y += th) { + int h = Math.min(th, abox[3] - y); + for (int x = abox[0]; x < abox[2]; x += tw) { int w = Math.min(tw, abox[2] - x); int a = aatg.getTypicalAlpha(); if (a == 0x00 || outpipe.needTile(context, x, y, w, h) == false) {
*** 205,215 **** } finally { aatg.dispose(); if (context != null) { outpipe.endSequence(context); } - if (alpha != null) { - dropAlphaTile(alpha); } } } } --- 187,244 ---- } finally { aatg.dispose(); if (context != null) { outpipe.endSequence(context); } } } + + // Tile state used by AAShapePipe + static final class TileState { + // cached tile (32 x 32 tile by default) + private byte[] theTile = new byte[32 * 32]; + // dirty aabox array + final int[] abox = new int[4]; + // dirty bbox rectangle + private final Rectangle dev = new Rectangle(); + // dirty bbox rectangle2D.Double + private final Rectangle2D.Double bbox2D = new Rectangle2D.Double(); + + byte[] getAlphaTile(int len) { + byte[] t = theTile; + if (t.length < len) { + // create a larger tile and may free current theTile (too small) + theTile = t = new byte[len]; + } + return t; + } + + Rectangle computeDevBox(final int[] abox) { + final Rectangle box = this.dev; + box.x = abox[0]; + box.y = abox[1]; + box.width = abox[2] - abox[0]; + box.height = abox[3] - abox[1]; + return box; } + + Rectangle2D computeBBox(double ux1, double uy1, + double ux2, double uy2) + { + if ((ux2 -= ux1) < 0.0) { + ux1 += ux2; + ux2 = -ux2; + } + if ((uy2 -= uy1) < 0.0) { + uy1 += uy2; + uy2 = -uy2; + } + final Rectangle2D.Double box = this.bbox2D; + box.x = ux1; + box.y = uy1; + box.width = ux2; + box.height = uy2; + return box; + } + } + }