FileDocCategorySizeDatePackage
PathParser.javaAPI DocAndroid 5.1 API28433Thu Mar 12 22:22:10 GMT 2015android.util

PathParser

public class PathParser extends Object
hide

Fields Summary
static final String
LOGTAG
Constructors Summary
Methods Summary
private static voidaddNode(java.util.ArrayList list, char cmd, float[] val)

        list.add(new PathDataNode(cmd, val));
    
public static booleancanMorph(android.util.PathParser$PathDataNode[] nodesFrom, android.util.PathParser$PathDataNode[] nodesTo)

param
nodesFrom The source path represented in an array of PathDataNode
param
nodesTo The target path represented in an array of PathDataNode
return
whether the nodesFrom can morph into nodesTo

        if (nodesFrom == null || nodesTo == null) {
            return false;
        }

        if (nodesFrom.length != nodesTo.length) {
            return false;
        }

        for (int i = 0; i < nodesFrom.length; i ++) {
            if (nodesFrom[i].mType != nodesTo[i].mType
                    || nodesFrom[i].mParams.length != nodesTo[i].mParams.length) {
                return false;
            }
        }
        return true;
    
public static android.util.PathParser$PathDataNode[]createNodesFromPathData(java.lang.String pathData)

param
pathData The string representing a path, the same as "d" string in svg file.
return
an array of the PathDataNode.

        if (pathData == null) {
            return null;
        }
        int start = 0;
        int end = 1;

        ArrayList<PathDataNode> list = new ArrayList<PathDataNode>();
        while (end < pathData.length()) {
            end = nextStart(pathData, end);
            String s = pathData.substring(start, end).trim();
            if (s.length() > 0) {
                float[] val = getFloats(s);
                addNode(list, s.charAt(0), val);
            }

            start = end;
            end++;
        }
        if ((end - start) == 1 && start < pathData.length()) {
            addNode(list, pathData.charAt(start), new float[0]);
        }
        return list.toArray(new PathDataNode[list.size()]);
    
public static android.graphics.PathcreatePathFromPathData(java.lang.String pathData)

param
pathData The string representing a path, the same as "d" string in svg file.
return
the generated Path object.


                             
         
        Path path = new Path();
        PathDataNode[] nodes = createNodesFromPathData(pathData);
        if (nodes != null) {
            try {
                PathDataNode.nodesToPath(nodes, path);
            } catch (RuntimeException e) {
                throw new RuntimeException("Error in parsing " + pathData, e);
            }
            return path;
        }
        return null;
    
public static android.util.PathParser$PathDataNode[]deepCopyNodes(android.util.PathParser$PathDataNode[] source)

param
source The array of PathDataNode to be duplicated.
return
a deep copy of the source.

        if (source == null) {
            return null;
        }
        PathDataNode[] copy = new PathParser.PathDataNode[source.length];
        for (int i = 0; i < source.length; i ++) {
            copy[i] = new PathDataNode(source[i]);
        }
        return copy;
    
private static voidextract(java.lang.String s, int start, android.util.PathParser$ExtractFloatResult result)
Calculate the position of the next comma or space or negative sign

param
s the string to search
param
start the position to start searching
param
result the result of the extraction, including the position of the the starting position of next number, whether it is ending with a '-'.

        // Now looking for ' ', ',', '.' or '-' from the start.
        int currentIndex = start;
        boolean foundSeparator = false;
        result.mEndWithNegOrDot = false;
        boolean secondDot = false;
        boolean isExponential = false;
        for (; currentIndex < s.length(); currentIndex++) {
            boolean isPrevExponential = isExponential;
            isExponential = false;
            char currentChar = s.charAt(currentIndex);
            switch (currentChar) {
                case ' ":
                case ',":
                    foundSeparator = true;
                    break;
                case '-":
                    // The negative sign following a 'e' or 'E' is not a separator.
                    if (currentIndex != start && !isPrevExponential) {
                        foundSeparator = true;
                        result.mEndWithNegOrDot = true;
                    }
                    break;
                case '.":
                    if (!secondDot) {
                        secondDot = true;
                    } else {
                        // This is the second dot, and it is considered as a separator.
                        foundSeparator = true;
                        result.mEndWithNegOrDot = true;
                    }
                    break;
                case 'e":
                case 'E":
                    isExponential = true;
                    break;
            }
            if (foundSeparator) {
                break;
            }
        }
        // When there is nothing found, then we put the end position to the end
        // of the string.
        result.mEndPosition = currentIndex;
    
private static float[]getFloats(java.lang.String s)
Parse the floats in the string. This is an optimized version of parseFloat(s.split(",|\\s"));

param
s the string containing a command and list of floats
return
array of floats

        if (s.charAt(0) == 'z" | s.charAt(0) == 'Z") {
            return new float[0];
        }
        try {
            float[] results = new float[s.length()];
            int count = 0;
            int startPosition = 1;
            int endPosition = 0;

            ExtractFloatResult result = new ExtractFloatResult();
            int totalLength = s.length();

            // The startPosition should always be the first character of the
            // current number, and endPosition is the character after the current
            // number.
            while (startPosition < totalLength) {
                extract(s, startPosition, result);
                endPosition = result.mEndPosition;

                if (startPosition < endPosition) {
                    results[count++] = Float.parseFloat(
                            s.substring(startPosition, endPosition));
                }

                if (result.mEndWithNegOrDot) {
                    // Keep the '-' or '.' sign with next number.
                    startPosition = endPosition;
                } else {
                    startPosition = endPosition + 1;
                }
            }
            return Arrays.copyOf(results, count);
        } catch (NumberFormatException e) {
            throw new RuntimeException("error in parsing \"" + s + "\"", e);
        }
    
private static intnextStart(java.lang.String s, int end)

        char c;

        while (end < s.length()) {
            c = s.charAt(end);
            // Note that 'e' or 'E' are not valid path commands, but could be
            // used for floating point numbers' scientific notation.
            // Therefore, when searching for next command, we should ignore 'e'
            // and 'E'.
            if ((((c - 'A") * (c - 'Z") <= 0) || ((c - 'a") * (c - 'z") <= 0))
                    && c != 'e" && c != 'E") {
                return end;
            }
            end++;
        }
        return end;
    
public static voidupdateNodes(android.util.PathParser$PathDataNode[] target, android.util.PathParser$PathDataNode[] source)
Update the target's data to match the source. Before calling this, make sure canMorph(target, source) is true.

param
target The target path represented in an array of PathDataNode
param
source The source path represented in an array of PathDataNode

        for (int i = 0; i < source.length; i ++) {
            target[i].mType = source[i].mType;
            for (int j = 0; j < source[i].mParams.length; j ++) {
                target[i].mParams[j] = source[i].mParams[j];
            }
        }