FileDocCategorySizeDatePackage
JavaShapeRasterizer.javaAPI DocAndroid 1.5 API13957Wed May 06 22:41:54 BST 2009org.apache.harmony.awt.gl.render

JavaShapeRasterizer

public class JavaShapeRasterizer extends Object
author
Denis M. Kishenko
version
$Revision$

Fields Summary
static final int
POINT_CAPACITY
int
edgesCount
int
edgeCur
int[]
edgesX
int[]
edgesY
int[]
edgesYS
int[]
edgesN
int[]
edgesDY
int[]
bounds
int
boundCount
boolean[]
edgesExt
int
activeCount
float[]
activeX
int[]
activeYEnd
float[]
activeXStep
int[]
activeDY
boolean[]
activeExt
int[]
crossX
int[]
crossDY
Filler
filler
Constructors Summary
public JavaShapeRasterizer()

    
Methods Summary
voidaddActiveEdge(int levelY, int start, int end, boolean back)
Marks edge as active

        int dy = back ? -edgesDY[end] : edgesDY[start];
        if (dy <= 0) {
            return;
        }
        int x1 = edgesX[start];
        int dx = edgesX[end] - x1;
        activeX[activeCount] = x1;
        activeYEnd[activeCount] = edgesY[end];
        activeXStep[activeCount] = dx / (float)dy;
        activeDY[activeCount] = back ? -dy : dy;
        activeExt[activeCount] = back ? edgesExt[end] : edgesExt[start];
        activeCount++;
    
voidaddEdge(int x, int y, int num)
Adds to the buffers new edge

        edgesX = checkBufSize(edgesX, edgesCount);
        edgesY = checkBufSize(edgesY, edgesCount);
        edgesN = checkBufSize(edgesN, edgesCount);
        edgesX[edgesCount] = x;
        edgesY[edgesCount] = y;
        edgesN[edgesCount] = (num << 16) | edgesCount;
        edgesCount++;
    
int[]checkBufSize(int[] buf, int size)
Checks buffer size and realloc if necessary

        if (size == buf.length) {
            int[] tmp;
            tmp = new int[size + POINT_CAPACITY];
            System.arraycopy(buf, 0, tmp, 0, buf.length);
            buf = tmp;
        }
        return buf;
    
intfindActiveEdges(int levelY)
Find new active edges


        int edgeActive = edgeCur;
        while (edgeActive < edgesCount && edgesYS[edgeActive] == levelY) {
            edgeActive++;
        }

        int activeNext = edgeActive;

        while (edgeActive > edgeCur) {
            edgeActive--;
            int num = edgesN[edgeActive] & 0xFFFF;
            addActiveEdge(levelY, num, getPrev(edgeActive), true);
            addActiveEdge(levelY, num, getNext(edgeActive), false);
        }

        edgeCur = activeNext;

        if (activeNext == edgesCount) {
            return edgesY[edgesCount - 1];
        }
        return edgesYS[activeNext];
    
intgetNext(int cur)

        int n = edgesN[cur];
        int bound = n >> 16;
        int num = (n & 0xFFFF) + 1;
        if (num == bounds[bound + 1]) {
            return bounds[bound];
        }
        return num;
    
intgetNextShape(int cur)

        int bound = edgesN[cur] >> 16;
        return bounds[bound + 1];
    
intgetPrev(int cur)

        int n = edgesN[cur];
        int bound = n >> 16;
        int num = (n & 0xFFFF) - 1;
        if (num < bounds[bound]) {
            return bounds[bound + 1] - 1;
        }
        return num;
    
voidinit()


        edgesYS = new int[edgesCount];
        System.arraycopy(edgesY, 0, edgesYS, 0, edgesCount);
        // Create edgesDY
        edgesDY = new int[edgesCount];
        for(int i = 0; i < edgesCount; i++) {
            int dy = edgesY[getNext(i)] - edgesY[i];
            edgesDY[i] = dy;
        }

        // Create edgesExt
        edgesExt = new boolean[edgesCount];
        int prev = -1;
        int i = 0;
        int pos = 0;
        while(i < edgesCount) {

            TOP: {
                do {
                    if (edgesDY[i] > 0) {
                        break TOP;
                    }
                    i = getNext(i);
                } while (i != pos);
                i = pos = getNextShape(i);
                continue;
            }

            BOTTOM: {
                do {
                    if (edgesDY[i] < 0) {
                        break BOTTOM;
                    }
                    if (edgesDY[i] > 0) {
                        prev = i;
                    }
                    i = getNext(i);
                } while (i != pos);
                i = pos = getNextShape(i);
                continue;
            }

            if (prev != -1) {
                edgesExt[prev] = true;
            }
            edgesExt[i] = true;
        }

        // Sort edgesY and edgesN
        sort(edgesYS, edgesN, edgesCount);

        edgeCur = 0;
        activeCount = 0;
        activeX = new float[edgesCount];
        activeYEnd = new int[edgesCount];
        activeXStep = new float[edgesCount];
        activeDY = new int[edgesCount];
        activeExt = new boolean[edgesCount];

        crossX = new int[edgesCount];
        crossDY = new int[edgesCount];
    
voidmakeBuffer(java.awt.geom.PathIterator path, double flatness)
Prepare all buffers and variable to rasterize shape

        edgesX = new int[POINT_CAPACITY];
        edgesY = new int[POINT_CAPACITY];
        edgesN = new int[POINT_CAPACITY];
        bounds = new int[POINT_CAPACITY];
        boundCount = 0;
        edgesCount = 0;

        if (path.getWindingRule() == PathIterator.WIND_EVEN_ODD) {
            filler = new Filler.EvenOdd();
        } else {
            filler = new Filler.NonZero();
        }
        float[] coords = new float[2];
        boolean closed = true;
        while (!path.isDone()) {
            switch(path.currentSegment(coords)) {
            case PathIterator.SEG_MOVETO:
                if (!closed) {
                    boundCount++;
                    bounds = checkBufSize(bounds, boundCount);
                    bounds[boundCount] = edgesCount;
                }
                addEdge((int)coords[0], (int)coords[1], boundCount);
                closed = false;
                break;
            case PathIterator.SEG_LINETO:
                addEdge((int)coords[0], (int)coords[1], boundCount);
                break;
            case PathIterator.SEG_CLOSE:
                boundCount++;
                bounds = checkBufSize(bounds, boundCount);
                bounds[boundCount] = edgesCount;
                closed = true;
                break;
            default:
                // awt.36=Wrong segment
                throw new RuntimeException(Messages.getString("awt.36")); //$NON-NLS-1$
            }
            path.next();
        }
        if (!closed) {
            boundCount++;
            bounds = checkBufSize(bounds, boundCount);
            bounds[boundCount] = edgesCount;
        }
    
public org.apache.harmony.awt.gl.MultiRectArearasterize(java.awt.Shape shape, double flatness)
Rasterizes shape with particular flatness

param
shape - the souze Shape to be rasterized
param
flatness - the rasterization flatness
return
a MultiRectArea of rasterized shape


        PathIterator path = shape.getPathIterator(null, flatness);

        // Shape is empty
        if (path.isDone()) {
            return new MultiRectArea();
        }

        makeBuffer(path, flatness);

        init();

        int y = edgesYS[0];
        int nextY = y;
        int crossCount;

        MultiRectArea.LineCash rect = new MultiRectArea.LineCash(edgesCount);
        rect.setLine(y);

        while(y <= nextY) {

            crossCount = 0;

            if (y == nextY) {

                int i = activeCount;
                while(i > 0) {
                    i--;
                    if (activeYEnd[i] == y) {

                        activeCount--;
                        int length = activeCount - i;
                        if (length != 0) {
                            int pos = i + 1;
                            System.arraycopy(activeX, pos, activeX, i, length);
                            System.arraycopy(activeYEnd, pos, activeYEnd, i, length);
                            System.arraycopy(activeXStep, pos, activeXStep, i, length);
                            System.arraycopy(activeDY, pos, activeDY, i, length);
                            System.arraycopy(activeExt, pos, activeExt, i, length);
                        }
                    }
                }

                nextY = findActiveEdges(y);
            }

            // Get X crossings
            for(int i = 0; i < activeCount; i++) {
                crossX[crossCount] = (int)Math.ceil(activeX[i]);
                crossDY[crossCount] = activeDY[i];
                crossCount++;
            }

            if (crossCount == 0) {
                rect.skipLine();
            } else {
                // Sort X crossings
                sort(crossX, crossDY, crossCount);
                filler.add(rect, crossX, crossDY, crossCount, y);
            }

            for(int i = 0; i < activeCount; i++) {
                activeX[i] += activeXStep[i];
            }

            y++;
        }

        return rect;
    
voidsort(int[] master, int[] slave, int length)
Sort buffers

        for(int i = 0; i < length - 1; i++) {
            int num = i;
            int min = master[num];
            for(int j = i + 1; j < length; j++) {
                if (master[j] < min) {
                    num = j;
                    min = master[num];
                }
            }
            if (num != i) {
                master[num] = master[i];
                master[i] = min;
                min = slave[num];
                slave[num] = slave[i];
                slave[i] = min;
            }
        }