package com.sun.prism.impl.shape;
import com.sun.javafx.geom.RectBounds;
import com.sun.javafx.geom.Path2D;
import com.sun.javafx.geom.Rectangle;
import com.sun.javafx.geom.Shape;
import com.sun.javafx.geom.transform.BaseTransform;
import com.sun.javafx.util.Logging;
import com.sun.openpisces.AlphaConsumer;
import com.sun.openpisces.Renderer;
import com.sun.prism.BasicStroke;
import com.sun.prism.impl.PrismSettings;
import java.nio.ByteBuffer;
public class OpenPiscesRasterizer implements ShapeRasterizer {
private static MaskData emptyData = MaskData.create(new byte[1], 0, 0, 1, 1);
private static Consumer savedConsumer;
@Override
public MaskData getMaskData(Shape shape,
BasicStroke stroke,
RectBounds xformBounds,
BaseTransform xform,
boolean close, boolean antialiasedShape)
{
if (stroke != null && stroke.getType() != BasicStroke.TYPE_CENTERED) {
shape = stroke.createStrokedShape(shape);
stroke = null;
}
if (xformBounds == null) {
if (stroke != null) {
shape = stroke.createStrokedShape(shape);
stroke = null;
}
xformBounds = new RectBounds();
xformBounds = (RectBounds) xform.transform(shape.getBounds(), xformBounds);
}
Rectangle rclip = new Rectangle(xformBounds);
if (rclip.isEmpty()) {
return emptyData;
}
Renderer renderer = null;
try {
if (shape instanceof Path2D) {
renderer = OpenPiscesPrismUtils.setupRenderer((Path2D) shape,
stroke, xform, rclip, antialiasedShape);
}
if (renderer == null) {
renderer = OpenPiscesPrismUtils.setupRenderer(shape,
stroke, xform, rclip, antialiasedShape);
}
int outpix_xmin = renderer.getOutpixMinX();
int outpix_ymin = renderer.getOutpixMinY();
int outpix_xmax = renderer.getOutpixMaxX();
int outpix_ymax = renderer.getOutpixMaxY();
int w = outpix_xmax - outpix_xmin;
int h = outpix_ymax - outpix_ymin;
if (w <= 0 || h <= 0) {
return emptyData;
}
Consumer consumer = savedConsumer;
if (consumer == null || w * h > consumer.getAlphaLength()) {
int csize = (w * h + 0xfff) & (~0xfff);
savedConsumer = consumer = new Consumer(csize);
if (PrismSettings.verbose) {
System.out.println("new alphas");
}
}
consumer.setBoundsNoClone(outpix_xmin, outpix_ymin, w, h);
renderer.produceAlphas(consumer);
return consumer.getMaskData();
} catch (Throwable ex) {
if (PrismSettings.verbose) {
ex.printStackTrace();
}
Logging.getJavaFXLogger().warning("Cannot rasterize Shape: "
+ ex.toString());
return emptyData;
}
}
private static class Consumer implements AlphaConsumer {
static byte savedAlphaMap[];
int x, y, width, height;
byte alphas[];
byte alphaMap[];
ByteBuffer alphabuffer;
MaskData maskdata = new MaskData();
public Consumer(int alphalen) {
this.alphas = new byte[alphalen];
alphabuffer = ByteBuffer.wrap(alphas);
}
public void setBoundsNoClone(int x, int y, int w, int h) {
this.x = x;
this.y = y;
this.width = w;
this.height = h;
maskdata.update(alphabuffer, x, y, w, h);
}
@Override
public int getOriginX() {
return x;
}
@Override
public int getOriginY() {
return y;
}
@Override
public int getWidth() {
return width;
}
@Override
public int getHeight() {
return height;
}
public byte[] getAlphasNoClone() {
return alphas;
}
public int getAlphaLength() {
return alphas.length;
}
public MaskData getMaskData() {
return maskdata;
}
@Override
public void setMaxAlpha(int maxalpha) {
byte map[] = savedAlphaMap;
if (map == null || map.length != maxalpha+1) {
map = new byte[maxalpha+1];
for (int i = 0; i <= maxalpha; i++) {
map[i] = (byte) ((i*255 + maxalpha/2)/maxalpha);
}
savedAlphaMap = map;
}
this.alphaMap = map;
}
@Override
public void setAndClearRelativeAlphas(int[] alphaRow, int pix_y,
int pix_from, int pix_to)
{
int w = width;
int off = (pix_y - y) * w;
byte out[] = this.alphas;
byte map[] = this.alphaMap;
int a = 0;
for (int i = 0; i < w; i++) {
a += alphaRow[i];
alphaRow[i] = 0;
out[off+i] = map[a];
}
}
public void setAndClearRelativeAlphas2(int[] alphaDeltas, int pix_y,
int pix_from, int pix_to)
{
if (pix_to >= pix_from) {
byte out[] = this.alphas;
byte map[] = this.alphaMap;
int from = pix_from - x;
int to = pix_to - x;
int w = width;
int off = (pix_y - y) * w;
int i = 0;
while (i < from) {
out[off+i] = 0;
i++;
}
int curAlpha = 0;
while (i <= to) {
curAlpha += alphaDeltas[i];
alphaDeltas[i] = 0;
byte a = map[curAlpha];
out[off+i] = a;
i++;
}
alphaDeltas[i] = 0;
while (i < w) {
out[off+i] = 0;
i++;
}
} else {
java.util.Arrays.fill(alphaDeltas, 0);
}
}
}
}