public static List path()

in modules/fxgutils/src/java/com/adobe/internal/fxg/swf/ShapeHelper.java [614:822]


    public static List<ShapeRecord> path(PathNode node, boolean fill)
    {
    	String data = node.data;
    	
        List<ShapeRecord> shapeRecords = new ArrayList<ShapeRecord>();

        if (data.length() == 0)
            return shapeRecords;
               
        String temp = data;
        // Split letter followed by number (i.e. "M3" becomes "M 3")
        Matcher m = charNumberPattern.matcher(data);
        if (m.find())
        {
            temp = m.replaceAll("$1 $2");
        }

        // Split number followed by letter (i.e. "3M" becomes "3 M")
        m = numberCharPattern.matcher(temp);
        temp = m.replaceAll("$1 $2");

        // Split letter followed by letter (i.e. "zM" becomes "z M")
        m = charCharPattern.matcher(temp);
        temp = m.replaceAll("$1 $2");

        //support scientific notation for floats/doubles
        m = scientificPattern.matcher(temp);
        temp = m.replaceAll("$1$3$5");
 
        // Replace commas with spaces
        m = commaPattern.matcher(temp);
        temp = m.replaceAll(" ");

        // Trim leading and trailing spaces
        temp = temp.trim();
        
        // Finally, split the string into an array 
        String[] args = spacePattern.split(temp);
        
        char ic = 0;
        char prevIc = 0;
        double lastMoveX = 0.0;
        double lastMoveY = 0.0;
        double prevX = 0.0;
        double prevY = 0.0;
        double x = 0.0;
        double y = 0.0;
        double controlX = 0.0;
        double controlY = 0.0;
        double control2X = 0.0;
        double control2Y = 0.0;
        boolean firstMove = true;
       
        for (int i = 0; i < args.length; )
        {
            boolean relative = false;
            char c = args[i].toCharArray()[0];
            if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')
            {
                ic = c;
                i++;
            }

            if ((firstMove) && (ic != 'm') && (ic != 'M'))
            	throw new FXGException(node.getStartLine(), node.getStartColumn(), "InvalidPathData");
            		
            switch (ic)
            {
                case 'm':
                    relative = true;
                case 'M':
                     if (firstMove) {
                        x = Double.parseDouble(args[i++]);
                        y = Double.parseDouble(args[i++]);
                        shapeRecords.add(move(x, y));
                        firstMove = false;
                    }
                    else 
                    {
                        //add an implicit closepath, if needed
                        if (fill && (Math.abs(prevX-lastMoveX) > AbstractFXGNode.EPSILON || Math.abs(prevY-lastMoveY) > AbstractFXGNode.EPSILON)) 
                        {
                            if (node.stroke == null)
                                shapeRecords.addAll(straightEdge(prevX, prevY, lastMoveX, lastMoveY));
                            else
                                shapeRecords.addAll(implicitClosepath(prevX, prevY, lastMoveX, lastMoveY));
                        }
                        x = Double.parseDouble(args[i++]) + (relative ? prevX : 0);
                        y = Double.parseDouble(args[i++]) + (relative ? prevY : 0);
                        shapeRecords.add(move(x, y));
                    }
                    lastMoveX = x;
                    lastMoveY = y;
                    ic = (relative) ? 'l' : 'L';
                    break;

                case 'l':
                    relative = true;
                case 'L':
                    x = Double.parseDouble(args[i++]) + (relative ? prevX : 0);
                    y = Double.parseDouble(args[i++]) + (relative ? prevY : 0);
                    shapeRecords.addAll(straightEdge(prevX, prevY, x, y));
                    break;

                case 'h':
                    relative = true;
                case 'H':
                    x = Double.parseDouble(args[i++]) + (relative ? prevX : 0);
                    y = prevY;
                    shapeRecords.addAll(straightEdge(prevX, prevY, x, y));
                    break;

                case 'v':
                    relative = true;
                case 'V':
                    x = prevX;
                    y = Double.parseDouble(args[i++]) + (relative ? prevY : 0);
                    shapeRecords.addAll(straightEdge(prevX, prevY, x, y));
                    break;

                case 'q':
                    relative = true;
                case 'Q':
                    controlX = Double.parseDouble(args[i++]) + (relative ? prevX : 0);
                    controlY = Double.parseDouble(args[i++]) + (relative ? prevY : 0);
                    x = Double.parseDouble(args[i++]) + (relative ? prevX : 0);
                    y = Double.parseDouble(args[i++]) + (relative ? prevY : 0);
                    shapeRecords.add(curvedEdge(prevX, prevY, controlX, controlY, x, y));
                    break;

                case 't':
                    relative = true;
                case 'T':
                    // control is a reflection of the previous control point
                    if ((prevIc == 'T') || (prevIc == 't') || (prevIc == 'q') || (prevIc == 'Q'))
                    {
                        controlX = prevX + (prevX - controlX);
                        controlY = prevY + (prevY - controlY);
                    }
                    else
                    {
                        controlX = prevX;
                        controlY = prevY;
                    }
                    x = Double.parseDouble(args[i++]) + (relative ? prevX : 0);
                    y = Double.parseDouble(args[i++]) + (relative ? prevY : 0);
                    shapeRecords.add(curvedEdge(prevX, prevY, controlX, controlY, x, y));
                    break;

                case 'c':
                    relative = true;
                case 'C':
                    controlX = Double.parseDouble(args[i++]) + (relative ? prevX : 0);
                    controlY = Double.parseDouble(args[i++]) + (relative ? prevY : 0);
                    control2X = Double.parseDouble(args[i++]) + (relative ? prevX : 0);
                    control2Y = Double.parseDouble(args[i++]) + (relative ? prevY : 0);
                    x = Double.parseDouble(args[i++]) + (relative ? prevX : 0);
                    y = Double.parseDouble(args[i++]) + (relative ? prevY : 0);
                    shapeRecords.addAll(cubicToQuadratic(prevX, prevY, controlX, controlY, control2X, control2Y, x, y));
                    break;

                case 's':
                    relative = true;
                case 'S':
                    // Control1 is a reflection of the previous control2 point
                    if ((prevIc == 'S') || (prevIc == 's') || (prevIc == 'c') || (prevIc == 'C'))
                    {
                        controlX = prevX + (prevX - control2X);
                        controlY = prevY + (prevY - control2Y);
                    }
                    else
                    {
                        controlX = prevX;
                        controlY = prevY;
                    }
                    control2X = Double.parseDouble(args[i++]) + (relative ? prevX : 0);
                    control2Y = Double.parseDouble(args[i++]) + (relative ? prevY : 0);
                    x = Double.parseDouble(args[i++]) + (relative ? prevX : 0);
                    y = Double.parseDouble(args[i++]) + (relative ? prevY : 0);
                    shapeRecords.addAll(cubicToQuadratic(prevX, prevY, controlX, controlY, control2X, control2Y, x, y));
                    break;
                    
                case 'z':
                case 'Z':
                    shapeRecords.addAll(straightEdge(prevX, prevY, lastMoveX, lastMoveY));
                    x = lastMoveX;
                    y = lastMoveY;
                    break;

                default:
                	throw new FXGException(node.getStartLine(), node.getStartColumn(), "InvalidPathData");
                    
            }

            prevX = x;
            prevY = y;
            prevIc = ic;
       }
        
        //do an implicit closepath, if needed
        if (fill && (Math.abs(prevX-lastMoveX) > AbstractFXGNode.EPSILON) || (Math.abs(prevY-lastMoveY) > AbstractFXGNode.EPSILON))  
        {
            if (node.stroke == null)
                shapeRecords.addAll(straightEdge(prevX, prevY, lastMoveX, lastMoveY));
            else
                shapeRecords.addAll(implicitClosepath(prevX, prevY, lastMoveX, lastMoveY));
        }
        return shapeRecords;
    }