summaryrefslogtreecommitdiff
path: root/libs/hwui/PathParser.cpp
diff options
context:
space:
mode:
author Xin Li <delphij@google.com> 2018-08-07 16:51:24 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2018-08-07 16:51:24 +0000
commite80b45506501815061b079dcb10bf87443bd385d (patch)
tree4d74a37a2b5bab1dfa593dd0b1565cd42b720c16 /libs/hwui/PathParser.cpp
parent38c9e614af1f516f44f2a74fb9d0ec6963f809a8 (diff)
parent02857a72198613a0583cdf6863edb2df59beee04 (diff)
Merge "Merge Android Pie into master"
Diffstat (limited to 'libs/hwui/PathParser.cpp')
-rw-r--r--libs/hwui/PathParser.cpp153
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