Path: blob/master/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java
41159 views
/*1* Copyright (c) 2015, 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.marlin;2627import java.awt.geom.Path2D;28import java.lang.ref.WeakReference;29import java.util.concurrent.atomic.AtomicInteger;30import sun.java2d.ReentrantContext;31import sun.java2d.marlin.ArrayCacheConst.CacheStats;32import sun.java2d.marlin.DMarlinRenderingEngine.NormalizingPathIterator;33import sun.java2d.marlin.TransformingPathConsumer2D.CurveBasicMonotonizer;34import sun.java2d.marlin.TransformingPathConsumer2D.CurveClipSplitter;3536/**37* This class is a renderer context dedicated to a single thread38*/39final class RendererContext extends ReentrantContext implements MarlinConst {4041// RendererContext creation counter42private static final AtomicInteger CTX_COUNT = new AtomicInteger(1);4344/**45* Create a new renderer context46*47* @return new RendererContext instance48*/49static RendererContext createContext() {50return new RendererContext("ctx"51+ Integer.toString(CTX_COUNT.getAndIncrement()));52}5354// Smallest object used as Cleaner's parent reference55private final Object cleanerObj;56// dirty flag indicating an exception occured during pipeline in pathTo()57boolean dirty = false;58// shared data59final double[] double6 = new double[6];60// shared curve (dirty) (Renderer / Stroker)61final Curve curve = new Curve();62// MarlinRenderingEngine NormalizingPathIterator NearestPixelCenter:63final NormalizingPathIterator nPCPathIterator;64// MarlinRenderingEngine NearestPixelQuarter NormalizingPathIterator:65final NormalizingPathIterator nPQPathIterator;66// MarlinRenderingEngine.TransformingPathConsumer2D67final TransformingPathConsumer2D transformerPC2D;68// recycled Path2D instance (weak)69private WeakReference<Path2D.Double> refPath2D = null;70final Renderer renderer;71final Stroker stroker;72// Simplifies out collinear lines73final CollinearSimplifier simplifier = new CollinearSimplifier();74// Simplifies path75final PathSimplifier pathSimplifier = new PathSimplifier();76final Dasher dasher;77final MarlinTileGenerator ptg;78final MarlinCache cache;79// flag indicating the shape is stroked (1) or filled (0)80int stroking = 0;81// flag indicating to clip the shape82boolean doClip = false;83// flag indicating if the path is closed or not (in advance) to handle properly caps84boolean closedPath = false;85// clip rectangle (ymin, ymax, xmin, xmax):86final double[] clipRect = new double[4];87// clip inverse scale (mean) to adjust length checks88double clipInvScale = 0.0d;89// CurveBasicMonotonizer instance90final CurveBasicMonotonizer monotonizer;91// CurveClipSplitter instance92final CurveClipSplitter curveClipSplitter;9394// Array caches:95/* clean int[] cache (zero-filled) = 5 refs */96private final IntArrayCache cleanIntCache = new IntArrayCache(true, 5);97/* dirty int[] cache = 5 refs */98private final IntArrayCache dirtyIntCache = new IntArrayCache(false, 5);99/* dirty double[] cache = 4 refs (2 polystack) */100private final DoubleArrayCache dirtyDoubleCache = new DoubleArrayCache(false, 4);101/* dirty byte[] cache = 2 ref (2 polystack) */102private final ByteArrayCache dirtyByteCache = new ByteArrayCache(false, 2);103104// RendererContext statistics105final RendererStats stats;106107final PathConsumer2DAdapter p2dAdapter = new PathConsumer2DAdapter();108109/**110* Constructor111*112* @param name context name (debugging)113*/114RendererContext(final String name) {115if (LOG_CREATE_CONTEXT) {116MarlinUtils.logInfo("new RendererContext = " + name);117}118this.cleanerObj = new Object();119120// create first stats (needed by newOffHeapArray):121if (DO_STATS || DO_MONITORS) {122stats = RendererStats.createInstance(cleanerObj, name);123// push cache stats:124stats.cacheStats = new CacheStats[] { cleanIntCache.stats,125dirtyIntCache.stats, dirtyDoubleCache.stats, dirtyByteCache.stats126};127} else {128stats = null;129}130131// NormalizingPathIterator instances:132nPCPathIterator = new NormalizingPathIterator.NearestPixelCenter(double6);133nPQPathIterator = new NormalizingPathIterator.NearestPixelQuarter(double6);134135// curve monotonizer & clip subdivider (before transformerPC2D init)136monotonizer = new CurveBasicMonotonizer(this);137curveClipSplitter = new CurveClipSplitter(this);138139// MarlinRenderingEngine.TransformingPathConsumer2D140transformerPC2D = new TransformingPathConsumer2D(this);141142// Renderer:143cache = new MarlinCache(this);144renderer = new Renderer(this); // needs MarlinCache from rdrCtx.cache145ptg = new MarlinTileGenerator(stats, renderer, cache);146147stroker = new Stroker(this);148dasher = new Dasher(this);149}150151/**152* Disposes this renderer context:153* clean up before reusing this context154*/155void dispose() {156if (DO_STATS) {157if (stats.totalOffHeap > stats.totalOffHeapMax) {158stats.totalOffHeapMax = stats.totalOffHeap;159}160stats.totalOffHeap = 0L;161}162stroking = 0;163doClip = false;164closedPath = false;165clipInvScale = 0.0d;166167// if context is maked as DIRTY:168if (dirty) {169// may happen if an exception if thrown in the pipeline processing:170// force cleanup of all possible pipelined blocks (except Renderer):171172// NormalizingPathIterator instances:173this.nPCPathIterator.dispose();174this.nPQPathIterator.dispose();175// Dasher:176this.dasher.dispose();177// Stroker:178this.stroker.dispose();179180// mark context as CLEAN:181dirty = false;182}183}184185Path2D.Double getPath2D() {186// resolve reference:187Path2D.Double p2d = (refPath2D != null) ? refPath2D.get() : null;188189// create a new Path2D ?190if (p2d == null) {191p2d = new Path2D.Double(WIND_NON_ZERO, INITIAL_EDGES_COUNT); // 32K192193// update weak reference:194refPath2D = new WeakReference<Path2D.Double>(p2d);195}196// reset the path anyway:197p2d.reset();198return p2d;199}200201RendererStats stats() {202return stats;203}204205OffHeapArray newOffHeapArray(final long initialSize) {206if (DO_STATS) {207stats.totalOffHeapInitial += initialSize;208}209return new OffHeapArray(cleanerObj, initialSize);210}211212IntArrayCache.Reference newCleanIntArrayRef(final int initialSize) {213return cleanIntCache.createRef(initialSize);214}215216IntArrayCache.Reference newDirtyIntArrayRef(final int initialSize) {217return dirtyIntCache.createRef(initialSize);218}219220DoubleArrayCache.Reference newDirtyDoubleArrayRef(final int initialSize) {221return dirtyDoubleCache.createRef(initialSize);222}223224ByteArrayCache.Reference newDirtyByteArrayRef(final int initialSize) {225return dirtyByteCache.createRef(initialSize);226}227228static final class PathConsumer2DAdapter implements DPathConsumer2D {229private sun.awt.geom.PathConsumer2D out;230231PathConsumer2DAdapter() {}232233PathConsumer2DAdapter init(sun.awt.geom.PathConsumer2D out) {234this.out = out;235return this;236}237238@Override239public void moveTo(double x0, double y0) {240out.moveTo((float)x0, (float)y0);241}242243@Override244public void lineTo(double x1, double y1) {245out.lineTo((float)x1, (float)y1);246}247248@Override249public void closePath() {250out.closePath();251}252253@Override254public void pathDone() {255out.pathDone();256}257258@Override259public void curveTo(double x1, double y1,260double x2, double y2,261double x3, double y3)262{263out.curveTo((float)x1, (float)y1,264(float)x2, (float)y2,265(float)x3, (float)y3);266}267268@Override269public void quadTo(double x1, double y1, double x2, double y2) {270out.quadTo((float)x1, (float)y1, (float)x2, (float)y2);271}272273@Override274public long getNativeConsumer() {275throw new InternalError("Not using a native peer");276}277}278}279280281