Expose Resources.getFont
Based on the work already done in aapt2, load a Font from a resource id. Test: WIP Change-Id: Idc06bfbfd16452a328bfcc6ea9dcfb723b633f0c
This commit is contained in:
@@ -10681,6 +10681,7 @@ package android.content.res {
|
||||
method public android.graphics.drawable.Drawable getDrawable(int, android.content.res.Resources.Theme) throws android.content.res.Resources.NotFoundException;
|
||||
method public deprecated android.graphics.drawable.Drawable getDrawableForDensity(int, int) throws android.content.res.Resources.NotFoundException;
|
||||
method public android.graphics.drawable.Drawable getDrawableForDensity(int, int, android.content.res.Resources.Theme);
|
||||
method public android.graphics.Typeface getFont(int) throws android.content.res.Resources.NotFoundException;
|
||||
method public float getFraction(int, int, int);
|
||||
method public int getIdentifier(java.lang.String, java.lang.String, java.lang.String);
|
||||
method public int[] getIntArray(int) throws android.content.res.Resources.NotFoundException;
|
||||
|
||||
@@ -11199,6 +11199,7 @@ package android.content.res {
|
||||
method public android.graphics.drawable.Drawable getDrawable(int, android.content.res.Resources.Theme) throws android.content.res.Resources.NotFoundException;
|
||||
method public deprecated android.graphics.drawable.Drawable getDrawableForDensity(int, int) throws android.content.res.Resources.NotFoundException;
|
||||
method public android.graphics.drawable.Drawable getDrawableForDensity(int, int, android.content.res.Resources.Theme);
|
||||
method public android.graphics.Typeface getFont(int) throws android.content.res.Resources.NotFoundException;
|
||||
method public float getFraction(int, int, int);
|
||||
method public int getIdentifier(java.lang.String, java.lang.String, java.lang.String);
|
||||
method public int[] getIntArray(int) throws android.content.res.Resources.NotFoundException;
|
||||
|
||||
@@ -10713,6 +10713,7 @@ package android.content.res {
|
||||
method public android.graphics.drawable.Drawable getDrawable(int, android.content.res.Resources.Theme) throws android.content.res.Resources.NotFoundException;
|
||||
method public deprecated android.graphics.drawable.Drawable getDrawableForDensity(int, int) throws android.content.res.Resources.NotFoundException;
|
||||
method public android.graphics.drawable.Drawable getDrawableForDensity(int, int, android.content.res.Resources.Theme);
|
||||
method public android.graphics.Typeface getFont(int) throws android.content.res.Resources.NotFoundException;
|
||||
method public float getFraction(int, int, int);
|
||||
method public int getIdentifier(java.lang.String, java.lang.String, java.lang.String);
|
||||
method public int[] getIntArray(int) throws android.content.res.Resources.NotFoundException;
|
||||
|
||||
@@ -40,6 +40,7 @@ import android.annotation.StyleableRes;
|
||||
import android.annotation.XmlRes;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.graphics.Movie;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Drawable.ConstantState;
|
||||
import android.graphics.drawable.DrawableInflater;
|
||||
@@ -333,7 +334,35 @@ public class Resources {
|
||||
return res;
|
||||
}
|
||||
throw new NotFoundException("String resource ID #0x"
|
||||
+ Integer.toHexString(id));
|
||||
+ Integer.toHexString(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Typeface value associated with a particular resource ID.
|
||||
* {@more}
|
||||
*
|
||||
* @param id The desired resource identifier, as generated by the aapt
|
||||
* tool. This integer encodes the package, type, and resource
|
||||
* entry. The value 0 is an invalid identifier.
|
||||
*
|
||||
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
|
||||
*
|
||||
* @return Typeface The Typeface data associated with the resource.
|
||||
*/
|
||||
@NonNull public Typeface getFont(@StringRes int id) throws NotFoundException {
|
||||
final TypedValue value = obtainTempTypedValue();
|
||||
try {
|
||||
final ResourcesImpl impl = mResourcesImpl;
|
||||
impl.getValue(id, value, true);
|
||||
Typeface typeface = impl.loadFont(value, id);
|
||||
if (typeface != null) {
|
||||
return typeface;
|
||||
}
|
||||
} finally {
|
||||
releaseTempTypedValue(value);
|
||||
}
|
||||
throw new NotFoundException("Font resource ID #0x"
|
||||
+ Integer.toHexString(id));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,6 +31,7 @@ import android.annotation.StyleableRes;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ActivityInfo.Config;
|
||||
import android.content.res.Resources.NotFoundException;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.icu.text.PluralRules;
|
||||
@@ -47,6 +48,7 @@ import android.util.Xml;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayAdjustments;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
@@ -739,6 +741,36 @@ public class ResourcesImpl {
|
||||
return dr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a font from XML or resources stream.
|
||||
*/
|
||||
@Nullable
|
||||
public Typeface loadFont(TypedValue value, int id) {
|
||||
if (value.string == null) {
|
||||
throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
|
||||
+ Integer.toHexString(id) + ") is not a Font: " + value);
|
||||
}
|
||||
|
||||
final String file = value.string.toString();
|
||||
|
||||
if (DEBUG_LOAD) {
|
||||
Log.v(TAG, "Loading font for cookie " + value.assetCookie + ": " + file);
|
||||
}
|
||||
|
||||
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
|
||||
try {
|
||||
if (file.endsWith(".xml")) {
|
||||
// TODO handle xml type font definitions
|
||||
} else {
|
||||
return Typeface.createFromResources(
|
||||
mAssets, value.string.toString(), value.assetCookie);
|
||||
}
|
||||
} finally {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the value and id, we can get the XML filename as in value.data, based on that, we
|
||||
* first try to load CSL from the cache. If not found, try to get from the constant state.
|
||||
|
||||
@@ -190,8 +190,8 @@ static void releaseAsset(const void* ptr, void* context) {
|
||||
delete static_cast<Asset*>(context);
|
||||
}
|
||||
|
||||
static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPtr,
|
||||
jobject jassetMgr, jstring jpath) {
|
||||
static jboolean FontFamily_addFontFromAssetManager(JNIEnv* env, jobject, jlong familyPtr,
|
||||
jobject jassetMgr, jstring jpath, jint cookie, jboolean isAsset) {
|
||||
NPE_CHECK_RETURN_ZERO(env, jassetMgr);
|
||||
NPE_CHECK_RETURN_ZERO(env, jpath);
|
||||
|
||||
@@ -201,7 +201,18 @@ static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPt
|
||||
}
|
||||
|
||||
ScopedUtfChars str(env, jpath);
|
||||
Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
|
||||
if (str.c_str() == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Asset* asset;
|
||||
if (isAsset) {
|
||||
asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
|
||||
} else {
|
||||
asset = cookie ? mgr->openNonAsset(static_cast<int32_t>(cookie), str.c_str(),
|
||||
Asset::ACCESS_BUFFER) : mgr->openNonAsset(str.c_str(), Asset::ACCESS_BUFFER);
|
||||
}
|
||||
|
||||
if (NULL == asset) {
|
||||
return false;
|
||||
}
|
||||
@@ -234,8 +245,8 @@ static const JNINativeMethod gFontFamilyMethods[] = {
|
||||
{ "nAddFont", "(JLjava/nio/ByteBuffer;I)Z", (void*)FontFamily_addFont },
|
||||
{ "nAddFontWeightStyle", "(JLjava/nio/ByteBuffer;ILjava/util/List;IZ)Z",
|
||||
(void*)FontFamily_addFontWeightStyle },
|
||||
{ "nAddFontFromAsset", "(JLandroid/content/res/AssetManager;Ljava/lang/String;)Z",
|
||||
(void*)FontFamily_addFontFromAsset },
|
||||
{ "nAddFontFromAssetManager", "(JLandroid/content/res/AssetManager;Ljava/lang/String;IZ)Z",
|
||||
(void*)FontFamily_addFontFromAssetManager },
|
||||
};
|
||||
|
||||
int register_android_graphics_FontFamily(JNIEnv* env)
|
||||
|
||||
@@ -85,8 +85,9 @@ public class FontFamily {
|
||||
return nAddFontWeightStyle(mNativePtr, font, ttcIndex, axes, weight, style);
|
||||
}
|
||||
|
||||
public boolean addFontFromAsset(AssetManager mgr, String path) {
|
||||
return nAddFontFromAsset(mNativePtr, mgr, path);
|
||||
public boolean addFontFromAssetManager(AssetManager mgr, String path, int cookie,
|
||||
boolean isAsset) {
|
||||
return nAddFontFromAssetManager(mNativePtr, mgr, path, cookie, isAsset);
|
||||
}
|
||||
|
||||
private static native long nCreateFamily(String lang, int variant);
|
||||
@@ -95,6 +96,6 @@ public class FontFamily {
|
||||
private static native boolean nAddFontWeightStyle(long nativeFamily, ByteBuffer font,
|
||||
int ttcIndex, List<FontListParser.Axis> listOfAxis,
|
||||
int weight, boolean isItalic);
|
||||
private static native boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr,
|
||||
String path);
|
||||
private static native boolean nAddFontFromAssetManager(long nativeFamily, AssetManager mgr,
|
||||
String path, int cookie, boolean isAsset);
|
||||
}
|
||||
|
||||
113
graphics/java/android/graphics/FontResourcesParser.java
Normal file
113
graphics/java/android/graphics/FontResourcesParser.java
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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 org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Parser for xml type font resources.
|
||||
* @hide
|
||||
*/
|
||||
public class FontResourcesParser {
|
||||
private static final String ANDROID_NAMESPACE = "http://schemas.android.com/apk/res/android";
|
||||
|
||||
/* Parse fallback list (no names) */
|
||||
public static FontListParser.Config parse(XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
int type;
|
||||
//noinspection StatementWithEmptyBody
|
||||
while ((type=parser.next()) != XmlPullParser.START_TAG
|
||||
&& type != XmlPullParser.END_DOCUMENT) {
|
||||
// Empty loop.
|
||||
}
|
||||
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
throw new XmlPullParserException("No start tag found");
|
||||
}
|
||||
return readFamilies(parser);
|
||||
}
|
||||
|
||||
private static FontListParser.Config readFamilies(XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
FontListParser.Config config = new FontListParser.Config();
|
||||
parser.require(XmlPullParser.START_TAG, null, "font-family");
|
||||
String tag = parser.getName();
|
||||
if (tag.equals("font-family")) {
|
||||
config.families.add(readFamily(parser));
|
||||
} else {
|
||||
skip(parser);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
private static FontListParser.Family readFamily(XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
String name = parser.getAttributeValue(null, "name");
|
||||
String lang = parser.getAttributeValue(null, "lang");
|
||||
String variant = parser.getAttributeValue(null, "variant");
|
||||
List<FontListParser.Font> fonts = new ArrayList<>();
|
||||
while (parser.next() != XmlPullParser.END_TAG) {
|
||||
if (parser.getEventType() != XmlPullParser.START_TAG) continue;
|
||||
String tag = parser.getName();
|
||||
if (tag.equals("font")) {
|
||||
fonts.add(readFont(parser));
|
||||
} else {
|
||||
skip(parser);
|
||||
}
|
||||
}
|
||||
return new FontListParser.Family(name, fonts, lang, variant);
|
||||
}
|
||||
|
||||
/** Matches leading and trailing XML whitespace. */
|
||||
private static final Pattern FILENAME_WHITESPACE_PATTERN =
|
||||
Pattern.compile("^[ \\n\\r\\t]+|[ \\n\\r\\t]+$");
|
||||
|
||||
private static FontListParser.Font readFont(XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
|
||||
List<FontListParser.Axis> axes = new ArrayList<>();
|
||||
|
||||
String weightStr = parser.getAttributeValue(ANDROID_NAMESPACE, "fontWeight");
|
||||
int weight = weightStr == null ? 400 : Integer.parseInt(weightStr);
|
||||
|
||||
boolean isItalic = "italic".equals(
|
||||
parser.getAttributeValue(ANDROID_NAMESPACE, "fontStyle"));
|
||||
|
||||
String filename = parser.getAttributeValue(ANDROID_NAMESPACE, "font");
|
||||
String fullFilename = FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll("");
|
||||
return new FontListParser.Font(fullFilename, 0, axes, weight, isItalic);
|
||||
}
|
||||
|
||||
private static void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||
int depth = 1;
|
||||
while (depth > 0) {
|
||||
switch (parser.next()) {
|
||||
case XmlPullParser.START_TAG:
|
||||
depth++;
|
||||
break;
|
||||
case XmlPullParser.END_TAG:
|
||||
depth--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.graphics;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.res.AssetManager;
|
||||
import android.util.Log;
|
||||
import android.util.LongSparseArray;
|
||||
@@ -108,6 +109,30 @@ public class Typeface {
|
||||
return (mStyle & ITALIC) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Used by Resources.
|
||||
*/
|
||||
@NonNull
|
||||
public static Typeface createFromResources(AssetManager mgr, String path, int cookie) {
|
||||
if (sFallbackFonts != null) {
|
||||
synchronized (sDynamicTypefaceCache) {
|
||||
final String key = createAssetUid(mgr, path);
|
||||
Typeface typeface = sDynamicTypefaceCache.get(key);
|
||||
if (typeface != null) return typeface;
|
||||
|
||||
FontFamily fontFamily = new FontFamily();
|
||||
if (fontFamily.addFontFromAssetManager(mgr, path, cookie, false /* isAsset */)) {
|
||||
FontFamily[] families = { fontFamily };
|
||||
typeface = createFromFamiliesWithDefault(families);
|
||||
sDynamicTypefaceCache.put(key, typeface);
|
||||
return typeface;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Font resource not found " + path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a typeface object given a family name, and option style information.
|
||||
* If null is passed for the name, then the "default" font will be chosen.
|
||||
@@ -195,7 +220,7 @@ public class Typeface {
|
||||
if (typeface != null) return typeface;
|
||||
|
||||
FontFamily fontFamily = new FontFamily();
|
||||
if (fontFamily.addFontFromAsset(mgr, path)) {
|
||||
if (fontFamily.addFontFromAssetManager(mgr, path, 0, true /* isAsset */)) {
|
||||
FontFamily[] families = { fontFamily };
|
||||
typeface = createFromFamiliesWithDefault(families);
|
||||
sDynamicTypefaceCache.put(key, typeface);
|
||||
|
||||
Reference in New Issue
Block a user