Use NativeAllocationRegistry instead.
Verified this doesn't cause performance regressions:
StaticLayout creation time:
MeasuredText Balanced Hyphenation : 721,055 -> 723,812: (+0.4%)
MeasuredText Balanced NoHyphenation: 527,880 -> 505,843: (-4.2%)
MeasuredText Greedy Hyphenation : 476,982 -> 460,241: (-3.5%)
MeasuredText Greedy NoHyphenation : 471,074 -> 459,013: (-2.6%)
RandomText Balanced Hyphenation : 18,566,915 -> 18,514,633: (-0.3%)
RandomText Balanced NoHyphenation : 7,697,772 -> 7,658,458: (-0.5%)
RandomText Greedy Hyphenation : 7,648,606 -> 7,602,026: (-0.6%)
RandomText Greedy NoHyphenation : 7,643,946 -> 7,618,898: (-0.3%)
MeasuredText creation time:
NoStyled Hyphenation : 18,377,293 -> 18,521,296: (+0.8%)
NoStyled Hyphenation WidthOnly : 17,852,099 -> 17,889,073: (+0.2%)
NoStyled NoHyphenation : 7,608,972 -> 7,614,311: (+0.1%)
NoStyled NoHyphenation WidthOnly : 7,194,461 -> 7,192,043: (-0.0%)
Styled Hyphenation : 15,396,698 -> 15,352,501: (-0.3%)
Styled Hyphenation WidthOnly : 14,356,020 -> 14,379,205: (+0.2%)
Styled NoHyphenation : 14,926,657 -> 14,971,723: (+0.3%)
Styled NoHyphenation WidthOnly : 13,964,537 -> 13,874,324: (-0.6%)
StaticLayout draw time:
MeasuredText NoStyled : 644,795 -> 635,241: (-1.5%)
MeasuredText NoStyled WithoutCache : 637,943 -> 616,369: (-3.4%)
MeasuredText Styled : 866,664 -> 860,322: (-0.7%)
MeasuredText Styled WithoutCache : 917,795 -> 897,164: (-2.2%)
RandomText NoStyled : 538,196 -> 533,253: (-0.9%)
RandomText NoStyled WithoutCache : 7,012,076 -> 7,047,498: (+0.5%)
RandomText Styled : 3,011,941 -> 2,999,661: (-0.4%)
RandomText Styled WithoutCache : 3,486,225 -> 3,462,493: (-0.7%)
Bug: 70185027
Test: atest CtsWidgetTestCases:EditTextTest
CtsWidgetTestCases:TextViewFadingEdgeTest
FrameworksCoreTests:TextViewFallbackLineSpacingTest
FrameworksCoreTests:TextViewTest FrameworksCoreTests:TypefaceTest
CtsGraphicsTestCases:TypefaceTest CtsWidgetTestCases:TextViewTest
CtsTextTestCases
Change-Id: I7ebb8a219a8eb07c8ad9fa432e8454e4e06be386
193 lines
7.3 KiB
Java
193 lines
7.3 KiB
Java
/*
|
|
* Copyright (C) 2014 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.annotation.Nullable;
|
|
import android.content.res.AssetManager;
|
|
import android.graphics.fonts.FontVariationAxis;
|
|
import android.text.TextUtils;
|
|
import android.util.Log;
|
|
|
|
import dalvik.annotation.optimization.CriticalNative;
|
|
|
|
import libcore.util.NativeAllocationRegistry;
|
|
|
|
import java.io.FileInputStream;
|
|
import java.io.IOException;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.channels.FileChannel;
|
|
|
|
/**
|
|
* A family of typefaces with different styles.
|
|
*
|
|
* @hide
|
|
*/
|
|
public class FontFamily {
|
|
|
|
private static String TAG = "FontFamily";
|
|
|
|
private static final NativeAllocationRegistry sBuilderRegistry = new NativeAllocationRegistry(
|
|
FontFamily.class.getClassLoader(), nGetBuilderReleaseFunc(), 64);
|
|
|
|
private @Nullable Runnable mNativeBuilderCleaner;
|
|
|
|
private static final NativeAllocationRegistry sFamilyRegistry = new NativeAllocationRegistry(
|
|
FontFamily.class.getClassLoader(), nGetFamilyReleaseFunc(), 64);
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
public long mNativePtr;
|
|
|
|
// Points native font family builder. Must be zero after freezing this family.
|
|
private long mBuilderPtr;
|
|
|
|
public FontFamily() {
|
|
mBuilderPtr = nInitBuilder(null, 0);
|
|
mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
|
|
}
|
|
|
|
public FontFamily(@Nullable String[] langs, int variant) {
|
|
final String langsString;
|
|
if (langs == null || langs.length == 0) {
|
|
langsString = null;
|
|
} else if (langs.length == 1) {
|
|
langsString = langs[0];
|
|
} else {
|
|
langsString = TextUtils.join(",", langs);
|
|
}
|
|
mBuilderPtr = nInitBuilder(langsString, variant);
|
|
mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
|
|
}
|
|
|
|
/**
|
|
* Finalize the FontFamily creation.
|
|
*
|
|
* @return boolean returns false if some error happens in native code, e.g. broken font file is
|
|
* passed, etc.
|
|
*/
|
|
public boolean freeze() {
|
|
if (mBuilderPtr == 0) {
|
|
throw new IllegalStateException("This FontFamily is already frozen");
|
|
}
|
|
mNativePtr = nCreateFamily(mBuilderPtr);
|
|
mNativeBuilderCleaner.run();
|
|
mBuilderPtr = 0;
|
|
if (mNativePtr != 0) {
|
|
sFamilyRegistry.registerNativeAllocation(this, mNativePtr);
|
|
}
|
|
return mNativePtr != 0;
|
|
}
|
|
|
|
public void abortCreation() {
|
|
if (mBuilderPtr == 0) {
|
|
throw new IllegalStateException("This FontFamily is already frozen or abandoned");
|
|
}
|
|
mNativeBuilderCleaner.run();
|
|
mBuilderPtr = 0;
|
|
}
|
|
|
|
public boolean addFont(String path, int ttcIndex, FontVariationAxis[] axes, int weight,
|
|
int italic) {
|
|
if (mBuilderPtr == 0) {
|
|
throw new IllegalStateException("Unable to call addFont after freezing.");
|
|
}
|
|
try (FileInputStream file = new FileInputStream(path)) {
|
|
FileChannel fileChannel = file.getChannel();
|
|
long fontSize = fileChannel.size();
|
|
ByteBuffer fontBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
|
|
if (axes != null) {
|
|
for (FontVariationAxis axis : axes) {
|
|
nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
|
|
}
|
|
}
|
|
return nAddFont(mBuilderPtr, fontBuffer, ttcIndex, weight, italic);
|
|
} catch (IOException e) {
|
|
Log.e(TAG, "Error mapping font file " + path);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public boolean addFontFromBuffer(ByteBuffer font, int ttcIndex, FontVariationAxis[] axes,
|
|
int weight, int italic) {
|
|
if (mBuilderPtr == 0) {
|
|
throw new IllegalStateException("Unable to call addFontWeightStyle after freezing.");
|
|
}
|
|
if (axes != null) {
|
|
for (FontVariationAxis axis : axes) {
|
|
nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
|
|
}
|
|
}
|
|
return nAddFontWeightStyle(mBuilderPtr, font, ttcIndex, weight, italic);
|
|
}
|
|
|
|
/**
|
|
* @param mgr The AssetManager to use for this context.
|
|
* @param path The path to the font file to load.
|
|
* @param cookie If available, the resource cookie given by Resources.
|
|
* @param isAsset {@code true} if this is from the assets/ folder, {@code false} if from
|
|
* resources
|
|
* @param weight The weight of the font. If 0 is given, the weight and italic will be resolved
|
|
* using the OS/2 table in the font.
|
|
* @param isItalic Whether this font is italic. If the weight is set to 0, this will be resolved
|
|
* using the OS/2 table in the font.
|
|
* @return
|
|
*/
|
|
public boolean addFontFromAssetManager(AssetManager mgr, String path, int cookie,
|
|
boolean isAsset, int ttcIndex, int weight, int isItalic,
|
|
FontVariationAxis[] axes) {
|
|
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);
|
|
}
|
|
|
|
private static native long nInitBuilder(String langs, int variant);
|
|
|
|
@CriticalNative
|
|
private static native long nCreateFamily(long mBuilderPtr);
|
|
|
|
@CriticalNative
|
|
private static native long nGetBuilderReleaseFunc();
|
|
|
|
@CriticalNative
|
|
private static native long nGetFamilyReleaseFunc();
|
|
// By passing -1 to weigth argument, the weight value is resolved by OS/2 table in the font.
|
|
// By passing -1 to italic argument, the italic value is resolved by OS/2 table in the font.
|
|
private static native boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex,
|
|
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
|
|
private static native void nAddAxisValue(long builderPtr, int tag, float value);
|
|
}
|