Merge "Introduce font variation settings parser"
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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(' ', ' ', ' ', ' '));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user