blob: ef751ce212a0ac2a3f6811e869c1a0905a0938c7 [file] [log] [blame]
/*
* Copyright (C) 2021 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.text.cts;
import static com.google.common.truth.Truth.assertThat;
import android.content.res.Resources;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.fonts.Font;
import android.graphics.fonts.FontFamily;
import android.graphics.fonts.SystemFonts;
import android.graphics.text.PositionedGlyphs;
import android.graphics.text.TextRunShaper;
import android.icu.util.ULocale;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class NotoCJKFontRequirement {
private static final String TEST_OPEN_DOUBLE_KEY_BRACKET = "\u300C\u300E";
private static final Set<String> CJK_SCRIPT = new HashSet<>(Arrays.asList(
"Hani", // General Han character
"Hans", // Simplified Chinese
"Hant", // Tranditional Chinese
"Hira", "Hrkt", "Jpan", "Kana", // Japanese
"Hang", "Kore" // Hangul
));
private boolean isCJKSupported() {
final String[] localeNames = Resources.getSystem().getStringArray(
Resources.getSystem().getIdentifier("supported_locales", "array", "android"));
for (String locale : localeNames) {
final ULocale uLocale = ULocale.addLikelySubtags(ULocale.forLanguageTag(locale));
final String script = uLocale.getScript();
if (CJK_SCRIPT.contains(script)) {
return true;
}
}
return false;
}
// List of CJK font configuration.
private static final Set<String> CJK_FONT_PSNAMES = new HashSet<>();
static {
CJK_FONT_PSNAMES.add("NotoSansCJKsc-Regular");
CJK_FONT_PSNAMES.add("NotoSansCJKtc-Regular");
CJK_FONT_PSNAMES.add("NotoSansCJKjp-Regular");
CJK_FONT_PSNAMES.add("NotoSansCJKkr-Regular");
CJK_FONT_PSNAMES.add("NotoSerifCJKsc-Regular");
CJK_FONT_PSNAMES.add("NotoSerifCJKtc-Regular");
CJK_FONT_PSNAMES.add("NotoSerifCJKjp-Regular");
CJK_FONT_PSNAMES.add("NotoSerifCJKkr-Regular");
};
// Returns list of Noto CJK fonts.
private static List<Font> getNotoCJKFonts() {
final ArrayList<Font> cjkFonts = new ArrayList<>();
for (Font font : SystemFonts.getAvailableFonts()) {
String psName = FontFileTestUtil.getPostScriptName(font.getFile(), font.getTtcIndex());
if (CJK_FONT_PSNAMES.contains(psName)) {
cjkFonts.add(font);
}
}
return cjkFonts;
}
@Test
public void testContextualSpacing() {
if (!isCJKSupported()) {
return; // If the device doesn't support CJK language, don't require chws font.
}
Paint paint = new Paint();
// Only expect chws feature on NotoCJK fonts.
getNotoCJKFonts().forEach(font -> {
Typeface tf = new Typeface.CustomFallbackBuilder(
new FontFamily.Builder(font).build()
).build();
paint.setTextSize(100f); // Make 1em = 100px
paint.setTypeface(tf);
paint.setFontFeatureSettings("\"chws\" 0");
PositionedGlyphs offGlyphs = TextRunShaper.shapeTextRun(
TEST_OPEN_DOUBLE_KEY_BRACKET,
0, TEST_OPEN_DOUBLE_KEY_BRACKET.length(),
0, TEST_OPEN_DOUBLE_KEY_BRACKET.length(),
0f, 0f, false /* LTR */, paint);
paint.setFontFeatureSettings("\"chws\" 1");
PositionedGlyphs onGlyphs = TextRunShaper.shapeTextRun(
TEST_OPEN_DOUBLE_KEY_BRACKET,
0, TEST_OPEN_DOUBLE_KEY_BRACKET.length(),
0, TEST_OPEN_DOUBLE_KEY_BRACKET.length(),
0f, 0f, false /* LTR */, paint);
assertThat(onGlyphs.getGlyphX(1)).isLessThan(offGlyphs.getGlyphX(1));
});
}
}