diff options
| author | 2016-11-30 01:13:00 +0000 | |
|---|---|---|
| committer | 2016-11-30 01:13:04 +0000 | |
| commit | e4b016ec41bf5a11abe2adc8c55c82cf22f4da8b (patch) | |
| tree | 4e90989c17f303c7436ed1c792a65fd678399329 | |
| parent | 5ab97721bca729107c43d4fa766270fb0961f816 (diff) | |
| parent | 3002ab6729237dd608a8640794c52960b3ec54d0 (diff) | |
Merge "Introduce font variation settings parser"
| -rw-r--r-- | graphics/java/android/graphics/FontListParser.java | 68 | ||||
| -rw-r--r-- | graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java | 113 |
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 |