diff options
| author | 2018-08-07 16:51:24 +0000 | |
|---|---|---|
| committer | 2018-08-07 16:51:24 +0000 | |
| commit | e80b45506501815061b079dcb10bf87443bd385d (patch) | |
| tree | 4d74a37a2b5bab1dfa593dd0b1565cd42b720c16 /libs/hwui/PathParser.cpp | |
| parent | 38c9e614af1f516f44f2a74fb9d0ec6963f809a8 (diff) | |
| parent | 02857a72198613a0583cdf6863edb2df59beee04 (diff) | |
Merge "Merge Android Pie into master"
Diffstat (limited to 'libs/hwui/PathParser.cpp')
| -rw-r--r-- | libs/hwui/PathParser.cpp | 153 |
1 files changed, 103 insertions, 50 deletions
diff --git a/libs/hwui/PathParser.cpp b/libs/hwui/PathParser.cpp index 2179f146115a..47fcca92bcca 100644 --- a/libs/hwui/PathParser.cpp +++ b/libs/hwui/PathParser.cpp @@ -19,9 +19,9 @@ #include "jni.h" #include <errno.h> +#include <stdlib.h> #include <utils/Log.h> #include <sstream> -#include <stdlib.h> #include <string> #include <vector> @@ -36,8 +36,8 @@ static size_t nextStart(const char* s, size_t length, size_t startIndex) { // 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') { + if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0)) && c != 'e' && + c != 'E') { return index; } index++; @@ -52,7 +52,8 @@ static size_t nextStart(const char* s, size_t length, size_t startIndex) { * @param result the result of the extraction, including the position of the * the starting position of next number, whether it is ending with a '-'. */ -static void extract(int* outEndPosition, bool* outEndWithNegOrDot, const char* s, int start, int end) { +static void extract(int* outEndPosition, bool* outEndWithNegOrDot, const char* s, int start, + int end) { // Now looking for ' ', ',', '.' or '-' from the start. int currentIndex = start; bool foundSeparator = false; @@ -64,30 +65,30 @@ static void extract(int* outEndPosition, bool* outEndWithNegOrDot, const char* s isExponential = false; char currentChar = s[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; - *outEndWithNegOrDot = true; - } - break; - case '.': - if (!secondDot) { - secondDot = true; - } else { - // This is the second dot, and it is considered as a separator. + case ' ': + case ',': foundSeparator = true; - *outEndWithNegOrDot = true; - } - break; - case 'e': - case 'E': - isExponential = true; - break; + break; + case '-': + // The negative sign following a 'e' or 'E' is not a separator. + if (currentIndex != start && !isPrevExponential) { + foundSeparator = true; + *outEndWithNegOrDot = true; + } + break; + case '.': + if (!secondDot) { + secondDot = true; + } else { + // This is the second dot, and it is considered as a separator. + foundSeparator = true; + *outEndWithNegOrDot = true; + } + break; + case 'e': + case 'E': + isExponential = true; + break; } if (foundSeparator) { break; @@ -98,7 +99,8 @@ static void extract(int* outEndPosition, bool* outEndWithNegOrDot, const char* s *outEndPosition = currentIndex; } -static float parseFloat(PathParser::ParseResult* result, const char* startPtr, size_t expectedLength) { +static float parseFloat(PathParser::ParseResult* result, const char* startPtr, + size_t expectedLength) { char* endPtr = NULL; float currentValue = strtof(startPtr, &endPtr); if ((currentValue == HUGE_VALF || currentValue == -HUGE_VALF) && errno == ERANGE) { @@ -122,8 +124,7 @@ static float parseFloat(PathParser::ParseResult* result, const char* startPtr, s * @return true on success */ static void getFloats(std::vector<float>* outPoints, PathParser::ParseResult* result, - const char* pathStr, int start, int end) { - + const char* pathStr, int start, int end) { if (pathStr[start] == 'z' || pathStr[start] == 'Z') { return; } @@ -138,8 +139,7 @@ static void getFloats(std::vector<float>* outPoints, PathParser::ParseResult* re extract(&endPosition, &endWithNegOrDot, pathStr, startPosition, end); if (startPosition < endPosition) { - float currentValue = parseFloat(result, &pathStr[startPosition], - end - startPosition); + float currentValue = parseFloat(result, &pathStr[startPosition], end - startPosition); if (result->failureOccurred) { return; } @@ -156,14 +156,67 @@ static void getFloats(std::vector<float>* outPoints, PathParser::ParseResult* re return; } -bool PathParser::isVerbValid(char verb) { - verb = tolower(verb); - return verb == 'a' || verb == 'c' || verb == 'h' || verb == 'l' || verb == 'm' || verb == 'q' - || verb == 's' || verb == 't' || verb == 'v' || verb == 'z'; +void PathParser::validateVerbAndPoints(char verb, size_t points, PathParser::ParseResult* result) { + size_t numberOfPointsExpected = -1; + switch (verb) { + case 'z': + case 'Z': + numberOfPointsExpected = 0; + break; + case 'm': + case 'l': + case 't': + case 'M': + case 'L': + case 'T': + numberOfPointsExpected = 2; + break; + case 'h': + case 'v': + case 'H': + case 'V': + numberOfPointsExpected = 1; + break; + case 'c': + case 'C': + numberOfPointsExpected = 6; + break; + case 's': + case 'q': + case 'S': + case 'Q': + numberOfPointsExpected = 4; + break; + case 'a': + case 'A': + numberOfPointsExpected = 7; + break; + default: + result->failureOccurred = true; + result->failureMessage += verb; + result->failureMessage += " is not a valid verb. "; + return; + } + if (numberOfPointsExpected == 0 && points == 0) { + return; + } + if (numberOfPointsExpected > 0 && points % numberOfPointsExpected == 0) { + return; + } + + result->failureOccurred = true; + result->failureMessage += verb; + result->failureMessage += " needs to be followed by "; + if (numberOfPointsExpected > 0) { + result->failureMessage += "a multiple of "; + } + result->failureMessage += std::to_string(numberOfPointsExpected) + + " floats. However, " + std::to_string(points) + + " float(s) are found. "; } void PathParser::getPathDataFromAsciiString(PathData* data, ParseResult* result, - const char* pathStr, size_t strLen) { + const char* pathStr, size_t strLen) { if (pathStr == NULL) { result->failureOccurred = true; result->failureMessage = "Path string cannot be NULL."; @@ -186,13 +239,11 @@ void PathParser::getPathDataFromAsciiString(PathData* data, ParseResult* result, end = nextStart(pathStr, strLen, end); std::vector<float> points; getFloats(&points, result, pathStr, start, end); - if (!isVerbValid(pathStr[start])) { - result->failureOccurred = true; - result->failureMessage = "Invalid pathData. Failure occurred at position " - + std::to_string(start) + " of path: " + pathStr; - } - // If either verb or points is not valid, return immediately. + validateVerbAndPoints(pathStr[start], points.size(), result); if (result->failureOccurred) { + // If either verb or points is not valid, return immediately. + result->failureMessage += "Failure occurred at position " + + std::to_string(start) + " of path: " + pathStr; return; } data->verbs.push_back(pathStr[start]); @@ -203,10 +254,11 @@ void PathParser::getPathDataFromAsciiString(PathData* data, ParseResult* result, } if ((end - start) == 1 && start < strLen) { - if (!isVerbValid(pathStr[start])) { - result->failureOccurred = true; - result->failureMessage = "Invalid pathData. Failure occurred at position " - + std::to_string(start) + " of path: " + pathStr; + validateVerbAndPoints(pathStr[start], 0, result); + if (result->failureOccurred) { + // If either verb or points is not valid, return immediately. + result->failureMessage += "Failure occurred at position " + + std::to_string(start) + " of path: " + pathStr; return; } data->verbs.push_back(pathStr[start]); @@ -235,7 +287,8 @@ void PathParser::dump(const PathData& data) { ALOGD("points are : %s", os.str().c_str()); } -void PathParser::parseAsciiStringForSkPath(SkPath* skPath, ParseResult* result, const char* pathStr, size_t strLen) { +void PathParser::parseAsciiStringForSkPath(SkPath* skPath, ParseResult* result, const char* pathStr, + size_t strLen) { PathData pathData; getPathDataFromAsciiString(&pathData, result, pathStr, strLen); if (result->failureOccurred) { @@ -252,5 +305,5 @@ void PathParser::parseAsciiStringForSkPath(SkPath* skPath, ParseResult* result, return; } -}; // namespace uirenderer -}; //namespace android +}; // namespace uirenderer +}; // namespace android |