summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yirui Huang <yirui@google.com> 2016-11-30 01:13:00 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2016-11-30 01:13:04 +0000
commite4b016ec41bf5a11abe2adc8c55c82cf22f4da8b (patch)
tree4e90989c17f303c7436ed1c792a65fd678399329
parent5ab97721bca729107c43d4fa766270fb0961f816 (diff)
parent3002ab6729237dd608a8640794c52960b3ec54d0 (diff)
Merge "Introduce font variation settings parser"
-rw-r--r--graphics/java/android/graphics/FontListParser.java68
-rw-r--r--graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java113
2 files changed, 177 insertions, 4 deletions
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 7871aa81dded..069f81b75b32 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -21,6 +21,8 @@ import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
@@ -99,6 +101,67 @@ public class FontListParser {
}
}
+ // Note that a well-formed variation contains a four-character tag and a float as styleValue,
+ // with spacers in between. The tag is enclosd either by double quotes or single quotes.
+ @VisibleForTesting
+ public static Axis[] parseFontVariationSettings(String settings) {
+ String[] settingList = settings.split(",");
+ ArrayList<Axis> axisList = new ArrayList<>();
+ settingLoop:
+ for (String setting : settingList) {
+ int pos = 0;
+ while (pos < setting.length()) {
+ char c = setting.charAt(pos);
+ if (c == '\'' || c == '"') {
+ break;
+ } else if (!isSpacer(c)) {
+ continue settingLoop; // Only spacers are allowed before tag appeared.
+ }
+ pos++;
+ }
+ if (pos + 7 > setting.length()) {
+ continue; // 7 is the minimum length of tag-style value pair text.
+ }
+ if (setting.charAt(pos) != setting.charAt(pos + 5)) {
+ continue; // Tag should be wrapped with double or single quote.
+ }
+ String tagString = setting.substring(pos + 1, pos + 5);
+ if (!TAG_PATTERN.matcher(tagString).matches()) {
+ continue; // Skip incorrect format tag.
+ }
+ pos += 6;
+ while (pos < setting.length()) {
+ if (!isSpacer(setting.charAt(pos++))) {
+ break; // Skip spacers between the tag and the styleValue.
+ }
+ }
+ // Skip invalid styleValue
+ float styleValue;
+ String valueString = setting.substring(pos - 1);
+ if (!STYLE_VALUE_PATTERN.matcher(valueString).matches()) {
+ continue; // Skip incorrect format styleValue.
+ }
+ try {
+ styleValue = Float.parseFloat(valueString);
+ } catch (NumberFormatException e) {
+ continue; // ignoreing invalid number format
+ }
+ int tag = makeTag(tagString.charAt(0), tagString.charAt(1), tagString.charAt(2),
+ tagString.charAt(3));
+ axisList.add(new Axis(tag, styleValue));
+ }
+ return axisList.toArray(new Axis[axisList.size()]);
+ }
+
+ @VisibleForTesting
+ public static int makeTag(char c1, char c2, char c3, char c4) {
+ return (c1 << 24) + (c2 << 16) + (c3 << 8) + c4;
+ }
+
+ private static boolean isSpacer(char c) {
+ return c == ' ' || c == '\r' || c == '\t' || c == '\n';
+ }
+
private static Config readFamilies(XmlPullParser parser)
throws XmlPullParserException, IOException {
Config config = new Config();
@@ -179,10 +242,7 @@ public class FontListParser {
int tag = 0;
String tagStr = parser.getAttributeValue(null, "tag");
if (tagStr != null && TAG_PATTERN.matcher(tagStr).matches()) {
- tag = (tagStr.charAt(0) << 24) +
- (tagStr.charAt(1) << 16) +
- (tagStr.charAt(2) << 8) +
- (tagStr.charAt(3) );
+ tag = makeTag(tagStr.charAt(0), tagStr.charAt(1), tagStr.charAt(2), tagStr.charAt(3));
} else {
throw new XmlPullParserException("Invalid tag attribute value.", parser, null);
}
diff --git a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
new file mode 100644
index 000000000000..e4d6aa8b64f5
--- /dev/null
+++ b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import junit.framework.TestCase;
+
+
+public class VariationParserTest extends TestCase {
+
+ @SmallTest
+ public void testParseFontVariationSetting() {
+ int tag = FontListParser.makeTag('w', 'd', 't', 'h');
+ FontListParser.Axis[] axis = FontListParser.parseFontVariationSettings("'wdth' 1");
+ assertEquals(tag, axis[0].tag);
+ assertEquals(1.0f, axis[0].styleValue);
+
+ axis = FontListParser.parseFontVariationSettings("\"wdth\" 100");
+ assertEquals(tag, axis[0].tag);
+ assertEquals(100.0f, axis[0].styleValue);
+
+ axis = FontListParser.parseFontVariationSettings(" 'wdth' 100");
+ assertEquals(tag, axis[0].tag);
+ assertEquals(100.0f, axis[0].styleValue);
+
+ axis = FontListParser.parseFontVariationSettings("\t'wdth' 0.5");
+ assertEquals(tag, axis[0].tag);
+ assertEquals(0.5f, axis[0].styleValue);
+
+ tag = FontListParser.makeTag('A', 'X', ' ', ' ');
+ axis = FontListParser.parseFontVariationSettings("'AX ' 1");
+ assertEquals(tag, axis[0].tag);
+ assertEquals(1.0f, axis[0].styleValue);
+
+ axis = FontListParser.parseFontVariationSettings("'AX '\t1");
+ assertEquals(tag, axis[0].tag);
+ assertEquals(1.0f, axis[0].styleValue);
+
+ axis = FontListParser.parseFontVariationSettings("'AX '\n1");
+ assertEquals(tag, axis[0].tag);
+ assertEquals(1.0f, axis[0].styleValue);
+
+ axis = FontListParser.parseFontVariationSettings("'AX '\r1");
+ assertEquals(tag, axis[0].tag);
+ assertEquals(1.0f, axis[0].styleValue);
+
+ axis = FontListParser.parseFontVariationSettings("'AX '\r\t\n 1");
+ assertEquals(tag, axis[0].tag);
+ assertEquals(1.0f, axis[0].styleValue);
+
+ // Test for invalid input
+ axis = FontListParser.parseFontVariationSettings("");
+ assertEquals(0, axis.length);
+ axis = FontListParser.parseFontVariationSettings("invalid_form");
+ assertEquals(0, axis.length);
+
+ // Test with invalid tag
+ axis = FontListParser.parseFontVariationSettings("'' 1");
+ assertEquals(0, axis.length);
+ axis = FontListParser.parseFontVariationSettings("'invalid' 1");
+ assertEquals(0, axis.length);
+
+ // Test with invalid styleValue
+ axis = FontListParser.parseFontVariationSettings("'wdth' ");
+ assertEquals(0, axis.length);
+ axis = FontListParser.parseFontVariationSettings("'wdth' x");
+ assertEquals(0, axis.length);
+ axis = FontListParser.parseFontVariationSettings("'wdth' \t");
+ assertEquals(0, axis.length);
+ axis = FontListParser.parseFontVariationSettings("'wdth' \n\r");
+ assertEquals(0, axis.length);
+ }
+
+ @SmallTest
+ public void testParseFontVariationStyleSettings() {
+ FontListParser.Axis[] axis =
+ FontListParser.parseFontVariationSettings("'wdth' 10,'AX '\r1");
+ int tag1 = FontListParser.makeTag('w', 'd', 't', 'h');
+ int tag2 = FontListParser.makeTag('A', 'X', ' ', ' ');
+ assertEquals(tag1, axis[0].tag);
+ assertEquals(10.0f, axis[0].styleValue);
+ assertEquals(tag2, axis[1].tag);
+ assertEquals(1.0f, axis[1].styleValue);
+
+ // Test only spacers are allowed before tag
+ axis = FontListParser.parseFontVariationSettings(" 'wdth' 10,ab'wdth' 1");
+ tag1 = FontListParser.makeTag('w', 'd', 't', 'h');
+ assertEquals(tag1, axis[0].tag);
+ assertEquals(10.0f, axis[0].styleValue);
+ assertEquals(1, axis.length);
+ }
+
+ @SmallTest
+ public void testMakeTag() {
+ assertEquals(0x77647468, FontListParser.makeTag('w', 'd', 't', 'h'));
+ assertEquals(0x41582020, FontListParser.makeTag('A', 'X', ' ', ' '));
+ assertEquals(0x20202020, FontListParser.makeTag(' ', ' ', ' ', ' '));
+ }
+} \ No newline at end of file