2128 lines · 78.3 KB · Java
RawDownload
         PathIterator pi = p2df.getPathIterator(null);         while (!pi.isDone()) {            switch (pi.currentSegment(coords)) {                case PathIterator.SEG_MOVETO:                    /* Performing closing of the unclosed segments */                    if (subpathStarted && !skip) {                        if (hnd.clipMode == PH_MODE_FILL_CLIP) {                            if (tCoords[0] != closeCoord[0] ||                                tCoords[1] != closeCoord[1])                            {                                ProcessLine(hnd, tCoords[0], tCoords[1],                                            closeCoord[0], closeCoord[1],                                            pixelInfo);                            }                        }                        hnd.processEndSubPath();                    }                     tCoords[0] = coords[0] + transXf;                    tCoords[1] = coords[1] + transYf;                     /* Checking SEG_MOVETO coordinates if they are out of the                     * [LOWER_BND, UPPER_BND] range.  This check also handles                     * NaN and Infinity values. Skipping next path segment in                     * case of invalid data.                     */                     if (tCoords[0] < UPPER_BND &&                        tCoords[0] > LOWER_BND &&                        tCoords[1] < UPPER_BND &&                        tCoords[1] > LOWER_BND)                    {                        subpathStarted = true;                        skip = false;                        closeCoord[0] = tCoords[0];                        closeCoord[1] = tCoords[1];                    } else {                        skip = true;                    }                    pixelInfo[0] = 0;                    break;                case PathIterator.SEG_LINETO:                    lastX = tCoords[2] = coords[0] + transXf;                    lastY = tCoords[3] = coords[1] + transYf;                     /* Checking SEG_LINETO coordinates if they are out of the                     * [LOWER_BND, UPPER_BND] range.  This check also handles                     * NaN and Infinity values. Ignoring current path segment                     * in case  of invalid data. If segment is skipped its                     * endpoint (if valid) is used to begin new subpath.                     */                     if (lastX < UPPER_BND &&                        lastX > LOWER_BND &&                        lastY < UPPER_BND &&                        lastY > LOWER_BND)                    {                        if (skip) {                            tCoords[0] = closeCoord[0] = lastX;                            tCoords[1] = closeCoord[1] = lastY;                            subpathStarted = true;                            skip = false;                        } else {                            ProcessLine(hnd, tCoords[0], tCoords[1],                                        tCoords[2], tCoords[3], pixelInfo);                            tCoords[0] = lastX;                            tCoords[1] = lastY;                        }                    }                    break;                case PathIterator.SEG_QUADTO:                    tCoords[2] = coords[0] + transXf;                    tCoords[3] = coords[1] + transYf;                    lastX = tCoords[4] = coords[2] + transXf;                    lastY = tCoords[5] = coords[3] + transYf;                     /* Checking SEG_QUADTO coordinates if they are out of the                     * [LOWER_BND, UPPER_BND] range.  This check also handles                     * NaN and Infinity values. Ignoring current path segment                     * in case  of invalid endpoints's data.  Equivalent to                     * the SEG_LINETO if endpoint coordinates are valid but                     * there are invalid data among other coordinates                     */                     if (lastX < UPPER_BND &&                        lastX > LOWER_BND &&                        lastY < UPPER_BND &&                        lastY > LOWER_BND)                    {                        if (skip) {                            tCoords[0] = closeCoord[0] = lastX;                            tCoords[1] = closeCoord[1] = lastY;                            subpathStarted = true;                            skip = false;                        } else {                            if (tCoords[2] < UPPER_BND &&                                tCoords[2] > LOWER_BND &&                                tCoords[3] < UPPER_BND &&                                tCoords[3] > LOWER_BND)                            {                                ProcessQuad(hnd, tCoords, pixelInfo);                            } else {                                ProcessLine(hnd, tCoords[0], tCoords[1],                                            tCoords[4], tCoords[5],                                            pixelInfo);                            }                            tCoords[0] = lastX;                            tCoords[1] = lastY;                        }                    }                    break;                case PathIterator.SEG_CUBICTO:                    tCoords[2] = coords[0] + transXf;                    tCoords[3] = coords[1] + transYf;                    tCoords[4] = coords[2] + transXf;                    tCoords[5] = coords[3] + transYf;                    lastX = tCoords[6] = coords[4] + transXf;                    lastY = tCoords[7] = coords[5] + transYf;                     /* Checking SEG_CUBICTO coordinates if they are out of the                     * [LOWER_BND, UPPER_BND] range.  This check also handles                     * NaN and Infinity values. Ignoring current path segment                     * in case  of invalid endpoints's data.  Equivalent to                     * the SEG_LINETO if endpoint coordinates are valid but                     * there are invalid data among other coordinates                     */                     if (lastX < UPPER_BND &&                        lastX > LOWER_BND &&                        lastY < UPPER_BND &&                        lastY > LOWER_BND)                    {                        if (skip) {                            tCoords[0] = closeCoord[0] = tCoords[6];                            tCoords[1] = closeCoord[1] = tCoords[7];                            subpathStarted = true;                            skip = false;                        } else {                            if (tCoords[2] < UPPER_BND &&                                tCoords[2] > LOWER_BND &&                                tCoords[3] < UPPER_BND &&                                tCoords[3] > LOWER_BND &&                                tCoords[4] < UPPER_BND &&                                tCoords[4] > LOWER_BND &&                                tCoords[5] < UPPER_BND &&                                tCoords[5] > LOWER_BND)                            {                                ProcessCubic(hnd, tCoords, pixelInfo);                            } else {                                ProcessLine(hnd, tCoords[0], tCoords[1],                                            tCoords[6], tCoords[7],                                            pixelInfo);                            }                            tCoords[0] = lastX;                            tCoords[1] = lastY;                        }                    }                    break;                case PathIterator.SEG_CLOSE:                    if (subpathStarted && !skip) {                        skip = false;                        if (tCoords[0] != closeCoord[0] ||                            tCoords[1] != closeCoord[1])                        {                            ProcessLine(hnd, tCoords[0], tCoords[1],                                        closeCoord[0], closeCoord[1],                                        pixelInfo);                             /* Storing last path's point for using in following                             * segments without initial moveTo                             */                            tCoords[0] = closeCoord[0];                            tCoords[1] = closeCoord[1];                        }                        hnd.processEndSubPath();                    }                    break;            }            pi.next();        }         /* Performing closing of the unclosed segments */        if (subpathStarted & !skip) {            if (hnd.clipMode == PH_MODE_FILL_CLIP) {                if (tCoords[0] != closeCoord[0] ||                    tCoords[1] != closeCoord[1])                {                    ProcessLine(hnd, tCoords[0], tCoords[1],                                closeCoord[0], closeCoord[1],                                pixelInfo);                }            }            hnd.processEndSubPath();        }        return true;    }     private static class Point {        public int x;        public int y;        public boolean lastPoint;        public Point prev;        public Point next;        public Point nextByY;        public Edge edge;        public Point(int x, int y, boolean lastPoint) {            this.x = x;            this.y = y;            this.lastPoint = lastPoint;        }    };     private static class Edge {        int x;        int dx;        Point p;        int  dir;        Edge prev;        Edge next;         public Edge(Point p, int x, int dx, int dir) {            this.p = p;            this.x = x;            this.dx = dx;            this.dir = dir;        }    };     /* Size of the default buffer in the FillData structure. This buffer is     * replaced with heap allocated in case of large paths.     */    private static final int DF_MAX_POINT = 256;     /* Following class accumulates points of the non-continuous flattened     * general path during iteration through the origin path's segments . The     * end of the each subpath is marked as lastPoint flag set at the last     * point     */    private static class FillData {        List<Point>  plgPnts;        public int  plgYMin;        public int  plgYMax;         public FillData() {            plgPnts = new Vector<Point>(DF_MAX_POINT);        }         public void addPoint(int x, int y, boolean lastPoint) {            if (plgPnts.size() == 0) {                plgYMin = plgYMax = y;            } else {                plgYMin = (plgYMin > y)?y:plgYMin;                plgYMax = (plgYMax < y)?y:plgYMax;            }             plgPnts.add(new Point(x, y, lastPoint));        }         public boolean isEmpty() {            return plgPnts.size() == 0;        }         public boolean isEnded() {            return plgPnts.get(plgPnts.size() - 1).lastPoint;        }         public boolean setEnded() {            return plgPnts.get(plgPnts.size() - 1).lastPoint = true;        }    }     private static class ActiveEdgeList {        Edge head;         public boolean isEmpty() {            return (head == null);        }         public void insert(Point pnt, int cy) {            Point np = pnt.next;            int X1 = pnt.x, Y1 = pnt.y;            int X2 = np.x, Y2 = np.y;            Edge ne;            if (Y1 == Y2) {                /* Skipping horizontal segments */                return;            } else {                int dX = X2 - X1;                int dY = Y2 - Y1;                int stepx, x0, dy, dir;                 if (Y1 < Y2) {                    x0 = X1;                    dy = cy - Y1;                    dir = -1;                } else { // (Y1 > Y2)                    x0 = X2;                    dy = cy - Y2;                    dir = 1;                }                 /* We need to worry only about dX because dY is in denominator                 * and abs(dy) < MDP_MULT (cy is a first scanline of the scan                 * converted segment and we subtract y coordinate of the                 * nearest segment's end from it to obtain dy)                 */                if (dX > CALC_UBND || dX < CALC_LBND)  {                    stepx = (int)((((double)dX)*MDP_MULT)/dY);                    x0 = x0 + (int)((((double)dX)*dy)/dY);                } else {                    stepx = (dX<<MDP_PREC)/dY;                    x0 += (dX*dy)/dY;                }                 ne = new Edge(pnt, x0, stepx, dir);            }             ne.next = head;            ne.prev = null;            if (head != null) {                head.prev = ne;            }            head = pnt.edge = ne;        }         public void delete(Edge e) {            Edge prevp = e.prev;            Edge nextp = e.next;            if (prevp != null) {                prevp.next = nextp;            } else {                head = nextp;            }            if (nextp != null) {                nextp.prev = prevp;            }        }         /**         * Bubble sorting in the ascending order of the linked list.  This         * implementation stops processing the list if there were no changes         * during the previous pass.         *         * We could not use O(N) Radix sort here because in most cases list of         * edges almost sorted.  So, bubble sort (O(N^2)) is working much         * better.  Note, in case of array of edges Shell sort is more         * efficient.         */        public void sort() {            Edge p, q, r, s = null, temp;            boolean wasSwap = true;             // r precedes p and s points to the node up to which            // comparisons are to be made            while (s != head.next && wasSwap) {                r = p = head;                q = p.next;                wasSwap = false;                while (p != s) {                    if (p.x >= q.x) {                        wasSwap = true;                        if (p == head) {                            temp = q.next;                            q.next = p;                            p.next = temp;                            head = q;                            r = q;                        } else {                            temp = q.next;                            q.next = p;                            p.next = temp;                            r.next = q;                            r = q;                        }                    } else {                        r = p;                        p = p.next;                    }                    q = p.next;                    if (q == s) s = p;                }            }             // correction of the back links in the double linked edge list            p = head;            q = null;            while (p != null) {                p.prev = q;                q = p;                p = p.next;            }        }    }     private static void FillPolygon(FillProcessHandler hnd,                                    int fillRule) {        int k, y, n;        boolean drawing;        Edge active;        int rightBnd = hnd.dhnd.xMax - 1;        FillData fd = hnd.fd;        int yMin = fd.plgYMin;        int yMax = fd.plgYMax;        int hashSize = ((yMax - yMin)>>MDP_PREC) + 4;         /* Because of support of the KEY_STROKE_CONTROL hint we are performing         * shift of the coordinates at the higher level         */        int hashOffset = ((yMin - 1) & MDP_W_MASK);         /* Winding counter */        int counter;         /* Calculating mask to be applied to the winding counter */        int counterMask =            (fillRule == PathIterator.WIND_NON_ZERO)? -1:1;         int pntOffset;        List<Point> pnts = fd.plgPnts;        n = pnts.size();         if (n <=1) return;         Point[] yHash = new Point[hashSize];         /* Creating double linked list (prev, next links) describing path order         * and hash table with points which fall between scanlines. nextByY         * link is used for the points which are between same scanlines.         * Scanlines are passed through the centers of the pixels.         */        Point curpt = pnts.get(0);        curpt.prev = null;        for (int i = 0; i < n - 1; i++) {            curpt = pnts.get(i);            Point nextpt = pnts.get(i + 1);            int curHashInd = (curpt.y - hashOffset - 1) >> MDP_PREC;            curpt.nextByY = yHash[curHashInd];            yHash[curHashInd] = curpt;            curpt.next = nextpt;            nextpt.prev = curpt;        }         Point ept = pnts.get(n - 1);        int curHashInd = (ept.y - hashOffset - 1) >> MDP_PREC;        ept.nextByY = yHash[curHashInd];        yHash[curHashInd] = ept;         ActiveEdgeList activeList = new ActiveEdgeList();         for (y=hashOffset + MDP_MULT,k = 0;             y<=yMax && k < hashSize; y += MDP_MULT, k++)        {            for(Point pt = yHash[k];pt != null; pt=pt.nextByY) {                /* pt.y should be inside hashed interval                 * assert(y-MDP_MULT <= pt.y && pt.y < y);                 */                if (pt.prev != null && !pt.prev.lastPoint) {                    if (pt.prev.edge != null && pt.prev.y <= y) {                        activeList.delete(pt.prev.edge);                        pt.prev.edge = null;                    } else  if (pt.prev.y > y) {                        activeList.insert(pt.prev, y);                    }                }                 if (!pt.lastPoint && pt.next != null) {                    if (pt.edge != null && pt.next.y <= y) {                        activeList.delete(pt.edge);                        pt.edge = null;                    } else if (pt.next.y > y) {                        activeList.insert(pt, y);                    }                }            }             if (activeList.isEmpty()) continue;             activeList.sort();             counter = 0;            drawing = false;            int xl, xr;            xl = xr = hnd.dhnd.xMin;            Edge curEdge = activeList.head;            while (curEdge != null) {                counter += curEdge.dir;                if ((counter & counterMask) != 0 && !drawing) {                    xl = (curEdge.x + MDP_MULT - 1)>>MDP_PREC;                    drawing = true;                }                 if ((counter & counterMask) == 0 && drawing) {                    xr = (curEdge.x - 1) >> MDP_PREC;                    if (xl <= xr) {                        hnd.dhnd.drawScanline(xl, xr, y >> MDP_PREC);                    }                    drawing = false;                }

Lines 1501–2000 of 2128. Previous lines