Merge "Consolidate AssetManager calls in Font/FontFamily"
This commit is contained in:
committed by
Android (Google) Code Review
commit
e2edcebb2b
@@ -27,8 +27,6 @@
|
||||
#include <nativehelper/ScopedPrimitiveArray.h>
|
||||
#include <nativehelper/ScopedUtfChars.h>
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
#include <android_runtime/android_util_AssetManager.h>
|
||||
#include <androidfw/AssetManager2.h>
|
||||
#include "Utils.h"
|
||||
#include "FontUtils.h"
|
||||
|
||||
@@ -212,63 +210,6 @@ static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong
|
||||
return addSkTypeface(builder, std::move(data), ttcIndex, weight, isItalic);
|
||||
}
|
||||
|
||||
static void releaseAsset(const void* ptr, void* context) {
|
||||
delete static_cast<Asset*>(context);
|
||||
}
|
||||
|
||||
static jboolean FontFamily_addFontFromAssetManager(JNIEnv* env, jobject, jlong builderPtr,
|
||||
jobject jassetMgr, jstring jpath, jint cookie, jboolean isAsset, jint ttcIndex,
|
||||
jint weight, jint isItalic) {
|
||||
#ifdef __ANDROID__ // Layoutlib does not support native AssetManager
|
||||
NPE_CHECK_RETURN_ZERO(env, jassetMgr);
|
||||
NPE_CHECK_RETURN_ZERO(env, jpath);
|
||||
|
||||
NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
|
||||
Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(env, jassetMgr);
|
||||
if (NULL == mgr) {
|
||||
builder->axes.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedUtfChars str(env, jpath);
|
||||
if (str.c_str() == nullptr) {
|
||||
builder->axes.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<Asset> asset;
|
||||
{
|
||||
ScopedLock<AssetManager2> locked_mgr(*mgr);
|
||||
if (isAsset) {
|
||||
asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
|
||||
} else if (cookie > 0) {
|
||||
// Valid java cookies are 1-based, but AssetManager cookies are 0-based.
|
||||
asset = locked_mgr->OpenNonAsset(str.c_str(), static_cast<ApkAssetsCookie>(cookie - 1),
|
||||
Asset::ACCESS_BUFFER);
|
||||
} else {
|
||||
asset = locked_mgr->OpenNonAsset(str.c_str(), Asset::ACCESS_BUFFER);
|
||||
}
|
||||
}
|
||||
|
||||
if (nullptr == asset) {
|
||||
builder->axes.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
const void* buf = asset->getBuffer(false);
|
||||
if (NULL == buf) {
|
||||
builder->axes.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
sk_sp<SkData> data(SkData::MakeWithProc(buf, asset->getLength(), releaseAsset,
|
||||
asset.release()));
|
||||
return addSkTypeface(builder, std::move(data), ttcIndex, weight, isItalic);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void FontFamily_addAxisValue(CRITICAL_JNI_PARAMS_COMMA jlong builderPtr, jint tag, jfloat value) {
|
||||
NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
|
||||
builder->axes.push_back({static_cast<minikin::AxisTag>(tag), value});
|
||||
@@ -284,8 +225,6 @@ static const JNINativeMethod gFontFamilyMethods[] = {
|
||||
{ "nAddFont", "(JLjava/nio/ByteBuffer;III)Z", (void*)FontFamily_addFont },
|
||||
{ "nAddFontWeightStyle", "(JLjava/nio/ByteBuffer;III)Z",
|
||||
(void*)FontFamily_addFontWeightStyle },
|
||||
{ "nAddFontFromAssetManager", "(JLandroid/content/res/AssetManager;Ljava/lang/String;IZIII)Z",
|
||||
(void*)FontFamily_addFontFromAssetManager },
|
||||
{ "nAddAxisValue", "(JIF)V", (void*)FontFamily_addAxisValue },
|
||||
};
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
#include "GraphicsJNI.h"
|
||||
#include <nativehelper/ScopedUtfChars.h>
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
#include <android_runtime/android_util_AssetManager.h>
|
||||
#include <androidfw/AssetManager2.h>
|
||||
#include "Utils.h"
|
||||
#include "FontUtils.h"
|
||||
|
||||
@@ -48,14 +46,6 @@ static inline NativeFontBuilder* toBuilder(jlong ptr) {
|
||||
return reinterpret_cast<NativeFontBuilder*>(ptr);
|
||||
}
|
||||
|
||||
static inline Asset* toAsset(jlong ptr) {
|
||||
return reinterpret_cast<Asset*>(ptr);
|
||||
}
|
||||
|
||||
static void releaseAsset(jlong asset) {
|
||||
delete toAsset(asset);
|
||||
}
|
||||
|
||||
static void releaseFont(jlong font) {
|
||||
delete reinterpret_cast<FontWrapper*>(font);
|
||||
}
|
||||
@@ -78,54 +68,6 @@ static void release_global_ref(const void* /*data*/, void* context) {
|
||||
env->DeleteGlobalRef(obj);
|
||||
}
|
||||
|
||||
// Regular JNI
|
||||
static jlong Font_Builder_getNativeAsset(
|
||||
JNIEnv* env, jobject clazz, jobject assetMgr, jstring path, jboolean isAsset, jint cookie) {
|
||||
#ifdef __ANDROID__ // Layoutlib does not support native AssetManager
|
||||
NPE_CHECK_RETURN_ZERO(env, assetMgr);
|
||||
NPE_CHECK_RETURN_ZERO(env, path);
|
||||
|
||||
Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(env, assetMgr);
|
||||
if (mgr == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ScopedUtfChars str(env, path);
|
||||
if (str.c_str() == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::unique_ptr<Asset> asset;
|
||||
{
|
||||
ScopedLock<AssetManager2> locked_mgr(*mgr);
|
||||
if (isAsset) {
|
||||
asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
|
||||
} else if (cookie > 0) {
|
||||
// Valid java cookies are 1-based, but AssetManager cookies are 0-based.
|
||||
asset = locked_mgr->OpenNonAsset(str.c_str(), static_cast<ApkAssetsCookie>(cookie - 1),
|
||||
Asset::ACCESS_BUFFER);
|
||||
} else {
|
||||
asset = locked_mgr->OpenNonAsset(str.c_str(), Asset::ACCESS_BUFFER);
|
||||
}
|
||||
}
|
||||
|
||||
return reinterpret_cast<jlong>(asset.release());
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Regular JNI
|
||||
static jobject Font_Builder_getAssetBuffer(JNIEnv* env, jobject clazz, jlong nativeAsset) {
|
||||
Asset* asset = toAsset(nativeAsset);
|
||||
return env->NewDirectByteBuffer(const_cast<void*>(asset->getBuffer(false)), asset->getLength());
|
||||
}
|
||||
|
||||
// CriticalNative
|
||||
static jlong Font_Builder_getReleaseNativeAssetFunc(CRITICAL_JNI_PARAMS) {
|
||||
return reinterpret_cast<jlong>(&releaseAsset);
|
||||
}
|
||||
|
||||
// Regular JNI
|
||||
static jlong Font_Builder_initBuilder(JNIEnv*, jobject) {
|
||||
return reinterpret_cast<jlong>(new NativeFontBuilder());
|
||||
@@ -196,11 +138,6 @@ static const JNINativeMethod gFontBuilderMethods[] = {
|
||||
{ "nAddAxis", "(JIF)V", (void*) Font_Builder_addAxis },
|
||||
{ "nBuild", "(JLjava/nio/ByteBuffer;Ljava/lang/String;IZI)J", (void*) Font_Builder_build },
|
||||
{ "nGetReleaseNativeFont", "()J", (void*) Font_Builder_getReleaseNativeFont },
|
||||
|
||||
{ "nGetNativeAsset", "(Landroid/content/res/AssetManager;Ljava/lang/String;ZI)J",
|
||||
(void*) Font_Builder_getNativeAsset },
|
||||
{ "nGetAssetBuffer", "(J)Ljava/nio/ByteBuffer;", (void*) Font_Builder_getAssetBuffer },
|
||||
{ "nGetReleaseNativeAssetFunc", "()J", (void*) Font_Builder_getReleaseNativeAssetFunc },
|
||||
};
|
||||
|
||||
int register_android_graphics_fonts_Font(JNIEnv* env) {
|
||||
|
||||
@@ -19,6 +19,7 @@ package android.graphics;
|
||||
import android.annotation.Nullable;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.res.AssetManager;
|
||||
import android.graphics.fonts.Font;
|
||||
import android.graphics.fonts.FontVariationAxis;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
@@ -195,18 +196,13 @@ public class FontFamily {
|
||||
if (mBuilderPtr == 0) {
|
||||
throw new IllegalStateException("Unable to call addFontFromAsset after freezing.");
|
||||
}
|
||||
if (axes != null) {
|
||||
for (FontVariationAxis axis : axes) {
|
||||
nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
|
||||
}
|
||||
}
|
||||
return nAddFontFromAssetManager(mBuilderPtr, mgr, path, cookie, isAsset, ttcIndex, weight,
|
||||
isItalic);
|
||||
}
|
||||
|
||||
// TODO: Remove once internal user stop using private API.
|
||||
private static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex) {
|
||||
return nAddFont(builderPtr, font, ttcIndex, -1, -1);
|
||||
try {
|
||||
ByteBuffer buffer = Font.Builder.createBuffer(mgr, path, isAsset, cookie);
|
||||
return addFontFromBuffer(buffer, ttcIndex, axes, weight, isItalic);
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static native long nInitBuilder(String langs, int variant);
|
||||
@@ -225,8 +221,6 @@ public class FontFamily {
|
||||
int weight, int isItalic);
|
||||
private static native boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font,
|
||||
int ttcIndex, int weight, int isItalic);
|
||||
private static native boolean nAddFontFromAssetManager(long builderPtr, AssetManager mgr,
|
||||
String path, int cookie, boolean isAsset, int ttcIndex, int weight, int isItalic);
|
||||
|
||||
// The added axis values are only valid for the next nAddFont* method call.
|
||||
@CriticalNative
|
||||
|
||||
@@ -19,6 +19,7 @@ package android.graphics.fonts;
|
||||
import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.content.res.AssetManager;
|
||||
import android.content.res.Resources;
|
||||
import android.os.LocaleList;
|
||||
@@ -35,7 +36,9 @@ import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
@@ -54,10 +57,6 @@ public final class Font {
|
||||
* A builder class for creating new Font.
|
||||
*/
|
||||
public static final class Builder {
|
||||
private static final NativeAllocationRegistry sAssetByteBufferRegistry =
|
||||
NativeAllocationRegistry.createMalloced(ByteBuffer.class.getClassLoader(),
|
||||
nGetReleaseNativeAssetFunc());
|
||||
|
||||
private static final NativeAllocationRegistry sFontRegistry =
|
||||
NativeAllocationRegistry.createMalloced(Font.class.getClassLoader(),
|
||||
nGetReleaseNativeFont());
|
||||
@@ -151,7 +150,11 @@ public final class Font {
|
||||
* @param path the file name of the font data in the asset directory
|
||||
*/
|
||||
public Builder(@NonNull AssetManager am, @NonNull String path) {
|
||||
this(am, path, true /* is asset */, 0 /* cookie */);
|
||||
try {
|
||||
mBuffer = createBuffer(am, path, true /* is asset */, 0 /* cookie */);
|
||||
} catch (IOException e) {
|
||||
mException = e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,18 +168,11 @@ public final class Font {
|
||||
*/
|
||||
public Builder(@NonNull AssetManager am, @NonNull String path, boolean isAsset,
|
||||
int cookie) {
|
||||
final long nativeAsset = nGetNativeAsset(am, path, isAsset, cookie);
|
||||
if (nativeAsset == 0) {
|
||||
mException = new FileNotFoundException("Unable to open " + path);
|
||||
return;
|
||||
try {
|
||||
mBuffer = createBuffer(am, path, isAsset, cookie);
|
||||
} catch (IOException e) {
|
||||
mException = e;
|
||||
}
|
||||
final ByteBuffer b = nGetAssetBuffer(nativeAsset);
|
||||
sAssetByteBufferRegistry.registerNativeAllocation(b, nativeAsset);
|
||||
if (b == null) {
|
||||
mException = new FileNotFoundException(path + " not found");
|
||||
return;
|
||||
}
|
||||
mBuffer = b;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,19 +195,64 @@ public final class Font {
|
||||
mException = new FileNotFoundException(resId + " must be font file.");
|
||||
return;
|
||||
}
|
||||
final long nativeAsset = nGetNativeAsset(res.getAssets(), str, false /* is asset */,
|
||||
value.assetCookie);
|
||||
if (nativeAsset == 0) {
|
||||
mException = new FileNotFoundException("Unable to open " + str);
|
||||
return;
|
||||
|
||||
try {
|
||||
mBuffer = createBuffer(res.getAssets(), str, false, value.assetCookie);
|
||||
} catch (IOException e) {
|
||||
mException = e;
|
||||
}
|
||||
final ByteBuffer b = nGetAssetBuffer(nativeAsset);
|
||||
sAssetByteBufferRegistry.registerNativeAllocation(b, nativeAsset);
|
||||
if (b == null) {
|
||||
mException = new FileNotFoundException(str + " not found");
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a buffer containing font data using the assetManager and other
|
||||
* provided inputs.
|
||||
*
|
||||
* @param am the application's asset manager
|
||||
* @param path the file name of the font data in the asset directory
|
||||
* @param isAsset true if the undelying data is in asset
|
||||
* @param cookie set asset cookie
|
||||
* @return buffer containing the contents of the file
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static ByteBuffer createBuffer(@NonNull AssetManager am, @NonNull String path,
|
||||
boolean isAsset, int cookie) throws IOException {
|
||||
Preconditions.checkNotNull(am, "assetManager can not be null");
|
||||
Preconditions.checkNotNull(path, "path can not be null");
|
||||
|
||||
if (!isAsset) {
|
||||
// Attempt to open as FD, which should work unless the asset is compressed
|
||||
AssetFileDescriptor assetFD;
|
||||
try {
|
||||
if (cookie > 0) {
|
||||
assetFD = am.openNonAssetFd(cookie, path);
|
||||
} else {
|
||||
assetFD = am.openNonAssetFd(path);
|
||||
}
|
||||
|
||||
try (FileInputStream fis = assetFD.createInputStream()) {
|
||||
final FileChannel fc = fis.getChannel();
|
||||
return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// failed to open as FD so now we will attempt to open as an input stream
|
||||
}
|
||||
}
|
||||
|
||||
try (InputStream assetStream = isAsset ? am.open(path, AssetManager.ACCESS_BUFFER)
|
||||
: am.openNonAsset(cookie, path, AssetManager.ACCESS_BUFFER)) {
|
||||
|
||||
int capacity = assetStream.available();
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(capacity);
|
||||
buffer.order(ByteOrder.nativeOrder());
|
||||
assetStream.read(buffer.array(), buffer.arrayOffset(), assetStream.available());
|
||||
|
||||
if (assetStream.read() != -1) {
|
||||
throw new IOException("Unable to access full contents of " + path);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
mBuffer = b;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -395,15 +436,6 @@ public final class Font {
|
||||
return font;
|
||||
}
|
||||
|
||||
/**
|
||||
* Native methods for accessing underlying buffer in Asset
|
||||
*/
|
||||
private static native long nGetNativeAsset(
|
||||
@NonNull AssetManager am, @NonNull String path, boolean isAsset, int cookie);
|
||||
private static native ByteBuffer nGetAssetBuffer(long nativeAsset);
|
||||
@CriticalNative
|
||||
private static native long nGetReleaseNativeAssetFunc();
|
||||
|
||||
/**
|
||||
* Native methods for creating Font
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user