package sun.java2d.marlin;
import java.awt.geom.Path2D;
import java.lang.ref.WeakReference;
import java.util.concurrent.atomic.AtomicInteger;
import sun.java2d.ReentrantContext;
import sun.java2d.ReentrantContextProvider;
import static sun.java2d.marlin.ArrayCache.*;
import sun.java2d.marlin.MarlinRenderingEngine.NormalizingPathIterator;
import static sun.java2d.marlin.MarlinUtils.logInfo;
final class RendererContext extends ReentrantContext implements MarlinConst {
private static final AtomicInteger contextCount = new AtomicInteger(1);
static final RendererStats stats = (doStats || doMonitors)
? RendererStats.getInstance(): null;
private static final boolean USE_CACHE_HARD_REF = doStats
|| (MarlinRenderingEngine.REF_TYPE == ReentrantContextProvider.REF_WEAK);
static RendererContext createContext() {
final RendererContext newCtx = new RendererContext("ctx"
+ Integer.toString(contextCount.getAndIncrement()));
if (RendererContext.stats != null) {
RendererContext.stats.allContexts.add(newCtx);
}
return newCtx;
}
final String name;
boolean dirty = false;
WeakReference<ArrayCachesHolder> refArrayCaches = null;
ArrayCachesHolder hardRefArrayCaches = null;
final float[] float6 = new float[6];
final Curve curve = new Curve();
final NormalizingPathIterator nPCPathIterator;
final NormalizingPathIterator nPQPathIterator;
final TransformingPathConsumer2D transformerPC2D;
Path2D.Float p2d = null;
final Renderer renderer;
final Stroker stroker;
final CollinearSimplifier simplifier = new CollinearSimplifier();
final Dasher dasher;
final MarlinTileGenerator ptg;
final MarlinCache cache;
int stroking = 0;
RendererContext(final String name) {
if (logCreateContext) {
MarlinUtils.logInfo("new RendererContext = " + name);
}
this.name = name;
nPCPathIterator = new NormalizingPathIterator.NearestPixelCenter(float6);
nPQPathIterator = new NormalizingPathIterator.NearestPixelQuarter(float6);
transformerPC2D = new TransformingPathConsumer2D();
cache = new MarlinCache(this);
renderer = new Renderer(this);
ptg = new MarlinTileGenerator(renderer);
stroker = new Stroker(this);
dasher = new Dasher(this);
}
void dispose() {
stroking = 0;
if (!USE_CACHE_HARD_REF) {
hardRefArrayCaches = null;
}
if (dirty) {
this.nPCPathIterator.dispose();
this.nPQPathIterator.dispose();
this.dasher.dispose();
this.stroker.dispose();
dirty = false;
}
}
ArrayCachesHolder getArrayCachesHolder() {
ArrayCachesHolder holder = hardRefArrayCaches;
if (holder == null) {
holder = (refArrayCaches != null)
? refArrayCaches.get()
: null;
if (holder == null) {
if (logCreateContext) {
MarlinUtils.logInfo("new ArrayCachesHolder for "
+ "RendererContext = " + name);
}
holder = new ArrayCachesHolder();
if (USE_CACHE_HARD_REF) {
hardRefArrayCaches = holder;
}
refArrayCaches = new WeakReference<ArrayCachesHolder>(holder);
}
}
return holder;
}
ByteArrayCache getDirtyByteArrayCache(final int length) {
final int bucket = ArrayCache.getBucketDirtyBytes(length);
return getArrayCachesHolder().dirtyByteArrayCaches[bucket];
}
byte[] getDirtyByteArray(final int length) {
if (length <= MAX_DIRTY_BYTE_ARRAY_SIZE) {
return getDirtyByteArrayCache(length).getArray();
}
if (doStats) {
incOversize();
}
if (doLogOverSize) {
logInfo("getDirtyByteArray[oversize]: length=\t" + length);
}
return new byte[length];
}
void putDirtyByteArray(final byte[] array) {
final int length = array.length;
if (((length & 0x1) == 0) && (length <= MAX_DIRTY_BYTE_ARRAY_SIZE)) {
getDirtyByteArrayCache(length).putDirtyArray(array, length);
}
}
byte[] widenDirtyByteArray(final byte[] in,
final int usedSize, final int needSize)
{
final int length = in.length;
if (doChecks && length >= needSize) {
return in;
}
if (doStats) {
incResizeDirtyByte();
}
final byte[] res = getDirtyByteArray(getNewSize(usedSize, needSize));
System.arraycopy(in, 0, res, 0, usedSize);
putDirtyByteArray(in);
if (doLogWidenArray) {
logInfo("widenDirtyByteArray[" + res.length + "]: usedSize=\t"
+ usedSize + "\tlength=\t" + length + "\tneeded length=\t"
+ needSize);
}
return res;
}
IntArrayCache getIntArrayCache(final int length) {
final int bucket = ArrayCache.getBucket(length);
return getArrayCachesHolder().intArrayCaches[bucket];
}
int[] getIntArray(final int length) {
if (length <= MAX_ARRAY_SIZE) {
return getIntArrayCache(length).getArray();
}
if (doStats) {
incOversize();
}
if (doLogOverSize) {
logInfo("getIntArray[oversize]: length=\t" + length);
}
return new int[length];
}
int[] widenIntArray(final int[] in, final int usedSize,
final int needSize, final int clearTo)
{
final int length = in.length;
if (doChecks && length >= needSize) {
return in;
}
if (doStats) {
incResizeInt();
}
final int[] res = getIntArray(getNewSize(usedSize, needSize));
System.arraycopy(in, 0, res, 0, usedSize);
putIntArray(in, 0, clearTo);
if (doLogWidenArray) {
logInfo("widenIntArray[" + res.length + "]: usedSize=\t"
+ usedSize + "\tlength=\t" + length + "\tneeded length=\t"
+ needSize);
}
return res;
}
void putIntArray(final int[] array, final int fromIndex,
final int toIndex)
{
final int length = array.length;
if (((length & 0x1) == 0) && (length <= MAX_ARRAY_SIZE)) {
getIntArrayCache(length).putArray(array, length, fromIndex, toIndex);
}
}
IntArrayCache getDirtyIntArrayCache(final int length) {
final int bucket = ArrayCache.getBucket(length);
return getArrayCachesHolder().dirtyIntArrayCaches[bucket];
}
int[] getDirtyIntArray(final int length) {
if (length <= MAX_ARRAY_SIZE) {
return getDirtyIntArrayCache(length).getArray();
}
if (doStats) {
incOversize();
}
if (doLogOverSize) {
logInfo("getDirtyIntArray[oversize]: length=\t" + length);
}
return new int[length];
}
int[] widenDirtyIntArray(final int[] in,
final int usedSize, final int needSize)
{
final int length = in.length;
if (doChecks && length >= needSize) {
return in;
}
if (doStats) {
incResizeDirtyInt();
}
final int[] res = getDirtyIntArray(getNewSize(usedSize, needSize));
System.arraycopy(in, 0, res, 0, usedSize);
putDirtyIntArray(in);
if (doLogWidenArray) {
logInfo("widenDirtyIntArray[" + res.length + "]: usedSize=\t"
+ usedSize + "\tlength=\t" + length + "\tneeded length=\t"
+ needSize);
}
return res;
}
void putDirtyIntArray(final int[] array) {
final int length = array.length;
if (((length & 0x1) == 0) && (length <= MAX_ARRAY_SIZE)) {
getDirtyIntArrayCache(length).putDirtyArray(array, length);
}
}
FloatArrayCache getDirtyFloatArrayCache(final int length) {
final int bucket = ArrayCache.getBucket(length);
return getArrayCachesHolder().dirtyFloatArrayCaches[bucket];
}
float[] getDirtyFloatArray(final int length) {
if (length <= MAX_ARRAY_SIZE) {
return getDirtyFloatArrayCache(length).getArray();
}
if (doStats) {
incOversize();
}
if (doLogOverSize) {
logInfo("getDirtyFloatArray[oversize]: length=\t" + length);
}
return new float[length];
}
float[] widenDirtyFloatArray(final float[] in,
final int usedSize, final int needSize)
{
final int length = in.length;
if (doChecks && length >= needSize) {
return in;
}
if (doStats) {
incResizeDirtyFloat();
}
final float[] res = getDirtyFloatArray(getNewSize(usedSize, needSize));
System.arraycopy(in, 0, res, 0, usedSize);
putDirtyFloatArray(in);
if (doLogWidenArray) {
logInfo("widenDirtyFloatArray[" + res.length + "]: usedSize=\t"
+ usedSize + "\tlength=\t" + length + "\tneeded length=\t"
+ needSize);
}
return res;
}
void putDirtyFloatArray(final float[] array) {
final int length = array.length;
if (((length & 0x1) == 0) && (length <= MAX_ARRAY_SIZE)) {
getDirtyFloatArrayCache(length).putDirtyArray(array, length);
}
}
static final class ArrayCachesHolder {
final IntArrayCache[] intArrayCaches;
final IntArrayCache[] dirtyIntArrayCaches;
final FloatArrayCache[] dirtyFloatArrayCaches;
final ByteArrayCache[] dirtyByteArrayCaches;
ArrayCachesHolder() {
intArrayCaches = new IntArrayCache[BUCKETS];
dirtyIntArrayCaches = new IntArrayCache[BUCKETS];
dirtyFloatArrayCaches = new FloatArrayCache[BUCKETS];
dirtyByteArrayCaches = new ByteArrayCache[BUCKETS];
for (int i = 0; i < BUCKETS; i++) {
intArrayCaches[i] = new IntArrayCache(ARRAY_SIZES[i]);
dirtyIntArrayCaches[i] = new IntArrayCache(ARRAY_SIZES[i]);
dirtyFloatArrayCaches[i] = new FloatArrayCache(ARRAY_SIZES[i]);
dirtyByteArrayCaches[i] = new ByteArrayCache(DIRTY_BYTE_ARRAY_SIZES[i]);
}
}
}
}