Merge "Make Font class being able to create from native instance" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
317c0ae14c
@@ -26,8 +26,7 @@ import android.graphics.Paint;
|
|||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.os.LocaleList;
|
import android.os.LocaleList;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.util.Log;
|
import android.text.TextUtils;
|
||||||
import android.util.LongSparseArray;
|
|
||||||
import android.util.LongSparseLongArray;
|
import android.util.LongSparseLongArray;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
|
|
||||||
@@ -44,7 +43,6 @@ import java.io.FileInputStream;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
@@ -61,14 +59,9 @@ public final class Font {
|
|||||||
private static final int STYLE_ITALIC = 1;
|
private static final int STYLE_ITALIC = 1;
|
||||||
private static final int STYLE_NORMAL = 0;
|
private static final int STYLE_NORMAL = 0;
|
||||||
|
|
||||||
private static final Object MAP_LOCK = new Object();
|
private static final NativeAllocationRegistry BUFFER_REGISTRY =
|
||||||
// We need to have mapping from native ptr to Font object for later accessing from TextShape
|
NativeAllocationRegistry.createMalloced(
|
||||||
// result since Typeface doesn't have reference to Font object and it is not always created from
|
ByteBuffer.class.getClassLoader(), nGetReleaseNativeFont());
|
||||||
// Font object. Sometimes Typeface is created in native layer only and there might not be Font
|
|
||||||
// object in Java layer. So, if not found in this cache, create new Font object for API user.
|
|
||||||
@GuardedBy("MAP_LOCK")
|
|
||||||
private static final LongSparseArray<WeakReference<Font>> FONT_PTR_MAP =
|
|
||||||
new LongSparseArray<>();
|
|
||||||
|
|
||||||
private static final Object SOURCE_ID_LOCK = new Object();
|
private static final Object SOURCE_ID_LOCK = new Object();
|
||||||
@GuardedBy("SOURCE_ID_LOCK")
|
@GuardedBy("SOURCE_ID_LOCK")
|
||||||
@@ -79,9 +72,7 @@ public final class Font {
|
|||||||
* A builder class for creating new Font.
|
* A builder class for creating new Font.
|
||||||
*/
|
*/
|
||||||
public static final class Builder {
|
public static final class Builder {
|
||||||
private static final NativeAllocationRegistry sFontRegistry =
|
|
||||||
NativeAllocationRegistry.createMalloced(Font.class.getClassLoader(),
|
|
||||||
nGetReleaseNativeFont());
|
|
||||||
|
|
||||||
private @Nullable ByteBuffer mBuffer;
|
private @Nullable ByteBuffer mBuffer;
|
||||||
private @Nullable File mFile;
|
private @Nullable File mFile;
|
||||||
@@ -484,26 +475,15 @@ public final class Font {
|
|||||||
final String filePath = mFile == null ? "" : mFile.getAbsolutePath();
|
final String filePath = mFile == null ? "" : mFile.getAbsolutePath();
|
||||||
|
|
||||||
long ptr;
|
long ptr;
|
||||||
int fontIdentifier;
|
final Font font;
|
||||||
if (mFont == null) {
|
if (mFont == null) {
|
||||||
ptr = nBuild(builderPtr, readonlyBuffer, filePath, mLocaleList, mWeight, italic,
|
ptr = nBuild(builderPtr, readonlyBuffer, filePath, mLocaleList, mWeight, italic,
|
||||||
mTtcIndex);
|
mTtcIndex);
|
||||||
long fontBufferPtr = nGetFontBufferAddress(ptr);
|
font = new Font(ptr);
|
||||||
synchronized (SOURCE_ID_LOCK) {
|
|
||||||
long id = FONT_SOURCE_ID_MAP.get(fontBufferPtr, -1);
|
|
||||||
if (id == -1) {
|
|
||||||
id = FONT_SOURCE_ID_MAP.size();
|
|
||||||
FONT_SOURCE_ID_MAP.put(fontBufferPtr, id);
|
|
||||||
}
|
|
||||||
fontIdentifier = (int) id;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ptr = nClone(mFont.getNativePtr(), builderPtr, mWeight, italic, mTtcIndex);
|
ptr = nClone(mFont.getNativePtr(), builderPtr, mWeight, italic, mTtcIndex);
|
||||||
fontIdentifier = mFont.mSourceIdentifier;
|
font = new Font(ptr);
|
||||||
}
|
}
|
||||||
final Font font = new Font(ptr, readonlyBuffer, mFile,
|
|
||||||
new FontStyle(mWeight, slant), mTtcIndex, mAxes, mLocaleList, fontIdentifier);
|
|
||||||
sFontRegistry.registerNativeAllocation(font, ptr);
|
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,33 +505,32 @@ public final class Font {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final long mNativePtr; // address of the shared ptr of minikin::Font
|
private final long mNativePtr; // address of the shared ptr of minikin::Font
|
||||||
private final @NonNull ByteBuffer mBuffer;
|
private final Object mLock = new Object();
|
||||||
private final @Nullable File mFile;
|
|
||||||
private final FontStyle mFontStyle;
|
@GuardedBy("mLock")
|
||||||
private final @IntRange(from = 0) int mTtcIndex;
|
private @NonNull ByteBuffer mBuffer = null;
|
||||||
private final @Nullable FontVariationAxis[] mAxes;
|
@GuardedBy("mLock")
|
||||||
private final @NonNull String mLocaleList;
|
private boolean mIsFileInitialized = false;
|
||||||
private final int mSourceIdentifier; // An identifier of font source data.
|
@GuardedBy("mLock")
|
||||||
|
private @Nullable File mFile = null;
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private FontStyle mFontStyle = null;
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private @Nullable FontVariationAxis[] mAxes = null;
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private @NonNull LocaleList mLocaleList = null;
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private int mSourceIdentifier = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use Builder instead
|
* Use Builder instead
|
||||||
|
*
|
||||||
|
* Caller must increment underlying minikin::Font ref count.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
*/
|
*/
|
||||||
private Font(long nativePtr, @NonNull ByteBuffer buffer, @Nullable File file,
|
public Font(long nativePtr) {
|
||||||
@NonNull FontStyle fontStyle, @IntRange(from = 0) int ttcIndex,
|
|
||||||
@Nullable FontVariationAxis[] axes, @NonNull String localeList,
|
|
||||||
int sourceIdentifier) {
|
|
||||||
mBuffer = buffer;
|
|
||||||
mFile = file;
|
|
||||||
mFontStyle = fontStyle;
|
|
||||||
mNativePtr = nativePtr;
|
mNativePtr = nativePtr;
|
||||||
mTtcIndex = ttcIndex;
|
|
||||||
mAxes = axes;
|
|
||||||
mLocaleList = localeList;
|
|
||||||
mSourceIdentifier = sourceIdentifier;
|
|
||||||
|
|
||||||
synchronized (MAP_LOCK) {
|
|
||||||
FONT_PTR_MAP.append(nGetNativeFontPtr(mNativePtr), new WeakReference<>(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -563,7 +542,22 @@ public final class Font {
|
|||||||
* @return a font buffer
|
* @return a font buffer
|
||||||
*/
|
*/
|
||||||
public @NonNull ByteBuffer getBuffer() {
|
public @NonNull ByteBuffer getBuffer() {
|
||||||
return mBuffer;
|
synchronized (mLock) {
|
||||||
|
if (mBuffer == null) {
|
||||||
|
// Create new instance of native FontWrapper, i.e. incrementing ref count of
|
||||||
|
// minikin Font instance for keeping buffer fo ByteBuffer reference which may live
|
||||||
|
// longer than this object.
|
||||||
|
long ref = nCloneFont(mNativePtr);
|
||||||
|
ByteBuffer fromNative = nNewByteBuffer(mNativePtr);
|
||||||
|
|
||||||
|
// Bind ByteBuffer's lifecycle with underlying font object.
|
||||||
|
BUFFER_REGISTRY.registerNativeAllocation(fromNative, ref);
|
||||||
|
|
||||||
|
// JNI NewDirectBuffer creates writable ByteBuffer even if it is mmaped readonly.
|
||||||
|
mBuffer = fromNative.asReadOnlyBuffer();
|
||||||
|
}
|
||||||
|
return mBuffer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -574,7 +568,16 @@ public final class Font {
|
|||||||
* @return a file path of the font
|
* @return a file path of the font
|
||||||
*/
|
*/
|
||||||
public @Nullable File getFile() {
|
public @Nullable File getFile() {
|
||||||
return mFile;
|
synchronized (mLock) {
|
||||||
|
if (!mIsFileInitialized) {
|
||||||
|
String path = nGetFontPath(mNativePtr);
|
||||||
|
if (!TextUtils.isEmpty(path)) {
|
||||||
|
mFile = new File(path);
|
||||||
|
}
|
||||||
|
mIsFileInitialized = true;
|
||||||
|
}
|
||||||
|
return mFile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -585,7 +588,16 @@ public final class Font {
|
|||||||
* @return a font style
|
* @return a font style
|
||||||
*/
|
*/
|
||||||
public @NonNull FontStyle getStyle() {
|
public @NonNull FontStyle getStyle() {
|
||||||
return mFontStyle;
|
synchronized (mLock) {
|
||||||
|
if (mFontStyle == null) {
|
||||||
|
int packedStyle = nGetPackedStyle(mNativePtr);
|
||||||
|
mFontStyle = new FontStyle(
|
||||||
|
FontFileUtil.unpackWeight(packedStyle),
|
||||||
|
FontFileUtil.unpackItalic(packedStyle)
|
||||||
|
? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT);
|
||||||
|
}
|
||||||
|
return mFontStyle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -597,7 +609,7 @@ public final class Font {
|
|||||||
* @return a TTC index value
|
* @return a TTC index value
|
||||||
*/
|
*/
|
||||||
public @IntRange(from = 0) int getTtcIndex() {
|
public @IntRange(from = 0) int getTtcIndex() {
|
||||||
return mTtcIndex;
|
return nGetIndex(mNativePtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -608,7 +620,23 @@ public final class Font {
|
|||||||
* @return font variation settings
|
* @return font variation settings
|
||||||
*/
|
*/
|
||||||
public @Nullable FontVariationAxis[] getAxes() {
|
public @Nullable FontVariationAxis[] getAxes() {
|
||||||
return mAxes == null ? null : mAxes.clone();
|
synchronized (mLock) {
|
||||||
|
if (mAxes == null) {
|
||||||
|
int axisCount = nGetAxisCount(mNativePtr);
|
||||||
|
mAxes = new FontVariationAxis[axisCount];
|
||||||
|
char[] charBuffer = new char[4];
|
||||||
|
for (int i = 0; i < axisCount; ++i) {
|
||||||
|
long packedAxis = nGetAxisInfo(mNativePtr, i);
|
||||||
|
float value = Float.intBitsToFloat((int) (packedAxis & 0x0000_0000_FFFF_FFFFL));
|
||||||
|
charBuffer[0] = (char) ((packedAxis & 0xFF00_0000_0000_0000L) >>> 56);
|
||||||
|
charBuffer[1] = (char) ((packedAxis & 0x00FF_0000_0000_0000L) >>> 48);
|
||||||
|
charBuffer[2] = (char) ((packedAxis & 0x0000_FF00_0000_0000L) >>> 40);
|
||||||
|
charBuffer[3] = (char) ((packedAxis & 0x0000_00FF_0000_0000L) >>> 32);
|
||||||
|
mAxes[i] = new FontVariationAxis(new String(charBuffer), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mAxes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -618,7 +646,17 @@ public final class Font {
|
|||||||
* @return a locale list
|
* @return a locale list
|
||||||
*/
|
*/
|
||||||
public @NonNull LocaleList getLocaleList() {
|
public @NonNull LocaleList getLocaleList() {
|
||||||
return LocaleList.forLanguageTags(mLocaleList);
|
synchronized (mLock) {
|
||||||
|
if (mLocaleList == null) {
|
||||||
|
String langTags = nGetLocaleList(mNativePtr);
|
||||||
|
if (TextUtils.isEmpty(langTags)) {
|
||||||
|
mLocaleList = LocaleList.getEmptyLocaleList();
|
||||||
|
} else {
|
||||||
|
mLocaleList = LocaleList.forLanguageTags(langTags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mLocaleList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -713,7 +751,20 @@ public final class Font {
|
|||||||
* @return an unique identifier for the font source data.
|
* @return an unique identifier for the font source data.
|
||||||
*/
|
*/
|
||||||
public int getSourceIdentifier() {
|
public int getSourceIdentifier() {
|
||||||
return mSourceIdentifier;
|
synchronized (mLock) {
|
||||||
|
if (mSourceIdentifier == -1) {
|
||||||
|
long bufferAddress = nGetBufferAddress(mNativePtr);
|
||||||
|
synchronized (SOURCE_ID_LOCK) {
|
||||||
|
long id = FONT_SOURCE_ID_MAP.get(bufferAddress, -1);
|
||||||
|
if (id == -1) {
|
||||||
|
id = FONT_SOURCE_ID_MAP.size();
|
||||||
|
FONT_SOURCE_ID_MAP.append(bufferAddress, id);
|
||||||
|
}
|
||||||
|
mSourceIdentifier = (int) id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mSourceIdentifier;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -736,13 +787,16 @@ public final class Font {
|
|||||||
private boolean isSameSource(@NonNull Font other) {
|
private boolean isSameSource(@NonNull Font other) {
|
||||||
Objects.requireNonNull(other);
|
Objects.requireNonNull(other);
|
||||||
|
|
||||||
|
ByteBuffer myBuffer = getBuffer();
|
||||||
|
ByteBuffer otherBuffer = other.getBuffer();
|
||||||
|
|
||||||
// Shortcut for the same instance.
|
// Shortcut for the same instance.
|
||||||
if (mBuffer == other.mBuffer) {
|
if (myBuffer == otherBuffer) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shortcut for different font buffer check by comparing size.
|
// Shortcut for different font buffer check by comparing size.
|
||||||
if (mBuffer.capacity() != other.mBuffer.capacity()) {
|
if (myBuffer.capacity() != otherBuffer.capacity()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -750,15 +804,15 @@ public final class Font {
|
|||||||
// underlying native font object holds buffer address, check if this buffer points exactly
|
// underlying native font object holds buffer address, check if this buffer points exactly
|
||||||
// the same address as a shortcut of equality. For being compatible with of API30 or before,
|
// the same address as a shortcut of equality. For being compatible with of API30 or before,
|
||||||
// check buffer position even if the buffer points the same address.
|
// check buffer position even if the buffer points the same address.
|
||||||
if (mSourceIdentifier == other.mSourceIdentifier
|
if (getSourceIdentifier() == other.getSourceIdentifier()
|
||||||
&& mBuffer.position() == other.mBuffer.position()) {
|
&& myBuffer.position() == otherBuffer.position()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unfortunately, need to compare bytes one-by-one since the buffer may be different font
|
// Unfortunately, need to compare bytes one-by-one since the buffer may be different font
|
||||||
// file but has the same file size, or two font has same content but they are allocated
|
// file but has the same file size, or two font has same content but they are allocated
|
||||||
// differently. For being compatible with API30 ore before, compare with ByteBuffer#equals.
|
// differently. For being compatible with API30 ore before, compare with ByteBuffer#equals.
|
||||||
return mBuffer.equals(other.mBuffer);
|
return myBuffer.equals(otherBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -769,10 +823,20 @@ public final class Font {
|
|||||||
if (!(o instanceof Font)) {
|
if (!(o instanceof Font)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Font f = (Font) o;
|
Font f = (Font) o;
|
||||||
boolean paramEqual = mFontStyle.equals(f.mFontStyle) && f.mTtcIndex == mTtcIndex
|
|
||||||
&& Arrays.equals(f.mAxes, mAxes) && Objects.equals(f.mLocaleList, mLocaleList)
|
// The underlying minikin::Font object is the source of the truth of font information. Thus,
|
||||||
&& Objects.equals(mFile, f.mFile);
|
// Pointer equality is the object equality.
|
||||||
|
if (nGetMinikinFontPtr(mNativePtr) == nGetMinikinFontPtr(f.mNativePtr)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean paramEqual = f.getStyle().equals(getStyle())
|
||||||
|
&& f.getTtcIndex() == getTtcIndex()
|
||||||
|
&& Arrays.equals(f.getAxes(), getAxes())
|
||||||
|
&& Objects.equals(f.getLocaleList(), getLocaleList())
|
||||||
|
&& Objects.equals(getFile(), f.getFile());
|
||||||
|
|
||||||
if (!paramEqual) {
|
if (!paramEqual) {
|
||||||
return false;
|
return false;
|
||||||
@@ -784,64 +848,42 @@ public final class Font {
|
|||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(
|
return Objects.hash(
|
||||||
mFontStyle,
|
getStyle(),
|
||||||
mTtcIndex,
|
getTtcIndex(),
|
||||||
Arrays.hashCode(mAxes),
|
Arrays.hashCode(getAxes()),
|
||||||
// Use Buffer size instead of ByteBuffer#hashCode since ByteBuffer#hashCode traverse
|
// Use Buffer size instead of ByteBuffer#hashCode since ByteBuffer#hashCode traverse
|
||||||
// data which is not performant e.g. for HashMap. The hash collision are less likely
|
// data which is not performant e.g. for HashMap. The hash collision are less likely
|
||||||
// happens because it is unlikely happens the different font files has exactly the
|
// happens because it is unlikely happens the different font files has exactly the
|
||||||
// same size.
|
// same size.
|
||||||
mLocaleList);
|
getLocaleList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Font {"
|
return "Font {"
|
||||||
+ "path=" + mFile
|
+ "path=" + getFile()
|
||||||
+ ", style=" + mFontStyle
|
+ ", style=" + getStyle()
|
||||||
+ ", ttcIndex=" + mTtcIndex
|
+ ", ttcIndex=" + getTtcIndex()
|
||||||
+ ", axes=" + FontVariationAxis.toFontVariationSettings(mAxes)
|
+ ", axes=" + FontVariationAxis.toFontVariationSettings(getAxes())
|
||||||
+ ", localeList=" + mLocaleList
|
+ ", localeList=" + getLocaleList()
|
||||||
+ ", buffer=" + mBuffer
|
+ ", buffer=" + getBuffer()
|
||||||
+ "}";
|
+ "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@CriticalNative
|
||||||
* Lookup Font object from native pointer or create new one if not found.
|
private static native long nGetMinikinFontPtr(long font);
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public static Font findOrCreateFontFromNativePtr(long ptr) {
|
|
||||||
// First, lookup from known mapps.
|
|
||||||
synchronized (MAP_LOCK) {
|
|
||||||
WeakReference<Font> fontRef = FONT_PTR_MAP.get(ptr);
|
|
||||||
if (fontRef != null) {
|
|
||||||
Font font = fontRef.get();
|
|
||||||
if (font != null) {
|
|
||||||
return font;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not found, create Font object from native object for Java API users.
|
@CriticalNative
|
||||||
ByteBuffer buffer = NativeFontBufferHelper.refByteBuffer(ptr);
|
private static native long nCloneFont(long font);
|
||||||
NativeFont.Font font = NativeFont.readNativeFont(ptr);
|
|
||||||
|
|
||||||
Font.Builder builder = new Font.Builder(buffer, font.getFile(), "")
|
@FastNative
|
||||||
.setWeight(font.getStyle().getWeight())
|
private static native ByteBuffer nNewByteBuffer(long font);
|
||||||
.setSlant(font.getStyle().getSlant())
|
|
||||||
.setTtcIndex(font.getIndex())
|
|
||||||
.setFontVariationSettings(font.getAxes());
|
|
||||||
|
|
||||||
Font newFont = null;
|
@CriticalNative
|
||||||
try {
|
private static native long nGetBufferAddress(long font);
|
||||||
newFont = builder.build();
|
|
||||||
FONT_PTR_MAP.append(ptr, new WeakReference<>(newFont));
|
@CriticalNative
|
||||||
} catch (IOException e) {
|
private static native long nGetReleaseNativeFont();
|
||||||
// This must not happen since the buffer was already created once.
|
|
||||||
Log.e("Font", "Failed to create font object from existing buffer.", e);
|
|
||||||
}
|
|
||||||
return newFont;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@FastNative
|
@FastNative
|
||||||
private static native float nGetGlyphBounds(long font, int glyphId, long paint, RectF rect);
|
private static native float nGetGlyphBounds(long font, int glyphId, long paint, RectF rect);
|
||||||
@@ -849,9 +891,21 @@ public final class Font {
|
|||||||
@FastNative
|
@FastNative
|
||||||
private static native float nGetFontMetrics(long font, long paint, Paint.FontMetrics metrics);
|
private static native float nGetFontMetrics(long font, long paint, Paint.FontMetrics metrics);
|
||||||
|
|
||||||
@CriticalNative
|
@FastNative
|
||||||
private static native long nGetNativeFontPtr(long ptr);
|
private static native String nGetFontPath(long fontPtr);
|
||||||
|
|
||||||
|
@FastNative
|
||||||
|
private static native String nGetLocaleList(long familyPtr);
|
||||||
|
|
||||||
@CriticalNative
|
@CriticalNative
|
||||||
private static native long nGetFontBufferAddress(long font);
|
private static native int nGetPackedStyle(long fontPtr);
|
||||||
|
|
||||||
|
@CriticalNative
|
||||||
|
private static native int nGetIndex(long fontPtr);
|
||||||
|
|
||||||
|
@CriticalNative
|
||||||
|
private static native int nGetAxisCount(long fontPtr);
|
||||||
|
|
||||||
|
@CriticalNative
|
||||||
|
private static native long nGetAxisInfo(long fontPtr, int i);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,12 +143,10 @@ public final class FontFamily {
|
|||||||
private static native long nGetReleaseNativeFamily();
|
private static native long nGetReleaseNativeFamily();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ArrayList<Font> mFonts;
|
|
||||||
private final long mNativePtr;
|
private final long mNativePtr;
|
||||||
|
|
||||||
// Use Builder instead.
|
// Use Builder instead.
|
||||||
private FontFamily(@NonNull ArrayList<Font> fonts, long ptr) {
|
private FontFamily(@NonNull ArrayList<Font> fonts, long ptr) {
|
||||||
mFonts = fonts;
|
|
||||||
mNativePtr = ptr;
|
mNativePtr = ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +174,10 @@ public final class FontFamily {
|
|||||||
* @return a registered font
|
* @return a registered font
|
||||||
*/
|
*/
|
||||||
public @NonNull Font getFont(@IntRange(from = 0) int index) {
|
public @NonNull Font getFont(@IntRange(from = 0) int index) {
|
||||||
return mFonts.get(index);
|
if (index < 0 || getSize() <= index) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
return new Font(nGetFont(mNativePtr, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -185,7 +186,7 @@ public final class FontFamily {
|
|||||||
* @return the number of fonts registered in this family.
|
* @return the number of fonts registered in this family.
|
||||||
*/
|
*/
|
||||||
public @IntRange(from = 1) int getSize() {
|
public @IntRange(from = 1) int getSize() {
|
||||||
return mFonts.size();
|
return nGetFontSize(mNativePtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@@ -193,6 +194,12 @@ public final class FontFamily {
|
|||||||
return mNativePtr;
|
return mNativePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@CriticalNative
|
||||||
|
private static native int nGetFontSize(long family);
|
||||||
|
|
||||||
|
@CriticalNative
|
||||||
|
private static native long nGetFont(long family, int i);
|
||||||
|
|
||||||
@FastNative
|
@FastNative
|
||||||
private static native String nGetLangTags(long family);
|
private static native String nGetLangTags(long family);
|
||||||
|
|
||||||
|
|||||||
@@ -1,205 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2020 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.fonts;
|
|
||||||
|
|
||||||
import android.graphics.Typeface;
|
|
||||||
|
|
||||||
import dalvik.annotation.optimization.CriticalNative;
|
|
||||||
import dalvik.annotation.optimization.FastNative;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read native font objects.
|
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public class NativeFont {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents native font object.
|
|
||||||
*/
|
|
||||||
public static final class Font {
|
|
||||||
private final File mFile;
|
|
||||||
private final int mIndex;
|
|
||||||
private final FontVariationAxis[] mAxes;
|
|
||||||
private final FontStyle mStyle;
|
|
||||||
|
|
||||||
public Font(File file, int index, FontVariationAxis[] axes, FontStyle style) {
|
|
||||||
mFile = file;
|
|
||||||
mIndex = index;
|
|
||||||
mAxes = axes;
|
|
||||||
mStyle = style;
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getFile() {
|
|
||||||
return mFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FontVariationAxis[] getAxes() {
|
|
||||||
return mAxes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FontStyle getStyle() {
|
|
||||||
return mStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIndex() {
|
|
||||||
return mIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
Font font = (Font) o;
|
|
||||||
return mIndex == font.mIndex && mFile.equals(font.mFile)
|
|
||||||
&& Arrays.equals(mAxes, font.mAxes) && mStyle.equals(font.mStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = Objects.hash(mFile, mIndex, mStyle);
|
|
||||||
result = 31 * result + Arrays.hashCode(mAxes);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents native font family object.
|
|
||||||
*/
|
|
||||||
public static final class Family {
|
|
||||||
private final List<Font> mFonts;
|
|
||||||
private final String mLocale;
|
|
||||||
|
|
||||||
public Family(List<Font> fonts, String locale) {
|
|
||||||
mFonts = fonts;
|
|
||||||
mLocale = locale;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Font> getFonts() {
|
|
||||||
return mFonts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLocale() {
|
|
||||||
return mLocale;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
Family family = (Family) o;
|
|
||||||
return mFonts.equals(family.mFonts) && mLocale.equals(family.mLocale);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(mFonts, mLocale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get underlying font families from Typeface
|
|
||||||
*
|
|
||||||
* @param typeface a typeface
|
|
||||||
* @return list of family
|
|
||||||
*/
|
|
||||||
public static List<Family> readTypeface(Typeface typeface) {
|
|
||||||
int familyCount = nGetFamilyCount(typeface.native_instance);
|
|
||||||
List<Family> result = new ArrayList<>(familyCount);
|
|
||||||
for (int i = 0; i < familyCount; ++i) {
|
|
||||||
result.add(readNativeFamily(nGetFamily(typeface.native_instance, i)));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read family object from native pointer
|
|
||||||
*
|
|
||||||
* @param familyPtr a font family pointer
|
|
||||||
* @return a family
|
|
||||||
*/
|
|
||||||
public static Family readNativeFamily(long familyPtr) {
|
|
||||||
int fontCount = nGetFontCount(familyPtr);
|
|
||||||
List<Font> result = new ArrayList<>(fontCount);
|
|
||||||
for (int i = 0; i < fontCount; ++i) {
|
|
||||||
result.add(readNativeFont(nGetFont(familyPtr, i)));
|
|
||||||
}
|
|
||||||
String localeList = nGetLocaleList(familyPtr);
|
|
||||||
return new Family(result, localeList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read font object from native pointer.
|
|
||||||
*
|
|
||||||
* @param ptr a font pointer
|
|
||||||
* @return a font
|
|
||||||
*/
|
|
||||||
public static Font readNativeFont(long ptr) {
|
|
||||||
long packed = nGetFontInfo(ptr);
|
|
||||||
int weight = (int) (packed & 0x0000_0000_0000_FFFFL);
|
|
||||||
boolean italic = (packed & 0x0000_0000_0001_0000L) != 0;
|
|
||||||
int ttcIndex = (int) ((packed & 0x0000_FFFF_0000_0000L) >> 32);
|
|
||||||
int axisCount = (int) ((packed & 0xFFFF_0000_0000_0000L) >> 48);
|
|
||||||
FontVariationAxis[] axes = new FontVariationAxis[axisCount];
|
|
||||||
char[] charBuffer = new char[4];
|
|
||||||
for (int i = 0; i < axisCount; ++i) {
|
|
||||||
long packedAxis = nGetAxisInfo(ptr, i);
|
|
||||||
float value = Float.intBitsToFloat((int) (packedAxis & 0x0000_0000_FFFF_FFFFL));
|
|
||||||
charBuffer[0] = (char) ((packedAxis & 0xFF00_0000_0000_0000L) >> 56);
|
|
||||||
charBuffer[1] = (char) ((packedAxis & 0x00FF_0000_0000_0000L) >> 48);
|
|
||||||
charBuffer[2] = (char) ((packedAxis & 0x0000_FF00_0000_0000L) >> 40);
|
|
||||||
charBuffer[3] = (char) ((packedAxis & 0x0000_00FF_0000_0000L) >> 32);
|
|
||||||
axes[i] = new FontVariationAxis(new String(charBuffer), value);
|
|
||||||
}
|
|
||||||
String path = nGetFontPath(ptr);
|
|
||||||
File file = (path == null) ? null : new File(path);
|
|
||||||
FontStyle style = new FontStyle(weight,
|
|
||||||
italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT);
|
|
||||||
|
|
||||||
return new Font(file, ttcIndex, axes, style);
|
|
||||||
}
|
|
||||||
|
|
||||||
@CriticalNative
|
|
||||||
private static native int nGetFamilyCount(long ptr);
|
|
||||||
|
|
||||||
@CriticalNative
|
|
||||||
private static native long nGetFamily(long ptr, int index);
|
|
||||||
|
|
||||||
@FastNative
|
|
||||||
private static native String nGetLocaleList(long familyPtr);
|
|
||||||
|
|
||||||
@CriticalNative
|
|
||||||
private static native long nGetFont(long familyPtr, int fontIndex);
|
|
||||||
|
|
||||||
@CriticalNative
|
|
||||||
private static native int nGetFontCount(long familyPtr);
|
|
||||||
|
|
||||||
@CriticalNative
|
|
||||||
private static native long nGetFontInfo(long fontPtr);
|
|
||||||
|
|
||||||
@CriticalNative
|
|
||||||
private static native long nGetAxisInfo(long fontPtr, int i);
|
|
||||||
|
|
||||||
@FastNative
|
|
||||||
private static native String nGetFontPath(long fontPtr);
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2020 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.fonts;
|
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
|
||||||
|
|
||||||
import dalvik.annotation.optimization.CriticalNative;
|
|
||||||
import dalvik.annotation.optimization.FastNative;
|
|
||||||
|
|
||||||
import libcore.util.NativeAllocationRegistry;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a helper class for showing native allocated buffer in Java API.
|
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public class NativeFontBufferHelper {
|
|
||||||
private NativeFontBufferHelper() {}
|
|
||||||
|
|
||||||
private static final NativeAllocationRegistry REGISTRY =
|
|
||||||
NativeAllocationRegistry.createMalloced(
|
|
||||||
ByteBuffer.class.getClassLoader(), nGetReleaseFunc());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap native buffer with ByteBuffer with adding reference to it.
|
|
||||||
*/
|
|
||||||
public static @NonNull ByteBuffer refByteBuffer(long fontPtr) {
|
|
||||||
long refPtr = nRefFontBuffer(fontPtr);
|
|
||||||
ByteBuffer buffer = nWrapByteBuffer(refPtr);
|
|
||||||
|
|
||||||
// Releasing native object so that decreasing shared pointer ref count when the byte buffer
|
|
||||||
// is GCed.
|
|
||||||
REGISTRY.registerNativeAllocation(buffer, refPtr);
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@CriticalNative
|
|
||||||
private static native long nRefFontBuffer(long fontPtr);
|
|
||||||
|
|
||||||
@FastNative
|
|
||||||
private static native ByteBuffer nWrapByteBuffer(long refPtr);
|
|
||||||
|
|
||||||
@CriticalNative
|
|
||||||
private static native long nGetReleaseFunc();
|
|
||||||
}
|
|
||||||
@@ -184,7 +184,7 @@ public final class PositionedGlyphs {
|
|||||||
long ptr = nGetFont(layoutPtr, i);
|
long ptr = nGetFont(layoutPtr, i);
|
||||||
if (prevPtr != ptr) {
|
if (prevPtr != ptr) {
|
||||||
prevPtr = ptr;
|
prevPtr = ptr;
|
||||||
prevFont = Font.findOrCreateFontFromNativePtr(ptr);
|
prevFont = new Font(ptr);
|
||||||
}
|
}
|
||||||
mFonts.add(prevFont);
|
mFonts.add(prevFont);
|
||||||
}
|
}
|
||||||
@@ -224,9 +224,7 @@ public final class PositionedGlyphs {
|
|||||||
if (getGlyphId(i) != that.getGlyphId(i)) return false;
|
if (getGlyphId(i) != that.getGlyphId(i)) return false;
|
||||||
if (getGlyphX(i) != that.getGlyphX(i)) return false;
|
if (getGlyphX(i) != that.getGlyphX(i)) return false;
|
||||||
if (getGlyphY(i) != that.getGlyphY(i)) return false;
|
if (getGlyphY(i) != that.getGlyphY(i)) return false;
|
||||||
// Intentionally using reference equality since font equality is heavy due to buffer
|
if (!getFont(i).equals(that.getFont(i))) return false;
|
||||||
// compare.
|
|
||||||
if (getFont(i) != that.getFont(i)) return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -335,7 +335,6 @@ cc_defaults {
|
|||||||
"jni/YuvToJpegEncoder.cpp",
|
"jni/YuvToJpegEncoder.cpp",
|
||||||
"jni/fonts/Font.cpp",
|
"jni/fonts/Font.cpp",
|
||||||
"jni/fonts/FontFamily.cpp",
|
"jni/fonts/FontFamily.cpp",
|
||||||
"jni/fonts/NativeFont.cpp",
|
|
||||||
"jni/text/LineBreaker.cpp",
|
"jni/text/LineBreaker.cpp",
|
||||||
"jni/text/MeasuredText.cpp",
|
"jni/text/MeasuredText.cpp",
|
||||||
"jni/text/TextShaper.cpp",
|
"jni/text/TextShaper.cpp",
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ extern int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env
|
|||||||
extern int register_android_graphics_drawable_VectorDrawable(JNIEnv* env);
|
extern int register_android_graphics_drawable_VectorDrawable(JNIEnv* env);
|
||||||
extern int register_android_graphics_fonts_Font(JNIEnv* env);
|
extern int register_android_graphics_fonts_Font(JNIEnv* env);
|
||||||
extern int register_android_graphics_fonts_FontFamily(JNIEnv* env);
|
extern int register_android_graphics_fonts_FontFamily(JNIEnv* env);
|
||||||
extern int register_android_graphics_fonts_NativeFont(JNIEnv* env);
|
|
||||||
extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env);
|
extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env);
|
||||||
extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env);
|
extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env);
|
||||||
extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env);
|
extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env);
|
||||||
@@ -136,7 +135,6 @@ static const RegJNIRec gRegJNI[] = {
|
|||||||
REG_JNI(register_android_graphics_drawable_VectorDrawable),
|
REG_JNI(register_android_graphics_drawable_VectorDrawable),
|
||||||
REG_JNI(register_android_graphics_fonts_Font),
|
REG_JNI(register_android_graphics_fonts_Font),
|
||||||
REG_JNI(register_android_graphics_fonts_FontFamily),
|
REG_JNI(register_android_graphics_fonts_FontFamily),
|
||||||
REG_JNI(register_android_graphics_fonts_NativeFont),
|
|
||||||
REG_JNI(register_android_graphics_pdf_PdfDocument),
|
REG_JNI(register_android_graphics_pdf_PdfDocument),
|
||||||
REG_JNI(register_android_graphics_pdf_PdfEditor),
|
REG_JNI(register_android_graphics_pdf_PdfEditor),
|
||||||
REG_JNI(register_android_graphics_pdf_PdfRenderer),
|
REG_JNI(register_android_graphics_pdf_PdfRenderer),
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#include <hwui/Typeface.h>
|
#include <hwui/Typeface.h>
|
||||||
#include <minikin/FontFamily.h>
|
#include <minikin/FontFamily.h>
|
||||||
#include <minikin/FontFileParser.h>
|
#include <minikin/FontFileParser.h>
|
||||||
|
#include <minikin/LocaleList.h>
|
||||||
#include <ui/FatVector.h>
|
#include <ui/FatVector.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -149,12 +150,8 @@ static jlong Font_Builder_clone(JNIEnv* env, jobject clazz, jlong fontPtr, jlong
|
|||||||
return reinterpret_cast<jlong>(new FontWrapper(std::move(newFont)));
|
return reinterpret_cast<jlong>(new FontWrapper(std::move(newFont)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Critical Native
|
|
||||||
static jlong Font_Builder_getReleaseNativeFont(CRITICAL_JNI_PARAMS) {
|
|
||||||
return reinterpret_cast<jlong>(releaseFont);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Font JNI functions
|
||||||
|
|
||||||
// Fast Native
|
// Fast Native
|
||||||
static jfloat Font_getGlyphBounds(JNIEnv* env, jobject, jlong fontHandle, jint glyphId,
|
static jfloat Font_getGlyphBounds(JNIEnv* env, jobject, jlong fontHandle, jint glyphId,
|
||||||
@@ -195,51 +192,92 @@ static jfloat Font_getFontMetrics(JNIEnv* env, jobject, jlong fontHandle, jlong
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Critical Native
|
// Critical Native
|
||||||
static jlong Font_getNativeFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontHandle) {
|
static jlong Font_getMinikinFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
|
||||||
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
|
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
|
||||||
return reinterpret_cast<jlong>(font->font.get());
|
return reinterpret_cast<jlong>(font->font->typeface().get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Critical Native
|
// Critical Native
|
||||||
static jlong Font_GetBufferAddress(CRITICAL_JNI_PARAMS_COMMA jlong fontHandle) {
|
static jlong Font_cloneFont(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
|
||||||
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
|
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
|
||||||
const void* bufferPtr = font->font->typeface()->GetFontData();
|
std::shared_ptr<minikin::Font> ref = font->font;
|
||||||
return reinterpret_cast<jlong>(bufferPtr);
|
return reinterpret_cast<jlong>(new FontWrapper(std::move(ref)));
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct FontBufferWrapper {
|
|
||||||
FontBufferWrapper(const std::shared_ptr<minikin::MinikinFont>& font) : minikinFont(font) {}
|
|
||||||
// MinikinFont holds a shared pointer of SkTypeface which has reference to font data.
|
|
||||||
std::shared_ptr<minikin::MinikinFont> minikinFont;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void unrefBuffer(jlong nativePtr) {
|
|
||||||
FontBufferWrapper* wrapper = reinterpret_cast<FontBufferWrapper*>(nativePtr);
|
|
||||||
delete wrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Critical Native
|
|
||||||
static jlong FontBufferHelper_refFontBuffer(CRITICAL_JNI_PARAMS_COMMA jlong fontHandle) {
|
|
||||||
const minikin::Font* font = reinterpret_cast<minikin::Font*>(fontHandle);
|
|
||||||
return reinterpret_cast<jlong>(new FontBufferWrapper(font->typeface()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fast Native
|
// Fast Native
|
||||||
static jobject FontBufferHelper_wrapByteBuffer(JNIEnv* env, jobject, jlong nativePtr) {
|
static jobject Font_newByteBuffer(JNIEnv* env, jobject, jlong fontPtr) {
|
||||||
FontBufferWrapper* wrapper = reinterpret_cast<FontBufferWrapper*>(nativePtr);
|
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
|
||||||
return env->NewDirectByteBuffer(
|
const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
|
||||||
const_cast<void*>(wrapper->minikinFont->GetFontData()),
|
return env->NewDirectByteBuffer(const_cast<void*>(minikinFont->GetFontData()),
|
||||||
wrapper->minikinFont->GetFontSize());
|
minikinFont->GetFontSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Critical Native
|
// Critical Native
|
||||||
static jlong FontBufferHelper_getReleaseFunc(CRITICAL_JNI_PARAMS) {
|
static jlong Font_getBufferAddress(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
|
||||||
return reinterpret_cast<jlong>(unrefBuffer);
|
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
|
||||||
|
return reinterpret_cast<jlong>(font->font->typeface()->GetFontData());
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
// Critical Native
|
||||||
|
static jlong Font_getReleaseNativeFontFunc() {
|
||||||
|
return reinterpret_cast<jlong>(releaseFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fast Native
|
||||||
|
static jstring Font_getFontPath(JNIEnv* env, jobject, jlong fontPtr) {
|
||||||
|
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
|
||||||
|
const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
|
||||||
|
const std::string& path = minikinFont->GetFontPath();
|
||||||
|
if (path.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return env->NewStringUTF(path.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fast Native
|
||||||
|
static jstring Font_getLocaleList(JNIEnv* env, jobject, jlong fontPtr) {
|
||||||
|
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
|
||||||
|
uint32_t localeListId = font->font->getLocaleListId();
|
||||||
|
if (localeListId == 0) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
std::string langTags = minikin::getLocaleString(localeListId);
|
||||||
|
if (langTags.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return env->NewStringUTF(langTags.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Critical Native
|
||||||
|
static jint Font_getPackedStyle(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
|
||||||
|
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
|
||||||
|
uint32_t weight = font->font->style().weight();
|
||||||
|
uint32_t isItalic = font->font->style().slant() == minikin::FontStyle::Slant::ITALIC ? 1 : 0;
|
||||||
|
return (isItalic << 16) | weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Critical Native
|
||||||
|
static jint Font_getIndex(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
|
||||||
|
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
|
||||||
|
const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
|
||||||
|
return minikinFont->GetFontIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Critical Native
|
||||||
|
static jint Font_getAxisCount(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
|
||||||
|
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
|
||||||
|
const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
|
||||||
|
return minikinFont->GetAxes().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Critical Native
|
||||||
|
static jlong Font_getAxisInfo(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr, jint index) {
|
||||||
|
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
|
||||||
|
const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
|
||||||
|
minikin::FontVariation var = minikinFont->GetAxes().at(index);
|
||||||
|
uint32_t floatBinary = *reinterpret_cast<const uint32_t*>(&var.value);
|
||||||
|
return (static_cast<uint64_t>(var.axisTag) << 32) | static_cast<uint64_t>(floatBinary);
|
||||||
|
}
|
||||||
|
|
||||||
// Fast Native
|
// Fast Native
|
||||||
static jlong FontFileUtil_getFontRevision(JNIEnv* env, jobject, jobject buffer, jint index) {
|
static jlong FontFileUtil_getFontRevision(JNIEnv* env, jobject, jobject buffer, jint index) {
|
||||||
@@ -314,20 +352,23 @@ static const JNINativeMethod gFontBuilderMethods[] = {
|
|||||||
{"nBuild", "(JLjava/nio/ByteBuffer;Ljava/lang/String;Ljava/lang/String;IZI)J",
|
{"nBuild", "(JLjava/nio/ByteBuffer;Ljava/lang/String;Ljava/lang/String;IZI)J",
|
||||||
(void*)Font_Builder_build},
|
(void*)Font_Builder_build},
|
||||||
{"nClone", "(JJIZI)J", (void*)Font_Builder_clone},
|
{"nClone", "(JJIZI)J", (void*)Font_Builder_clone},
|
||||||
{"nGetReleaseNativeFont", "()J", (void*)Font_Builder_getReleaseNativeFont},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const JNINativeMethod gFontMethods[] = {
|
static const JNINativeMethod gFontMethods[] = {
|
||||||
{ "nGetGlyphBounds", "(JIJLandroid/graphics/RectF;)F", (void*) Font_getGlyphBounds },
|
{"nGetMinikinFontPtr", "(J)J", (void*)Font_getMinikinFontPtr},
|
||||||
{ "nGetFontMetrics", "(JJLandroid/graphics/Paint$FontMetrics;)F", (void*) Font_getFontMetrics },
|
{"nCloneFont", "(J)J", (void*)Font_cloneFont},
|
||||||
{ "nGetNativeFontPtr", "(J)J", (void*) Font_getNativeFontPtr },
|
{"nNewByteBuffer", "(J)Ljava/nio/ByteBuffer;", (void*)Font_newByteBuffer},
|
||||||
{ "nGetFontBufferAddress", "(J)J", (void*) Font_GetBufferAddress },
|
{"nGetBufferAddress", "(J)J", (void*)Font_getBufferAddress},
|
||||||
};
|
{"nGetReleaseNativeFont", "()J", (void*)Font_getReleaseNativeFontFunc},
|
||||||
|
{"nGetGlyphBounds", "(JIJLandroid/graphics/RectF;)F", (void*)Font_getGlyphBounds},
|
||||||
static const JNINativeMethod gFontBufferHelperMethods[] = {
|
{"nGetFontMetrics", "(JJLandroid/graphics/Paint$FontMetrics;)F",
|
||||||
{ "nRefFontBuffer", "(J)J", (void*) FontBufferHelper_refFontBuffer },
|
(void*)Font_getFontMetrics},
|
||||||
{ "nWrapByteBuffer", "(J)Ljava/nio/ByteBuffer;", (void*) FontBufferHelper_wrapByteBuffer },
|
{"nGetFontPath", "(J)Ljava/lang/String;", (void*)Font_getFontPath},
|
||||||
{ "nGetReleaseFunc", "()J", (void*) FontBufferHelper_getReleaseFunc },
|
{"nGetLocaleList", "(J)Ljava/lang/String;", (void*)Font_getLocaleList},
|
||||||
|
{"nGetPackedStyle", "(J)I", (void*)Font_getPackedStyle},
|
||||||
|
{"nGetIndex", "(J)I", (void*)Font_getIndex},
|
||||||
|
{"nGetAxisCount", "(J)I", (void*)Font_getAxisCount},
|
||||||
|
{"nGetAxisInfo", "(JI)J", (void*)Font_getAxisInfo},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const JNINativeMethod gFontFileUtilMethods[] = {
|
static const JNINativeMethod gFontFileUtilMethods[] = {
|
||||||
@@ -343,8 +384,6 @@ int register_android_graphics_fonts_Font(JNIEnv* env) {
|
|||||||
NELEM(gFontBuilderMethods)) +
|
NELEM(gFontBuilderMethods)) +
|
||||||
RegisterMethodsOrDie(env, "android/graphics/fonts/Font", gFontMethods,
|
RegisterMethodsOrDie(env, "android/graphics/fonts/Font", gFontMethods,
|
||||||
NELEM(gFontMethods)) +
|
NELEM(gFontMethods)) +
|
||||||
RegisterMethodsOrDie(env, "android/graphics/fonts/NativeFontBufferHelper",
|
|
||||||
gFontBufferHelperMethods, NELEM(gFontBufferHelperMethods)) +
|
|
||||||
RegisterMethodsOrDie(env, "android/graphics/fonts/FontFileUtil", gFontFileUtilMethods,
|
RegisterMethodsOrDie(env, "android/graphics/fonts/FontFileUtil", gFontFileUtilMethods,
|
||||||
NELEM(gFontFileUtilMethods));
|
NELEM(gFontFileUtilMethods));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,17 +100,31 @@ static jint FontFamily_getVariant(CRITICAL_JNI_PARAMS_COMMA jlong familyPtr) {
|
|||||||
return static_cast<jint>(family->family->variant());
|
return static_cast<jint>(family->family->variant());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CriticalNative
|
||||||
|
static jint FontFamily_getFontSize(jlong familyPtr) {
|
||||||
|
FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(familyPtr);
|
||||||
|
return family->family->getNumFonts();
|
||||||
|
}
|
||||||
|
|
||||||
|
// CriticalNative
|
||||||
|
static jlong FontFamily_getFont(jlong familyPtr, jint index) {
|
||||||
|
FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(familyPtr);
|
||||||
|
std::shared_ptr<minikin::Font> font = family->family->getFontRef(index);
|
||||||
|
return reinterpret_cast<jlong>(new FontWrapper(std::move(font)));
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static const JNINativeMethod gFontFamilyBuilderMethods[] = {
|
static const JNINativeMethod gFontFamilyBuilderMethods[] = {
|
||||||
{ "nInitBuilder", "()J", (void*) FontFamily_Builder_initBuilder },
|
{ "nInitBuilder", "()J", (void*) FontFamily_Builder_initBuilder },
|
||||||
{ "nAddFont", "(JJ)V", (void*) FontFamily_Builder_addFont },
|
{ "nAddFont", "(JJ)V", (void*) FontFamily_Builder_addFont },
|
||||||
{ "nBuild", "(JLjava/lang/String;IZ)J", (void*) FontFamily_Builder_build },
|
{ "nBuild", "(JLjava/lang/String;IZ)J", (void*) FontFamily_Builder_build },
|
||||||
|
|
||||||
{ "nGetReleaseNativeFamily", "()J", (void*) FontFamily_Builder_GetReleaseFunc },
|
{ "nGetReleaseNativeFamily", "()J", (void*) FontFamily_Builder_GetReleaseFunc },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const JNINativeMethod gFontFamilyMethods[] = {
|
static const JNINativeMethod gFontFamilyMethods[] = {
|
||||||
|
{"nGetFontSize", "(J)I", (void*)FontFamily_getFontSize},
|
||||||
|
{"nGetFont", "(JI)J", (void*)FontFamily_getFont},
|
||||||
{"nGetLangTags", "(J)Ljava/lang/String;", (void*)FontFamily_getLangTags},
|
{"nGetLangTags", "(J)Ljava/lang/String;", (void*)FontFamily_getLangTags},
|
||||||
{"nGetVariant", "(J)I", (void*)FontFamily_getVariant},
|
{"nGetVariant", "(J)I", (void*)FontFamily_getVariant},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,125 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2018 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#undef LOG_TAG
|
|
||||||
#define LOG_TAG "Minikin"
|
|
||||||
|
|
||||||
#include "Font.h"
|
|
||||||
#include "SkData.h"
|
|
||||||
#include "SkFont.h"
|
|
||||||
#include "SkFontMetrics.h"
|
|
||||||
#include "SkFontMgr.h"
|
|
||||||
#include "SkRefCnt.h"
|
|
||||||
#include "SkTypeface.h"
|
|
||||||
#include "GraphicsJNI.h"
|
|
||||||
#include <nativehelper/ScopedUtfChars.h>
|
|
||||||
#include "Utils.h"
|
|
||||||
#include "FontUtils.h"
|
|
||||||
|
|
||||||
#include <hwui/MinikinSkia.h>
|
|
||||||
#include <hwui/Paint.h>
|
|
||||||
#include <hwui/Typeface.h>
|
|
||||||
#include <minikin/FontFamily.h>
|
|
||||||
#include <minikin/LocaleList.h>
|
|
||||||
#include <ui/FatVector.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace android {
|
|
||||||
|
|
||||||
// Critical Native
|
|
||||||
static jint NativeFont_getFamilyCount(CRITICAL_JNI_PARAMS_COMMA jlong typefaceHandle) {
|
|
||||||
Typeface* tf = reinterpret_cast<Typeface*>(typefaceHandle);
|
|
||||||
return tf->fFontCollection->getFamilies().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Critical Native
|
|
||||||
static jlong NativeFont_getFamily(CRITICAL_JNI_PARAMS_COMMA jlong typefaceHandle, jint index) {
|
|
||||||
Typeface* tf = reinterpret_cast<Typeface*>(typefaceHandle);
|
|
||||||
return reinterpret_cast<jlong>(tf->fFontCollection->getFamilies()[index].get());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fast Native
|
|
||||||
static jstring NativeFont_getLocaleList(JNIEnv* env, jobject, jlong familyHandle) {
|
|
||||||
minikin::FontFamily* family = reinterpret_cast<minikin::FontFamily*>(familyHandle);
|
|
||||||
uint32_t localeListId = family->localeListId();
|
|
||||||
return env->NewStringUTF(minikin::getLocaleString(localeListId).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Critical Native
|
|
||||||
static jint NativeFont_getFontCount(CRITICAL_JNI_PARAMS_COMMA jlong familyHandle) {
|
|
||||||
minikin::FontFamily* family = reinterpret_cast<minikin::FontFamily*>(familyHandle);
|
|
||||||
return family->getNumFonts();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Critical Native
|
|
||||||
static jlong NativeFont_getFont(CRITICAL_JNI_PARAMS_COMMA jlong familyHandle, jint index) {
|
|
||||||
minikin::FontFamily* family = reinterpret_cast<minikin::FontFamily*>(familyHandle);
|
|
||||||
return reinterpret_cast<jlong>(family->getFont(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Critical Native
|
|
||||||
static jlong NativeFont_getFontInfo(CRITICAL_JNI_PARAMS_COMMA jlong fontHandle) {
|
|
||||||
const minikin::Font* font = reinterpret_cast<minikin::Font*>(fontHandle);
|
|
||||||
MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->typeface().get());
|
|
||||||
|
|
||||||
uint64_t result = font->style().weight();
|
|
||||||
result |= font->style().slant() == minikin::FontStyle::Slant::ITALIC ? 0x10000 : 0x00000;
|
|
||||||
result |= ((static_cast<uint64_t>(minikinSkia->GetFontIndex())) << 32);
|
|
||||||
result |= ((static_cast<uint64_t>(minikinSkia->GetAxes().size())) << 48);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Critical Native
|
|
||||||
static jlong NativeFont_getAxisInfo(CRITICAL_JNI_PARAMS_COMMA jlong fontHandle, jint index) {
|
|
||||||
const minikin::Font* font = reinterpret_cast<minikin::Font*>(fontHandle);
|
|
||||||
MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->typeface().get());
|
|
||||||
const minikin::FontVariation& var = minikinSkia->GetAxes().at(index);
|
|
||||||
uint32_t floatBinary = *reinterpret_cast<const uint32_t*>(&var.value);
|
|
||||||
return (static_cast<uint64_t>(var.axisTag) << 32) | static_cast<uint64_t>(floatBinary);
|
|
||||||
}
|
|
||||||
|
|
||||||
// FastNative
|
|
||||||
static jstring NativeFont_getFontPath(JNIEnv* env, jobject, jlong fontHandle) {
|
|
||||||
const minikin::Font* font = reinterpret_cast<minikin::Font*>(fontHandle);
|
|
||||||
MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->typeface().get());
|
|
||||||
const std::string& filePath = minikinSkia->getFilePath();
|
|
||||||
if (filePath.empty()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return env->NewStringUTF(filePath.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static const JNINativeMethod gNativeFontMethods[] = {
|
|
||||||
{ "nGetFamilyCount", "(J)I", (void*) NativeFont_getFamilyCount },
|
|
||||||
{ "nGetFamily", "(JI)J", (void*) NativeFont_getFamily },
|
|
||||||
{ "nGetLocaleList", "(J)Ljava/lang/String;", (void*) NativeFont_getLocaleList },
|
|
||||||
{ "nGetFontCount", "(J)I", (void*) NativeFont_getFontCount },
|
|
||||||
{ "nGetFont", "(JI)J", (void*) NativeFont_getFont },
|
|
||||||
{ "nGetFontInfo", "(J)J", (void*) NativeFont_getFontInfo },
|
|
||||||
{ "nGetAxisInfo", "(JI)J", (void*) NativeFont_getAxisInfo },
|
|
||||||
{ "nGetFontPath", "(J)Ljava/lang/String;", (void*) NativeFont_getFontPath },
|
|
||||||
};
|
|
||||||
|
|
||||||
int register_android_graphics_fonts_NativeFont(JNIEnv* env) {
|
|
||||||
return RegisterMethodsOrDie(env, "android/graphics/fonts/NativeFont", gNativeFontMethods,
|
|
||||||
NELEM(gNativeFontMethods));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace android
|
|
||||||
@@ -23,13 +23,14 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "SkPaint.h"
|
|
||||||
#include "SkTypeface.h"
|
|
||||||
#include <hwui/MinikinSkia.h>
|
#include <hwui/MinikinSkia.h>
|
||||||
#include <hwui/MinikinUtils.h>
|
#include <hwui/MinikinUtils.h>
|
||||||
#include <hwui/Paint.h>
|
#include <hwui/Paint.h>
|
||||||
#include <minikin/MinikinPaint.h>
|
|
||||||
#include <minikin/MinikinFont.h>
|
#include <minikin/MinikinFont.h>
|
||||||
|
#include <minikin/MinikinPaint.h>
|
||||||
|
#include "FontUtils.h"
|
||||||
|
#include "SkPaint.h"
|
||||||
|
#include "SkTypeface.h"
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
@@ -149,7 +150,8 @@ static jfloat TextShaper_Result_getY(CRITICAL_JNI_PARAMS_COMMA jlong ptr, jint i
|
|||||||
// CriticalNative
|
// CriticalNative
|
||||||
static jlong TextShaper_Result_getFont(CRITICAL_JNI_PARAMS_COMMA jlong ptr, jint i) {
|
static jlong TextShaper_Result_getFont(CRITICAL_JNI_PARAMS_COMMA jlong ptr, jint i) {
|
||||||
const LayoutWrapper* layout = reinterpret_cast<LayoutWrapper*>(ptr);
|
const LayoutWrapper* layout = reinterpret_cast<LayoutWrapper*>(ptr);
|
||||||
return reinterpret_cast<jlong>(layout->layout.getFont(i));
|
std::shared_ptr<minikin::Font> fontRef = layout->layout.getFontRef(i);
|
||||||
|
return reinterpret_cast<jlong>(new FontWrapper(std::move(fontRef)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// CriticalNative
|
// CriticalNative
|
||||||
|
|||||||
Reference in New Issue
Block a user