/*******************************************************************************
* Breakout Cave Survey Visualizer
*
* Copyright (C) 2014 James Edwards
*
* jedwards8 at fastmail dot fm
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*******************************************************************************/
package com.andork.plot;
import java.awt.Color;
import java.awt.PaintContext;
import java.awt.image.ColorModel;
import java.awt.image.DataBufferInt;
import java.awt.image.DirectColorModel;
import java.awt.image.Raster;
import java.awt.image.SinglePixelPackedSampleModel;
import java.lang.ref.WeakReference;
class CheckerPaintContext implements PaintContext {
static ColorModel xrgbmodel = new DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff);
static ColorModel xbgrmodel = new DirectColorModel(24, 0x000000ff, 0x0000ff00, 0x00ff0000);
static ColorModel cachedModel;
static WeakReference cached;
static synchronized Raster getCachedRaster(ColorModel cm, int w, int h) {
if (cm == cachedModel) {
if (cached != null) {
Raster ras = (Raster) cached.get();
if (ras != null &&
ras.getWidth() >= w &&
ras.getHeight() >= h) {
cached = null;
return ras;
}
}
}
return cm.createCompatibleWritableRaster(w, h);
}
static synchronized void putCachedRaster(ColorModel cm, Raster ras) {
if (cached != null) {
Raster cras = (Raster) cached.get();
if (cras != null) {
int cw = cras.getWidth();
int ch = cras.getHeight();
int iw = ras.getWidth();
int ih = ras.getHeight();
if (cw >= iw && ch >= ih) {
return;
}
if (cw * ch >= iw * ih) {
return;
}
}
}
cachedModel = cm;
cached = new WeakReference(ras);
}
Color c1;
Color c2;
int size;
Raster saved;
ColorModel model;
public CheckerPaintContext(ColorModel cm, Color c1, Color c2, int size) {
model = cm;
this.c1 = c1;
this.c2 = c2;
this.size = size;
}
/**
* Release the resources allocated for the operation.
*/
@Override
public void dispose() {
if (saved != null) {
putCachedRaster(model, saved);
saved = null;
}
}
void fillRaster(int[] pixels, int off, int adjust, int x, int y, int w, int h) {
int ic1 = c1.getRGB();
int ic2 = c2.getRGB();
int c = y / size % 2 == 0 ^ x / size % 2 == 0 ? ic1 : ic2;
int initRx = size - x % size;
int ry = size - y % size;
while (h-- > 0) {
int rx = initRx;
int cc = c;
for (int ix = 0; ix < w; ix++) {
pixels[off++] = c;
if (--rx == 0) {
rx = size;
c ^= ic1;
c ^= ic2;
}
}
off += adjust;
c = cc;
if (--ry == 0) {
ry = size;
c ^= ic1;
c ^= ic2;
}
}
}
/**
* Return the ColorModel of the output.
*/
@Override
public ColorModel getColorModel() {
return model;
}
/**
* Return a Raster containing the colors generated for the graphics
* operation.
*
* @param x
* ,y,w,h The area in device space for which colors are
* generated.
*/
@Override
public Raster getRaster(int x, int y, int w, int h) {
Raster rast = saved;
if (rast == null || rast.getWidth() < w || rast.getHeight() < h) {
rast = getCachedRaster(model, w, h);
saved = rast;
}
DataBufferInt rasterDB = (DataBufferInt) rast.getDataBuffer();
int[] pixels = rasterDB.getBankData()[0];
int off = rasterDB.getOffset();
int scanlineStride = ((SinglePixelPackedSampleModel) rast.getSampleModel()).getScanlineStride();
int adjust = scanlineStride - w;
fillRaster(pixels, off, adjust, x, y, w, h);
return rast;
}
}