FileDocCategorySizeDatePackage
PiscesRenderer.javaAPI DocphoneME MR2 API (J2ME)47472Wed May 02 18:00:36 BST 2007com.sun.pisces

PiscesRenderer

public final class PiscesRenderer extends PathSink
version

Fields Summary
public static final int
ARC_OPEN
public static final int
ARC_CHORD
public static final int
ARC_PIE
public static final int
COMMAND_MOVE_TO
public static final int
COMMAND_LINE_TO
public static final int
COMMAND_QUAD_TO
public static final int
COMMAND_CUBIC_TO
public static final int
COMMAND_CLOSE
private static final boolean
enableLogging
private static PrintStream
logStream
private static final int
STROKE_X_BIAS
private static final int
STROKE_Y_BIAS
private static boolean
messageShown
private static int
DEFAULT_FILLER_FLATNESS
Object
data
int
width
int
height
int
offset
int
scanlineStride
int
pixelStride
int
type
RendererBase
rdr
public PathSink
fillerP
public PathSink
textFillerP
public PathSink
strokerP
PathSink
externalConsumer
boolean
inSubpath
boolean
isPathFilled
int
lineWidth
int
capStyle
int
joinStyle
int
miterLimit
int[]
dashArray
int
dashPhase
Transform6
transform
Paint
paint
Transform6
paintTransform
Transform6
paintCompoundTransform
int[]
gcm_fractions
int[]
gcm_rgba
int
gcm_cycleMethod
GradientColorMap
gradientColorMap
int
red
int
green
int
blue
int
alpha
int
bbMinX
int
bbMinY
int
bbMaxX
int
bbMaxY
private boolean
antialiasingOn
public Flattener
fillFlattener
Transformer
fillTransformer
public Flattener
textFlattener
Transformer
textTransformer
Stroker
strokeStroker
Dasher
strokeDasher
public Flattener
strokeFlattener
Transformer
strokeTransformer
private static int[]
convert8To5
private static int[]
convert8To6
private static final long
acv
Constructors Summary
public PiscesRenderer(Object data, int width, int height, int offset, int scanlineStride, int pixelStride, int type)
Creates a renderer that will write into a given pixel array.

param
data an int or short array where pixel data should be written.
param
width the width of the pixel array.
param
height the height of the pixel array.
param
offset the starting offset of the pixel array.
param
scanlineStride the scanline stride of the pixel array, in array entries.
param
pixelStride the pixel stride of the pixel array, in array entries.
param
type the pixel format, one of the RendererBase.TYPE_* constants.

    
                                                                                            
          
                               
                            
        if (!messageShown) {
            System.out.println("Using Pisces Renderer (java version)");
        }

        if (data instanceof NativeSurface) {
            NativeSurface ns = (NativeSurface)data;
            
            this.data = ns.getData();
            this.width = ns.getWidth();
            this.height = ns.getHeight();
            this.offset = 0;
            this.scanlineStride = ns.getWidth();
            this.pixelStride = 1;
        } else {
            this.data = data;
            this.width = width;
            this.height = height;
            this.offset = offset;
            this.scanlineStride = scanlineStride;
            this.pixelStride = pixelStride;
        }
        
        this.type = type;
        this.rdr = new Renderer(this.data, this.width, this.height,
                this.offset, this.scanlineStride, this.pixelStride,
                type);

        invalidate();
        setFill();

        messageShown = true;
    
Methods Summary
private booleanarraysDiffer(int[] a, int[] b)

        if (a == null) {
            return true;
        }
        int len = b.length;
        if (a.length != len) {
            return true;
        }
        for (int i = 0; i < len; i++) {
            if (a[i] != b[i]) {
                return true;
            }
        }

        return false;
    
public voidbeginRendering(int windingRule)

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.beginRendering(" + windingRule + ")");
            }
        }
        myBeginRendering(windingRule);
    
public voidbeginRendering(int minX, int minY, int width, int height, int windingRule)
Begins the rendering of path data. The supplied clipping bounds are intersected against the current clip rectangle and the destination image bounds; only pixels within the resulting rectangle may be written to.

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.beginRendering(" +
                                  minX + ", " +
                                  minY + ", " +
                                  width + ", " +
                                  height + ", " +
                                  windingRule + ");");
            }
        }
        myBeginRendering(minX, minY, width, height, windingRule);
    
public voidclearRect(int x, int y, int w, int h)

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.clearRect(" +
                                  x + ", " +
                                  y + ", " +
                                  w + ", " +
                                  h + ");"); 
            }
        }

        int maxX = x + w;
        int maxY = y + h;
        
        x = Math.max(x, 0);
        x = Math.max(x, bbMinX);

        y = Math.max(y, 0);
        y = Math.max(y, bbMinY);

        maxX = Math.min(maxX, this.width);
        maxX = Math.min(maxX, bbMaxX);

        maxY = Math.min(maxY, this.height);
        maxY = Math.min(maxY, bbMaxY);

        rdr.clearRect(x, y, maxX - x, maxY - y);
    
private int[]cloneArray(int[] src)

        int len = src.length;
        int[] dst = new int[len];
        System.arraycopy(src, 0, dst, 0, len);
        return dst;
    
public voidclose()

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.close();");
            }
        }
        inSubpath = false;
        externalConsumer.close();
    
public voidcubicTo(int x1, int y1, int x2, int y2, int x3, int y3)

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.cubicTo(" +
                                  x1 + ", " + y1 + ", " +
                                  x2 + ", " + y2 + ", " +
                                  x3 + ", " + y3 + ");");
            }
        }
        inSubpath = true;
        externalConsumer.cubicTo(x1, y1, x2, y2, x3, y3);
    
public voiddrawArc(int x, int y, int width, int height, int startAngle, int arcAngle, int arcType)

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.drawArc(" +
                                  x + ", " +
                                  y + ", " +
                                  width + ", " +
                                  height + ", " +
                                  startAngle + ", " + 
                                  arcAngle + ", " + 
                                  arcType + ");"); 
           }
        }
        fillOrDrawArc(x, y, width, height, startAngle, arcAngle, arcType, true);
    
public voiddrawLine(int x0, int y0, int x1, int y1)

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.drawLine(" +
                                  x0 + ", " +
                                  y0 + ", " +
                                  x1 + ", " +
                                  y1 + ");"); 
            }
        }
        myBeginRendering(RendererBase.WIND_NON_ZERO);
        PathSink stroker = getStroker();
        stroker.moveTo(x0, y0);
        stroker.lineTo(x1, y1);
        stroker.end();
        myEndRendering();
    
public voiddrawOval(int x, int y, int w, int h)

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.drawOval(" +
                                  x + ", " +
                                  y + ", " +
                                  w + ", " +
                                  h + ");"); 
            }
        }
        fillOrDrawOval(x, y, w, h, true);
    
public voiddrawRect(int x, int y, int w, int h)

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.drawRect(" +
                                  x + ", " +
                                  y + ", " +
                                  w + ", " +
                                  h + ");"); 
            }
        }

        if (w <= 0 || h <= 0) {
            return;
        }

        // If dashing is disabled, and using mitered joins,
        // simply draw two opposing rect outlines separated
        // by linewidth
        if (dashArray == null) {
            if ((joinStyle == Stroker.JOIN_MITER)
                    && (miterLimit >= PiscesMath.SQRT_TWO)) {
                int x0 = x + STROKE_X_BIAS;
                int y0 = y + STROKE_Y_BIAS;
                int x1 = x0 + w;
                int y1 = y0 + h;
                
                int lw = lineWidth;
                int m = lineWidth/2;
                
                PathSink filler = getFiller();
                myBeginRendering(RendererBase.WIND_NON_ZERO);
                filler.moveTo(x0 - m, y0 - m);
                filler.lineTo(x1 + m, y0 - m);
                filler.lineTo(x1 + m, y1 + m);
                filler.lineTo(x0 - m, y1 + m);
                filler.close();
                
                // Hollow out interior if w and h are greater than linewidth
                if ((x1 - x0) > lw && (y1 - y0) > lw) {
                    filler.moveTo(x0 + m, y0 + m);
                    filler.lineTo(x0 + m, y1 - m);
                    filler.lineTo(x1 - m, y1 - m);
                    filler.lineTo(x1 - m, y0 + m);
                    filler.close();
                }
                
                filler.end();
                myEndRendering();
                return;
            } else if (joinStyle == Stroker.JOIN_ROUND) {
                // IMPL NOTE - accelerate hollow rects with round joins
            }
        }

        PathSink stroker = getStroker();
        fillOrDrawRect(stroker, x, y, w, h);
    
public voiddrawRoundRect(int x, int y, int w, int h, int aw, int ah)

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.drawRoundRect(" +
                                  x + ", " +
                                  y + ", " +
                                  w + ", " +
                                  h + ", " +
                                  aw + ", " +
                                  ah + ");"); 
            }
        }
        if (w < 0 || h < 0) {
            return;
        }
        fillOrDrawRoundRect(x, y, w, h, aw, ah, true);
    
private voidemitArc(PathSink consumer, int cx, int cy, int rx, int ry, int startAngle, int endAngle, int nPoints)

        boolean first = true;

        for (int i = 0; i < nPoints; i++) {
            int theta = startAngle + i*(endAngle - startAngle)/(nPoints - 1);
            int ox = PiscesMath.cos(theta);
            int oy = PiscesMath.sin(theta);

            int lx = cx + (int)((long)rx*ox >> 16);
            int ly = cy - (int)((long)ry*oy >> 16);
            if (first) {
                consumer.moveTo(lx, ly);
                first = false;
            } else {
                consumer.lineTo(lx, ly);
            }
        }
    
private voidemitOffsetOval(PathSink consumer, int cx, int cy, int rx, int ry, int lw2, int nPoints, boolean inside)

        int i = inside ? nPoints - 1 : 1;
        int incr = inside ? -1 : 1;

        double drx = rx/65536.0;
        double dry = ry/65536.0;
        double dlw2 = lw2/65536.0;

        consumer.moveTo(cx + rx + lw2*incr, cy);

        nPoints /= 4;
        int[] points = new int[2*nPoints];
        int idx = 0;

        for (int j = 0; j < nPoints; j++) {
            double dtheta = i*(Math.PI/2.0)/nPoints;
            double cosTheta = Math.cos(dtheta);
            double sinTheta = Math.sin(dtheta);
            double drxSinTheta = drx*sinTheta;
            double dryCosTheta = dry*cosTheta;
            double den = dlw2/Math.sqrt(drxSinTheta*drxSinTheta +
                                        dryCosTheta*dryCosTheta);
            double dpx = cosTheta*(drx + incr*dry*den);
            double dpy = sinTheta*(dry + incr*drx*den);
            
            int px = (int)(dpx*65536.0);
            int py = (int)(dpy*65536.0);

            points[idx++] = px;
            points[idx++] = py;

            i += incr;
        }

        emitQuadrants(consumer, cx, cy, points, nPoints);
        consumer.close();
    
private voidemitOval(PathSink consumer, int cx, int cy, int rx, int ry, int nPoints, boolean reverse)

        int i = reverse ? nPoints - 1 : 1;
        int incr = reverse ? -1 : 1;

        consumer.moveTo(cx + rx, cy);

        nPoints /= 4;
        int[] points = new int[2*nPoints];
        int idx = 0;

        for (int j = 0; j < nPoints; j++) {
            int theta = i*PiscesMath.TWO_PI/(4*nPoints);
            int ox = PiscesMath.cos(theta);
            int oy = PiscesMath.sin(theta);
            points[idx++] = (int)((long)rx*ox >> 16);
            points[idx++] = (int)((long)ry*oy >> 16);

            i += incr;
        }
        
        emitQuadrants(consumer, cx, cy, points, nPoints);
        consumer.close();
    
private voidemitQuadrants(PathSink consumer, int cx, int cy, int[] points, int nPoints)

        // Emit quarter-arc once for each quadrant, suitably
        // reflected
        for (int pass = 0; pass < 4; pass++) {
            int xsign = 1;
            int ysign = 1;
            if (pass == 1 || pass == 2) xsign = -1;
            if (pass == 2 || pass == 3) ysign = -1;
            int incr = 2*xsign*ysign;
            int idx = (incr > 0) ? 0 : 2*nPoints - 2;

            for (int j = 0; j < nPoints; j++) {
                consumer.lineTo(cx + xsign*points[idx],
                                cy + ysign*points[idx + 1]);
                idx += incr;
            }
        }
    
private voidemitRoundRect(PathSink consumer, int x, int y, int w, int h, int aw, int ah, boolean reverse)

        int xw = x + w;
        int yh = y + h;

        int aw2 = aw >> 1;
        int ah2 = ah >> 1;
        int acvaw = (int)(acv*aw >> 16);
        int acvah = (int)(acv*ah >> 16);
        int xacvaw = x + acvaw;
        int xw_acvaw = xw - acvaw;
        int yacvah = y + acvah;
        int yh_acvah = yh - acvah;
        int xaw2 = x + aw2;
        int xw_aw2 = xw - aw2;
        int yah2 = y + ah2;
        int yh_ah2 = yh - ah2;
        
        consumer.moveTo(x, yah2);
        if (reverse) {
            consumer.cubicTo(x, yacvah, xacvaw, y, xaw2, y);
            consumer.lineTo(xw_aw2, y);
            consumer.cubicTo(xw_acvaw, y, xw, yacvah, xw, yah2);
            consumer.lineTo(xw, yh_ah2);
            consumer.cubicTo(xw, yh_acvah, xw_acvaw, yh, xw_aw2, yh);
            consumer.lineTo(xaw2, yh);
            consumer.cubicTo(xacvaw, yh, x, yh_acvah, x, yh_ah2);
        } else {
            consumer.lineTo(x, yh_ah2);
            consumer.cubicTo(x, yh_acvah, xacvaw, yh, xaw2, yh);
            consumer.lineTo(xw_aw2, yh);
            consumer.cubicTo(xw_acvaw, yh, xw, yh_acvah, xw, yh_ah2);
            consumer.lineTo(xw, yah2);
            consumer.cubicTo(xw, yacvah, xw_acvaw, y, xw_aw2, y);
            consumer.lineTo(xaw2, y);
            consumer.cubicTo(xacvaw, y, x, yacvah, x, yah2);
        }
        consumer.close();
        consumer.end();
    
public voidend()

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.end();");
            }
        }
        if (inSubpath && isPathFilled) {
            close();
        }
        inSubpath = false;
        externalConsumer.end();
    
public voidendRendering()
Completes the rendering of path data. Destination pixels will be written at this time.

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.endRendering();");
            }
        }
        end();
        myEndRendering();
    
public voidfillArc(int x, int y, int width, int height, int startAngle, int arcAngle, int arcType)

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.fillArc(" +
                                  x + ", " +
                                  y + ", " +
                                  width + ", " +
                                  height + ", " +
                                  startAngle + ", " +
                                  arcAngle + ", " + 
                                  arcType + ");"); 
            }
        }
        fillOrDrawArc(x, y, width, height, startAngle, arcAngle, arcType, false);
    
public voidfillOrDrawArc(int x, int y, int width, int height, int startAngle, int arcAngle, int arcType, boolean stroke)

        PathSink consumer = stroke ? getStroker() : getFiller();
        if (width <= 0 || height <= 0) {
            return;
        }

        int w2 = width >> 1;
        int h2 = height >> 1;
        int cx = x + w2;
        int cy = y + h2;

        startAngle = (int)(((long)startAngle*PiscesMath.TWO_PI)/(360*65536));
        arcAngle = (int)(((long)arcAngle*PiscesMath.TWO_PI)/(360*65536));

        int endAngle = startAngle + arcAngle;

        int nPoints = Math.max(16, Math.max(w2, h2) >> 16);

        myBeginRendering(RendererBase.WIND_NON_ZERO);
        emitArc(consumer, cx, cy, w2, h2, startAngle, endAngle, nPoints);
        if (arcType == ARC_PIE) {
            consumer.lineTo(cx, cy);
        }
        if (!stroke || (arcType == ARC_CHORD) || (arcType == ARC_PIE)) {
            consumer.close();
        }
        consumer.end();
        myEndRendering();
    
private voidfillOrDrawOval(int x, int y, int w, int h, boolean hollow)

        if (w <= 0 || h <= 0) {
            return;
        }

//         if (!antialiasingOn) {
//             lineWidth = (lineWidth + 0xffff) & 0xffff0000;
//         }

        int w2 = w >> 1;
        int h2 = h >> 1;
        int cx = x + w2;
        int cy = y + h2;
        int lineWidth2 = hollow ? lineWidth/2 : 0;
        
        int wl = w2 + lineWidth2;
        int hl = h2 + lineWidth2;
        int nPoints = Math.max(16, Math.max(wl, hl) >> 13);

        myBeginRendering(RendererBase.WIND_NON_ZERO);

        // Stroke the outline if dashing
        if (hollow && dashArray != null) {
            PathSink stroker = getStroker();
            emitOval(stroker, cx, cy, w2, h2, nPoints, false);
            stroker.end();
            myEndRendering();
            return;
        }

        if (!antialiasingOn) {
            cx += STROKE_X_BIAS;
        }

        // Draw exterior outline
        PathSink filler = getFiller();

        if (w == h) {
            emitOval(filler, cx, cy, wl, hl, nPoints, false);
        } else {
            emitOffsetOval(filler, cx, cy, w2, h2, lineWidth2,
                           nPoints, false);
        }

        // Draw interior in the reverse direction
        if (hollow) {
            wl = w2 - lineWidth2;
            hl = h2 - lineWidth2;
            
            if (wl > 0 && hl > 0) {
                if (w == h) {
                    emitOval(filler, cx, cy, wl, hl, nPoints, true);
                } else {
                    emitOffsetOval(filler, cx, cy, w2, h2, lineWidth2,
                                   nPoints, true);
                }
            }
        }
        filler.end();
        myEndRendering();
    
private voidfillOrDrawRect(PathSink consumer, int x, int y, int w, int h)

        int x0 = x;
        int y0 = y;
        int x1 = x0 + w;
        int y1 = y0 + h;
        
        myBeginRendering(RendererBase.WIND_NON_ZERO);
        consumer.moveTo(x0, y0);
        consumer.lineTo(x1, y0);
        consumer.lineTo(x1, y1);
        consumer.lineTo(x0, y1);
        consumer.close();
        consumer.end();
        myEndRendering();
    
private voidfillOrDrawRoundRect(int x, int y, int w, int h, int aw, int ah, boolean stroke)

        PathSink consumer = stroke ? getStroker() : getFiller();

        if (aw < 0) aw = -aw;
        if (aw > w) aw = w;
        if (ah < 0) ah = -ah;
        if (ah > h) ah = h;

        // If stroking but not dashing, draw the outer and inner
        // contours explicitly as round rects
        //
        // Note - this only works if aw == ah since the result of tracing
        // a circle with a circular pen is a larger circle, but the result
        // of tracing an ellipse with a circular pen is not (generally)
        // an ellipse...
        if (stroke && dashArray == null && aw == ah) {
            int lineWidth2 = lineWidth >> 1;

            myBeginRendering(RendererBase.WIND_NON_ZERO);
            PathSink filler = getFiller();

            x += STROKE_X_BIAS;
            y += STROKE_Y_BIAS;

            emitRoundRect(filler,
                          x - lineWidth2, y - lineWidth2,
                          w + lineWidth, h + lineWidth,
                          aw + lineWidth, ah + lineWidth, false);

            // Empty out inner rect
            w -= lineWidth;
            h -= lineWidth;
            if (w > 0 && h > 0) {
                emitRoundRect(filler,
                              x + lineWidth2, y + lineWidth2,
                              w, h,
                              aw - lineWidth, ah - lineWidth, true);
            }
            myEndRendering();
        } else {
            myBeginRendering(RendererBase.WIND_NON_ZERO);
            emitRoundRect(consumer, x, y, w, h, aw, ah, false);
            myEndRendering();
        }
    
public voidfillOval(int x, int y, int w, int h)

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.fillOval(" +
                                  x + ", " +
                                  y + ", " +
                                  w + ", " +
                                  h + ");"); 
            }
        }
        fillOrDrawOval(x, y, w, h, false);
    
public voidfillRect(int x, int y, int w, int h)

param
x the X coordinate in S15.16 format.
param
y the Y coordinate in S15.16 format.
param
w the width in S15.16 format.
param
h the height in S15.16 format.

        convert8To5 = new int[256];
        convert8To6 = new int[256];

        for (int i = 0; i < 256; i++) {
            convert8To5[i] = (i*31 + 127)/255;
            convert8To6[i] = (i*63 + 127)/255;
        }
    
        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.fillRect(" +
                                  x + ", " +
                                  y + ", " +
                                  w + ", " +
                                  h + ");"); 
            }
        }

        if (w <= 0 || h <= 0) {
            return;
        }

        // Renderer will detect aligned rectangles
        PathSink filler = getFiller();
        fillOrDrawRect(filler, x, y, w, h);
    
public voidfillRoundRect(int x, int y, int w, int h, int aw, int ah)


             
                                  
        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.fillRoundRect(" +
                                  x + ", " +
                                  y + ", " +
                                  w + ", " +
                                  h + ", " +
                                  aw + ", " +
                                  ah + ");"); 
            }
        }
        if (w <= 0 || h <= 0) {
            return;
        }
        fillOrDrawRoundRect(x, y, w, h, aw, ah, false);
    
public booleangetAntialiasing()

        return this.antialiasingOn;
    
public voidgetBoundingBox(int[] bbox)
Returns a bounding box containing all pixels drawn during the rendering of the most recent primitive (beginRendering/endRendering pair). The bounding box is returned in the form (x, y, width, height).

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("bbox = new int[4];");
                logStream.println("pr.getBoundingBox(bbox);");
            }
        }
        rdr.getBoundingBox(bbox);
    
public PathSinkgetFiller()

        if (this.fillerP == null) {
            fillFlattener.setOutput(rdr);
            
            String flatness = System.getProperty("filler.flatness");
            if (flatness != null) {
                fillFlattener.setFlatness(Integer.parseInt(flatness));
            } else {
                fillFlattener.setFlatness(DEFAULT_FILLER_FLATNESS);
            }
            fillTransformer.setOutput(fillFlattener);
            fillTransformer.setTransform(transform);
            this.fillerP = fillTransformer;
        }
        return fillerP;
    
public voidgetImageData()

        rdr.getImageData(data, offset, scanlineStride);
    
public PathSinkgetStroker()


       
        if (this.strokerP == null) {
            strokeStroker.setOutput(rdr);
            strokeStroker.setParameters(lineWidth,
                                        capStyle, joinStyle,
                                        miterLimit, transform);
            if (dashArray == null) {
                strokeFlattener.setOutput(strokeStroker);
                strokeFlattener.setFlatness(1 << 16);
            } else {
                strokeDasher.setOutput(strokeStroker);
                strokeDasher.setParameters(dashArray, dashPhase, transform);
                strokeFlattener.setOutput(strokeDasher);
                strokeFlattener.setFlatness(1 << 16);
            }

            Transform6 t = transform;
            t = new Transform6(transform);
            t.m02 += STROKE_X_BIAS;
            t.m12 += STROKE_Y_BIAS;
            strokeTransformer.setTransform(t);
            strokeTransformer.setOutput(strokeFlattener);
            this.strokerP = strokeTransformer;
        }
        return strokerP;
    
public PathSinkgetTextFiller()

        if (textFillerP == null) {
            textFlattener.setOutput(rdr);
            textFlattener.setFlatness(1 << (16 -
                             Math.min(rdr.getSubpixelLgPositionsX(),
                                      rdr.getSubpixelLgPositionsY())));
            textTransformer.setOutput(textFlattener);
            textTransformer.setTransform(transform);
            this.textFillerP = textTransformer;
        }
        return textFillerP;
    
public Transform6getTransform()

        return new Transform6(transform);
    
private voidinvalidate()

        fillerP = null;
        textFillerP = null;
        strokerP = null;
    
public voidlineJoin()

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.lineJoin();");
            }
        }
        externalConsumer.lineJoin();
    
public voidlineTo(int x1, int y1)

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.lineTo(" + x1 + ", " + y1 + ");");
            }
        }
        inSubpath = true;
        externalConsumer.lineTo(x1, y1);
    
public voidmoveTo(int x0, int y0)

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.moveTo(" + x0 + ", " + y0 + ");");
            }
        }
        if (inSubpath && isPathFilled) {
            externalConsumer.close();
        }
        inSubpath = false;
        externalConsumer.moveTo(x0, y0);
    
private voidmyBeginRendering(int windingRule)

        int minX = Math.max(0, bbMinX);
        int minY = Math.max(0, bbMinY);
        int maxX = Math.min(width, bbMaxX);
        int maxY = Math.min(height, bbMaxY);
        myBeginRendering(minX, minY, maxX - minX, maxY - minY, windingRule);
    
private voidmyBeginRendering(int minX, int minY, int width, int height, int windingRule)

        inSubpath = false;
        
        int maxX = minX + width;
        int maxY = minY + height;
        
        minX = Math.max(minX, 0);
        minX = Math.max(minX, bbMinX);

        minY = Math.max(minY, 0);
        minY = Math.max(minY, bbMinY);

        maxX = Math.min(maxX, this.width);
        maxX = Math.min(maxX, bbMaxX);

        maxY = Math.min(maxY, this.height);
        maxY = Math.min(maxY, bbMaxY);

        width = maxX - minX;
        height = maxY - minY;
        rdr.beginRendering(minX, minY, width, height, windingRule);
    
private voidmyEndRendering()

        rdr.endRendering();
    
public voidquadTo(int x1, int y1, int x2, int y2)

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.quadTo(" +
                                  x1 + ", " + y1 + ", " +
                                  x2 + ", " + y2 + ");");
            }
        }
        inSubpath = true;
        externalConsumer.quadTo(x1, y1, x2, y2);
    
private voidrenderPath(int numCommands, byte[] commands, float[] coordsXY, int windingRule)

        beginRendering(windingRule);
        int clen = coordsXY.length;
	int offset = 0;
        for (int i = 0; i < numCommands; i++) {
            int command = commands[i] & 0xff;
            switch (command) {
            case COMMAND_MOVE_TO:
                if (offset >= 0 & offset < clen - 1) {
                    int x0 = (int)(coordsXY[offset++]*65536.0f);
                    int y0 = (int)(coordsXY[offset++]*65536.0f);
                    moveTo(x0, y0);
                }
                break;

            case COMMAND_LINE_TO:
                if (offset >= 0 & offset < clen - 1) {
                    int x1 = (int)(coordsXY[offset++]*65536.0f);
                    int y1 = (int)(coordsXY[offset++]*65536.0f);
                    lineTo(x1, y1);
                }
                break;

            case COMMAND_QUAD_TO:
                if (offset >= 0 & offset < clen - 3) {
                    int x1 = (int)(coordsXY[offset++]*65536.0f);
                    int y1 = (int)(coordsXY[offset++]*65536.0f);
                    int x2 = (int)(coordsXY[offset++]*65536.0f);
                    int y2 = (int)(coordsXY[offset++]*65536.0f);
                    quadTo(x1, y1, x2, y2);
                }
                break;

            case COMMAND_CUBIC_TO:
                if (offset >= 0 & offset < clen - 5) {
                    int x1 = (int)(coordsXY[offset++]*65536.0f);
                    int y1 = (int)(coordsXY[offset++]*65536.0f);
                    int x2 = (int)(coordsXY[offset++]*65536.0f);
                    int y2 = (int)(coordsXY[offset++]*65536.0f);
                    int x3 = (int)(coordsXY[offset++]*65536.0f);
                    int y3 = (int)(coordsXY[offset++]*65536.0f);
                    cubicTo(x1, y1, x2, y2, x3, y3);
                }
                break;

            case COMMAND_CLOSE:
                close();
                break;
            }
        }
        endRendering();
    
public voidrenderPath(int numCommands, byte[] commands, float[] coordsXY, int windingRule, PiscesCache cache)
Render a complex path, possibly caching the results in a form that can be rendered more rapidly at a future time. The cache will be valid across changes in paint style, but not across changes to the transform, stroke/fill mode setting, stroke parameters, or winding rule.

The implementation does not check the validity of the cache relative to changes in the renderer state. It is up to the caller to manually invalidate the cache object as needed. The other parameters must contain a valid description of the path even if a valid cache is passed in. If cache is null, no caching is performed.

This method is equivalent to:

beginRendering(windingRule);

PiscesCache cache = getCache();
if (cache != null) {
if (cache.isValid()) {
// Render using the cached form of the path
renderFromCache(cache);
} else {
// Perform rendering and optionally place a pre-renderered
// representation of the results into the cache
renderAndComputeCache(numCommands, commands, offsets, coordsXY,
windingRule, cache);
}
} else {
// Perform rendering without a cache
renderNoCache(numCommands, commands, offsets, coordsXY, windingRule);
}

endRendering();

Any command for which the value of offsets would lead to a reference outside of the bounds of coordsXY will not be issued.

Retrieval of the bounding box using getBoundingBox following a call to render is supported.

        if (cache != null) {
            if (cache.isValid()) {
                rdr.renderFromCache(cache);
            } else {
                rdr.setCache(cache);
                renderPath(numCommands, commands, coordsXY, windingRule);
                rdr.setCache(null);
            }
        } else {
            renderPath(numCommands, commands, coordsXY, windingRule);
        }
    
public voidresetClip()
Resets the clip rectangle. Each primitive will be clipped only to the destination image bounds.

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.resetClip()");
            }
        }
        this.bbMinX = Integer.MIN_VALUE;
        this.bbMinY = Integer.MIN_VALUE;
        this.bbMaxX = Integer.MAX_VALUE;
        this.bbMaxY = Integer.MAX_VALUE;
    
public voidsetAntialiasing(boolean antialiasingOn)


        
        this.antialiasingOn = antialiasingOn;
        int samples = antialiasingOn ? 3 : 0;
        rdr.setAntialiasing(samples, samples);
        invalidate();
    
public voidsetClip(int minX, int minY, int width, int height)
Sets a clip rectangle for all primitives. Each primitive will be clipped to the intersection of this rectangle and the destination image bounds.

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.setClip(" +
                                  minX + ", " +
                                  minY + ", " +
                                  width + ", " +
                                  height + ");");
            }
        }

        this.bbMinX = minX;
        this.bbMinY = minY;
        this.bbMaxX = minX + width;
        this.bbMaxY = minY + height;
    
public voidsetColor(int red, int green, int blue, int alpha)
Sets the current paint color.

red
a value between 0 and 255.
green
a value between 0 and 255.
blue
a value between 0 and 255.
alpha
a value between 0 and 255.

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.setColor(" +
                                  red + ", " +
                                  green + ", " +
                                  blue + ", " +
                                  alpha + ");");
            }
        }
        rdr.setColor(red, green, blue, alpha);
        this.red = red;
        this.green = green;
        this.blue = blue;
        this.alpha = alpha;

        this.paint = null;
    
public voidsetColor(int red, int green, int blue)
Sets the current paint color. An alpha value of 255 is used.

red
a value between 0 and 255.
green
a value between 0 and 255.
blue
a value between 0 and 255.

        setColor(red, green, blue, 255);
    
public voidsetFill()

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.setFill();");
            }
        }
        isPathFilled = true ;
        this.externalConsumer = getFiller();
    
private voidsetGradientColorMap(int[] fractions, int[] rgba, int cycleMethod)

        if (fractions.length != rgba.length) {
            throw new IllegalArgumentException("fractions.length != rgba.length!");
        }

        if (gradientColorMap == null ||
            gcm_cycleMethod != cycleMethod ||
            arraysDiffer(gcm_fractions, fractions) ||
            arraysDiffer(gcm_rgba, rgba)) {
            this.gradientColorMap =
                new GradientColorMap(fractions, rgba, cycleMethod);
            this.gcm_cycleMethod = cycleMethod;
            this.gcm_fractions = cloneArray(fractions);
            this.gcm_rgba = cloneArray(rgba);
        }
    
public voidsetLinearGradient(int x0, int y0, int x1, int y1, int[] fractions, int[] rgba, int cycleMethod, Transform6 gradientTransform)

        setPaintTransform(gradientTransform);
        setGradientColorMap(fractions, rgba, cycleMethod);
        this.paint = new LinearGradient(x0, y0, x1, y1,
                                        paintCompoundTransform,
                                        gradientColorMap);
        rdr.setPaint(paint);
    
private voidsetPaintTransform(Transform6 paintTransform)

        this.paintTransform = new Transform6(paintTransform);
        this.paintCompoundTransform = new Transform6(paintTransform);
    
public voidsetPathData(float[] data, byte[] commands, int nCommands)

        throw new IllegalStateException("Not implemented");
    
public voidsetRadialGradient(int cx, int cy, int fx, int fy, int radius, int[] fractions, int[] rgba, int cycleMethod, Transform6 gradientTransform)

        setPaintTransform(gradientTransform);
        setGradientColorMap(fractions, rgba, cycleMethod);
        this.paint = new RadialGradient(cx, cy, fx, fy, radius,
                                        paintCompoundTransform,
                                        gradientColorMap);
        rdr.setPaint(paint);
    
public voidsetStroke(int lineWidth, int capStyle, int joinStyle, int miterLimit, int[] dashArray, int dashPhase)
Sets the current stroke parameters.

param
lineWidth the sroke width, in S15.16 format.
param
capStyle the line cap style, one of Stroker.CAP_*.
param
joinStyle the line cap style, one of Stroker.JOIN_*.
param
miterLimit the stroke miter limit, in S15.16 format.
param
dashArray an int array containing the dash segment lengths in S15.16 format, or null.
param
dashPhase the starting dash offset, in S15.16 format.

        if (enableLogging) {
            if (logStream != null) {
                logStream.print("dashArray = ");
                if (dashArray == null) {
                    logStream.println("null;");
                } else {
                    logStream.print("{");
                    for (int i = 0; i < dashArray.length; i++) {
                        logStream.print(" " + dashArray[i]);
                    }
                    logStream.print(" };");
                }

                logStream.println("pr.setStroke(" +
                                  lineWidth + ", " +
                                  capStyle + ", " +
                                  joinStyle + ", " +
                                  miterLimit + ", " +
                                  "dashArray, " +
                                  dashPhase + ");");
            }
        }
        this.lineWidth = lineWidth;
        this.capStyle = capStyle;
        this.joinStyle = joinStyle;
        this.miterLimit = miterLimit;
        this.dashArray = dashArray;
        this.dashPhase = dashPhase;
        this.strokerP = null;
        setStroke();
    
public voidsetStroke()

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.setStroke();");
            }
        }
        isPathFilled = false;
        this.externalConsumer = getStroker();
    
public voidsetTextFill()

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("pr.setTextFill();");
            }
        }
        isPathFilled = true;
        this.externalConsumer = getTextFiller();
    
public voidsetTexture(int imageType, java.lang.Object imageData, int width, int height, int offset, int stride, Transform6 textureTransform, boolean repeat)

        Transform6 textureCompoundTransform = new Transform6(this.transform);
        textureCompoundTransform.postMultiply(textureTransform);
        setPaintTransform(textureCompoundTransform);

        this.paint = new Texture(imageType, imageData,
                                 width, height, offset, stride,
                                 textureCompoundTransform, repeat);
        rdr.setPaint(paint);
    
public voidsetTransform(Transform6 transform)
Sets the current transform from user to window coordinates.

param
transform an Transform6 object.

        if (enableLogging) {
            if (logStream != null) {
                logStream.println("transform = new Transform6(" +
                                  transform.m00 + ", " +
                                  transform.m01 + ", " +
                                  transform.m10 + ", " +
                                  transform.m11 + ", " +
                                  transform.m02 + ", " +
                                  transform.m12 + ");");
                logStream.println("pr.setTransform(transform);");
            }
        }
        this.transform = transform;

        if (paint != null) {
            setPaintTransform(paintTransform);
            paint.setTransform(this.paintCompoundTransform);
            rdr.setPaint(paint);
        }

        invalidate();