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

JavaArcRasterizer

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

Fields Summary
Constructors Summary
Methods Summary
static voidaddSeg(org.apache.harmony.awt.gl.MultiRectArea mra, int cx1, int cy1, int cx2, int cy2, int a, int b, int[] xline, int[] yline, int[] bounds)
Adds head/tail arc segment to MultiRectArea

        switch(bounds[0]) {
        case 0:
            addY3LineSeg(mra, yline, cx2, cy1, a, bounds[1], bounds[2]);
            break;
        case 1:
            addX1LineSeg(mra, xline, cx2, cy1, b, bounds[1], bounds[2]);
            break;
        case 2:
            addX2LineSeg(mra, xline, cx1, cy1, b, bounds[1], bounds[2]);
            break;
        case 3:
            addY2LineSeg(mra, yline, cx1, cy1, a, bounds[1], bounds[2]);
            break;
        case 4:
            addY1LineSeg(mra, yline, cx1, cy2, a, bounds[1], bounds[2]);
            break;
        case 5:
            addX3LineSeg(mra, xline, cx1, cy2, b, bounds[1], bounds[2]);
            break;
        case 6:
            addX0LineSeg(mra, xline, cx2, cy2, b, bounds[1], bounds[2]);
            break;
        case 7:
            addY0LineSeg(mra, yline, cx2, cy2, a, bounds[1], bounds[2]);
            break;
        }
    
static voidaddX0Line(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int b)

        int prev = 0;
        for(int i = 0; i < line.length; i++) {
            mra.addRect(cx + prev, cy + (b - i), cx + line[i], cy + (b - i));
            prev = line[i] + 1;
        }
    
static voidaddX0LineSeg(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int b, int start, int finish)
Adds particular arc segment to mra

        int x1 = 0;
        for(int i = 0; i < line.length; i++) {
            int x2 = line[i];
            int y = cy + (b - i);
            if (x1 <= finish && x2 >= start) {
                mra.addRect(cx + Math.max(x1, start), y, cx + Math.min(x2, finish), y);
            }
            x1 = x2 + 1;
        }
    
static voidaddX1Line(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int b)

        int prev = 0;
        for(int i = 0; i < line.length; i++) {
            mra.addRect(cx + prev, cy - (b - i), cx + line[i], cy - (b - i));
            prev = line[i] + 1;
        }
    
static voidaddX1LineSeg(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int b, int start, int finish)

        int x1 = 0;
        for(int i = 0; i < line.length; i++) {
            int x2 = line[i];
            int y = cy - (b - i);
            if (x1 <= finish && x2 >= start) {
                mra.addRect(cx + Math.max(x1, start), y, cx + Math.min(x2, finish), y);
            }
            x1 = x2 + 1;
        }
    
static voidaddX2Line(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int b)

        int prev = 0;
        for(int i = 0; i < line.length; i++) {
            mra.addRect(cx - line[i], cy - (b - i), cx - prev, cy - (b - i));
            prev = line[i] + 1;
        }
    
static voidaddX2LineSeg(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int b, int start, int finish)

        int x1 = 0;
        for(int i = 0; i < line.length; i++) {
            int x2 = line[i];
            int y = cy - (b - i);
            if (x1 <= finish && x2 >= start) {
                mra.addRect(cx - Math.min(x2, finish), y, cx - Math.max(x1, start), y);
            }
            x1 = x2 + 1;
        }
    
static voidaddX3Line(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int b)

        int prev = 0;
        for(int i = 0; i < line.length; i++) {
            mra.addRect(cx - line[i], cy + (b - i), cx - prev, cy + (b - i));
            prev = line[i] + 1;
        }
    
static voidaddX3LineSeg(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int b, int start, int finish)

        int x1 = 0;
        for(int i = 0; i < line.length; i++) {
            int x2 = line[i];
            int y = cy + (b - i);
            if (x1 <= finish && x2 >= start) {
                mra.addRect(cx - Math.min(x2, finish), y, cx - Math.max(x1, start), y);
            }
            x1 = x2 + 1;
        }
    
static voidaddY0Line(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int a)

        int prev = 0;
        for(int i = 0; i < line.length; i++) {
            mra.addRect(cx + (a - i), cy + prev, cx + (a - i), cy + line[i]);
            prev = line[i] + 1;
        }
    
static voidaddY0LineSeg(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int b, int start, int finish)

        int y1 = 0;
        for(int i = 0; i < line.length; i++) {
            int x = cx + (b - i);
            int y2 = line[i];
            if (y1 <= finish && y2 >= start) {
                mra.addRect(x, cy + Math.max(y1, start), x, cy + Math.min(y2, finish));
            }
            y1 = y2 + 1;
        }
    
static voidaddY1Line(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int a)

        int prev = 0;
        for(int i = 0; i < line.length; i++) {
            mra.addRect(cx - (a - i), cy + prev, cx - (a - i), cy + line[i]);
            prev = line[i] + 1;
        }
    
static voidaddY1LineSeg(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int b, int start, int finish)

        int y1 = 0;
        for(int i = 0; i < line.length; i++) {
            int x = cx - (b - i);
            int y2 = line[i];
            if (y1 <= finish && y2 >= start) {
                mra.addRect(x, cy + Math.max(y1, start), x, cy + Math.min(y2, finish));
            }
            y1 = y2 + 1;
        }
    
static voidaddY2Line(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int a)

        int prev = 0;
        for(int i = 0; i < line.length; i++) {
            mra.addRect(cx - (a - i), cy - line[i], cx - (a - i), cy - prev);
            prev = line[i] + 1;
        }
    
static voidaddY2LineSeg(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int b, int start, int finish)

        int y1 = 0;
        for(int i = 0; i < line.length; i++) {
            int x = cx - (b - i);
            int y2 = line[i];
            if (y1 <= finish && y2 >= start) {
                mra.addRect(x, cy - Math.min(y2, finish), x, cy - Math.max(y1, start));
            }
            y1 = y2 + 1;
        }
    
static voidaddY3Line(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int a)

        int prev = 0;
        for(int i = 0; i < line.length; i++) {
            mra.addRect(cx + (a - i), cy - line[i], cx + (a - i), cy - prev);
            prev = line[i] + 1;
        }
    
static voidaddY3LineSeg(org.apache.harmony.awt.gl.MultiRectArea mra, int[] line, int cx, int cy, int b, int start, int finish)

        int y1 = 0;
        for(int i = 0; i < line.length; i++) {
            int x = cx + (b - i);
            int y2 = line[i];
            if (y1 <= finish && y2 >= start) {
                mra.addRect(x, cy - Math.min(y2, finish), x, cy - Math.max(y1, start));
            }
            y1 = y2 + 1;
        }
    
static int[]createLine(int a, int b, int xcount, int ycount)
Creates arc lookup table

        int[] buf = new int[b - ycount + 1];
        int d = a * a + 2 * b * b - 2 * a * a * b;
        int x = 0;
        int y = b;
        while (y >= ycount) {
            if (d < 0) {
                d = d + b * b * (4 * x + 6);
            } else {
                buf[b - y] = x;
                d = d + b * b * (4 * x + 6) + 4 * a * a * (1 - y);
                y--;
            }
            x++;
        }
        return buf;
    
static doublegetNormAngle(double angle)
Returns normalized angle (from 0 to 360 degrees)

        angle -= Math.floor(angle / 360) * 360;
        if (angle < 0) {
            angle += 360;
        }
        return angle;
    
static int[]getSegment1(double angle, int ax, int ay, int xcount, int ycount)
Returns bounds for non quadratic arc head

        int[] bounds = new int[3];
        switch((int)(angle / 90)) {
        case 0:
            if (xcount <  ax) {
                bounds[0] = 0; // Y3
                bounds[1] = -ay;
                bounds[2] = ycount;
            } else {
                bounds[0] = 1; // X1
                bounds[1] = 0;
                bounds[2] = ax;
            }
            break;
        case 1:
            if (xcount > -ax) {
                bounds[0] = 2; // X2
                bounds[1] = -ax;
                bounds[2] = xcount;
            } else {
                bounds[0] = 3; // Y2
                bounds[1] = 0;
                bounds[2] = -ay;
            }
            break;
        case 2:
            if (xcount < -ax) {
                bounds[0] = 4; // Y1
                bounds[1] = ay;
                bounds[2] = ycount;
            } else {
                bounds[0] = 5; // X3
                bounds[1] = 0;
                bounds[2] = -ax;
            }
            break;
        case 3:
            if (xcount >  ax) {
                bounds[0] = 6; // X0
                bounds[1] = ax;
                bounds[2] = xcount;
            } else {
                bounds[0] = 7; // Y0
                bounds[1] = 0;
                bounds[2] = ay;
            }
            break;
        }
        return bounds;
    
static int[]getSegment2(double angle, int ax, int ay, int xcount, int ycount)
Returns bounds for non quadratic arc tail

        int[] bounds = new int[3];
        switch((int)(angle / 90)) {
        case 0:
            if (xcount <  ax) {
                bounds[0] = 0; // Y3
                bounds[1] = 0;
                bounds[2] = -ay;
            } else {
                bounds[0] = 1; // X1
                bounds[1] = ax;
                bounds[2] = xcount;
            }
            break;
        case 1:
            if (xcount > -ax) {
                bounds[0] = 2; // X2
                bounds[1] = 0;
                bounds[2] = -ax;
            } else {
                bounds[0] = 3; // Y2
                bounds[1] = -ay;
                bounds[2] = ycount;
            }
            break;
        case 2:
            if (xcount < -ax) {
                bounds[0] = 4; // Y1
                bounds[1] = 0;
                bounds[2] = ay;
            } else {
                bounds[0] = 5; // X3
                bounds[1] = -ax;
                bounds[2] = xcount;
            }
            break;
        case 3:
            if (xcount >  ax) {
                bounds[0] = 6; // X0
                bounds[1] = 0;
                bounds[2] = ax;
            } else {
                bounds[0] = 7; // Y0
                bounds[1] = ay;
                bounds[2] = ycount;
            }
            break;
        }
        return bounds;
    
public static org.apache.harmony.awt.gl.MultiRectArearasterize(int x, int y, int width, int height, double angleStart, double angleExtent, org.apache.harmony.awt.gl.MultiRectArea clip)
Rasterizes arc using clippind and dashing style

param
x1 - the x coordinate of the left-upper corner of the arc bounds
param
y1 - the y coordinate of the left-upper corner of the arc bounds
param
width - the width of the arc bounds
param
height - the height of the arc bounds
param
angleStart - the start angle of the arc in degrees
param
angleExtent - the angle extent in degrees
param
clip - the MultiRectArea object of clipping area
return
a MultiRectArea of rasterizer arc


        MultiRectArea mra = new MultiRectArea(false);

        int cx1, cx2, cy1, cy2;
        cx1 = cx2 = x + width / 2;
        cy1 = cy2 = y + height / 2;

        if (width % 2 == 0) {
            cx2--;
        }

        if (height % 2 == 0) {
            cy2--;
        }

        int a = width / 2;
        int b = height / 2;
        double c = Math.sqrt(a * a + b * b);

        int xcount, ycount;
        if (a < b) {
            xcount = (int)Math.ceil(a * a / c);
            ycount = (int)Math.floor(b * b / c);
        } else {
            xcount = (int)Math.floor(a * a / c);
            ycount = (int)Math.ceil(b * b / c);
        }

        int[] xline = createLine(a, b, xcount, ycount);
        int[] yline = createLine(b, a, ycount, xcount);

        // Correct lines
        int i = xline.length;
        while(xline[--i] > xcount) {
            xline[i] = xcount;
        }

        i = yline.length;
        while(yline[--i] > ycount) {
            yline[i] = ycount;
        }

        if (Math.abs(angleExtent) >= 360) {
            // Rasterize CIRCLE
            addX0Line(mra, xline, cx2, cy2, b);
            addX1Line(mra, xline, cx2, cy1, b);
            addX2Line(mra, xline, cx1, cy1, b);
            addX3Line(mra, xline, cx1, cy2, b);
            addY0Line(mra, yline, cx2, cy2, a);
            addY1Line(mra, yline, cx1, cy2, a);
            addY2Line(mra, yline, cx1, cy1, a);
            addY3Line(mra, yline, cx2, cy1, a);
        } else {
            // Rasterize ARC
            angleStart = getNormAngle(angleStart);
            double angleFinish = getNormAngle(angleStart + angleExtent);

            if (angleExtent < 0) {
                double tmp = angleStart;
                angleStart = angleFinish;
                angleFinish = tmp;
            }

            double radStart = -Math.toRadians(angleStart);
            double radFinish = -Math.toRadians(angleFinish);
            int ax1 = (int)(a * Math.cos(radStart));
            int ay1 = (int)(b * Math.sin(radStart));
            int ax2 = (int)(a * Math.cos(radFinish));
            int ay2 = (int)(b * Math.sin(radFinish));

            int[] seg1 = getSegment1(angleStart, ax1, ay1, xcount, ycount);
            int[] seg2 = getSegment2(angleFinish, ax2, ay2, xcount, ycount);

            // Start and Finish located in the same quater
            if (angleStart < angleFinish && seg1[0] == seg2[0]) {
                if (seg1[0] % 2 == 0) {
                    seg1[2] = seg2[2];
                } else {
                    seg1[1] = seg2[1];
                }
                addSeg(mra, cx1, cy1, cx2, cy2, a, b, xline, yline, seg1);
                return mra;
            }

            addSeg(mra, cx1, cy1, cx2, cy2, a, b, xline, yline, seg1);
            addSeg(mra, cx1, cy1, cx2, cy2, a, b, xline, yline, seg2);

            int startSeg = (seg1[0] + 1) % 8;
            int finishSeg = seg2[0];

            while (startSeg != finishSeg) {
                switch(startSeg) {
                case 0:
                    addY3Line(mra, yline, cx2, cy1, a);
                    break;
                case 1:
                    addX1Line(mra, xline, cx2, cy1, b);
                    break;
                case 2:
                    addX2Line(mra, xline, cx1, cy1, b);
                    break;
                case 3:
                    addY2Line(mra, yline, cx1, cy1, a);
                    break;
                case 4:
                    addY1Line(mra, yline, cx1, cy2, a);
                    break;
                case 5:
                    addX3Line(mra, xline, cx1, cy2, b);
                    break;
                case 6:
                    addX0Line(mra, xline, cx2, cy2, b);
                    break;
                case 7:
                    addY0Line(mra, yline, cx2, cy2, a);
                    break;
                }
                startSeg = (startSeg + 1) % 8;
            }
        }

        if (clip != null) {
            mra.intersect(clip);
        }

        return mra;