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

Dasher

public class Dasher extends LineSink
The Dasher class takes a series of linear commands (moveTo, lineTo, close and end) and breaks them into smaller segments according to a dash pattern array and a starting dash phase.

Issues: in J2Se, a zero length dash segment as drawn as a very short dash, whereas Pisces does not draw anything. The PostScript semantics are unclear.

Fields Summary
LineSink
output
int[]
dash
int
startPhase
int
startIdx
int
idx
int
phase
int
sx
int
sy
int
x0
int
y0
int
m00
int
m01
int
m10
int
m11
Transform4
transform
boolean
symmetric
long
ldet
boolean
firstDashOn
boolean
starting
int
sx1
int
sy1
Constructors Summary
public Dasher()
Empty constructor. setOutput and setParameters must be called prior to calling any other methods.

public Dasher(LineSink output, int[] dash, int phase, Transform4 transform)
Constructs a Dasher.

param
output an output LineSink.
param
dash an array of ints containing the dash pattern in S15.16 format.
param
phase an int containing the dash phase in S15.16 format.
param
transform a Transform4 object indicating the transform that has been previously applied to all incoming coordinates. This is required in order to compute dash lengths properly.

        setOutput(output);
        setParameters(dash, phase, transform);
    
Methods Summary
public voidclose()

        lineTo(sx, sy);
        if (firstDashOn) {
            output.lineTo(sx1, sy1);
        }
    
public voidend()

        output.end();
    
private voidgoTo(int x1, int y1)

	if ((idx % 2) == 0) {
            if (starting) {
                this.sx1 = x1;
                this.sy1 = y1;
                firstDashOn = true;
                starting = false;
            }
	    output.lineTo(x1, y1);
	} else {
            if (starting) {
                firstDashOn = false;
                starting = false;
            }
	    output.moveTo(x1, y1);
	}
	this.x0 = x1;
	this.y0 = y1;
    
public voidlineJoin()

        output.lineJoin();
    
public voidlineTo(int x1, int y1)

	while (true) {
	    int d = dash[idx] - phase;
	    int lx = x1 - x0;
	    int ly = y1 - y0;

            // Compute segment length in the untransformed
            // coordinate system
            // IMPL NOTE - use fixed point

            int l;
            if (symmetric) {
                l = (int)((PiscesMath.hypot(lx, ly)*65536L)/ldet);
            } else{
                long la = ((long)ly*m00 - (long)lx*m10)/ldet;
                long lb = ((long)ly*m01 - (long)lx*m11)/ldet;
                l = (int)PiscesMath.hypot(la, lb);
            }
	    
	    if (l < d) {
		goTo(x1, y1);
		// Advance phase within current dash segment
		phase += l;
		return;
	    }
	    
            long t;
            int xsplit, ysplit;
//             // For zero length dashses, SE appears to move 1/8 unit
//             // in device space
//             if (d == 0) {
//                 double dlx = lx/65536.0;
//                 double dly = ly/65536.0;
//                 len = PiscesMath.hypot(dlx, dly);
//                 double dt = 1.0/(8*len);
//                 double dxsplit = (x0/65536.0) + dt*dlx;
//                 double dysplit = (y0/65536.0) + dt*dly;
//                 xsplit = (int)(dxsplit*65536.0);
//                 ysplit = (int)(dysplit*65536.0);
//             } else {
                t = ((long)d << 16)/l;
                xsplit = x0 + (int)(t*(x1 - x0) >> 16);
                ysplit = y0 + (int)(t*(y1 - y0) >> 16);
//             }
	    goTo(xsplit, ysplit);
	    
	    // Advance to next dash segment
	    idx = (idx + 1) % dash.length;
	    phase = 0;
	}
    
public voidmoveTo(int x0, int y0)

 	output.moveTo(x0, y0);
	this.idx = startIdx;
	this.phase = this.startPhase;
	this.sx = this.x0 = x0;
	this.sy = this.y0 = y0;
        this.starting = true;
    
public voidsetOutput(LineSink output)
Sets the output LineSink of this Dasher.

param
output an output LineSink.

        this.output = output;
    
public voidsetParameters(int[] dash, int phase, Transform4 transform)
Sets the parameters of this Dasher.

param
dash an array of ints containing the dash pattern in S15.16 format.
param
phase an int containing the dash phase in S15.16 format.
param
transform a Transform4 object indicating the transform that has been previously applied to all incoming coordinates. This is required in order to compute dash lengths properly.

	if (phase < 0) {
	    throw new IllegalArgumentException("phase < 0 !");
	}

	// Normalize so 0 <= phase < dash[0]
	int idx = 0;
	int d;
	while (phase >= (d = dash[idx])) {
	    phase -= d;
	    idx = (idx + 1) % dash.length;
	}

	this.dash = new int[dash.length];
	for (int i = 0; i < dash.length; i++) {
	    this.dash[i] = dash[i];
	}
	this.startPhase = this.phase = phase;
	this.startIdx = idx;

        this.transform = transform;

        this.m00 = transform.m00;
        this.m01 = transform.m01;
        this.m10 = transform.m10;
        this.m11 = transform.m11;
        this.ldet = ((long)m00*m11 - (long)m01*m10) >> 16;
        this.symmetric = (m00 == m11 && m10 == -m01);