Make Font class being able to create from native instance
This CL refactors followings:
- Use infomation stored in native instance as the source-of-truth.
- Being able to create Font instance from native instance.
- Use ByteBuffer as a wrapper of the native byte buffer.
Bug: 179113771
Test: atest CtsTextTestCases CtsGraphicsTestCases
Test: atest android.graphics.fonts.NativeSystemFontTest
Test: atest android.graphics.fonts.SystemFontsTest
Test: atest FrameworksCoreTests:android.text
Test: atest FrameworksCoreTests:android.graphics
Change-Id: Icc1df1c76ba78d4f8800984444439fd03970e179
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index 9214ff1..b153c99 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -26,8 +26,7 @@
import android.graphics.RectF;
import android.os.LocaleList;
import android.os.ParcelFileDescriptor;
-import android.util.Log;
-import android.util.LongSparseArray;
+import android.text.TextUtils;
import android.util.LongSparseLongArray;
import android.util.TypedValue;
@@ -44,7 +43,6 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
@@ -61,14 +59,9 @@
private static final int STYLE_ITALIC = 1;
private static final int STYLE_NORMAL = 0;
- private static final Object MAP_LOCK = new Object();
- // We need to have mapping from native ptr to Font object for later accessing from TextShape
- // result since Typeface doesn't have reference to Font object and it is not always created from
- // 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 NativeAllocationRegistry BUFFER_REGISTRY =
+ NativeAllocationRegistry.createMalloced(
+ ByteBuffer.class.getClassLoader(), nGetReleaseNativeFont());
private static final Object SOURCE_ID_LOCK = new Object();
@GuardedBy("SOURCE_ID_LOCK")
@@ -79,9 +72,7 @@
* A builder class for creating new Font.
*/
public static final class Builder {
- private static final NativeAllocationRegistry sFontRegistry =
- NativeAllocationRegistry.createMalloced(Font.class.getClassLoader(),
- nGetReleaseNativeFont());
+
private @Nullable ByteBuffer mBuffer;
private @Nullable File mFile;
@@ -484,26 +475,15 @@
final String filePath = mFile == null ? "" : mFile.getAbsolutePath();
long ptr;
- int fontIdentifier;
+ final Font font;
if (mFont == null) {
ptr = nBuild(builderPtr, readonlyBuffer, filePath, mLocaleList, mWeight, italic,
mTtcIndex);
- long fontBufferPtr = nGetFontBufferAddress(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;
- }
+ font = new Font(ptr);
} else {
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;
}
@@ -525,33 +505,32 @@
}
private final long mNativePtr; // address of the shared ptr of minikin::Font
- private final @NonNull ByteBuffer mBuffer;
- private final @Nullable File mFile;
- private final FontStyle mFontStyle;
- private final @IntRange(from = 0) int mTtcIndex;
- private final @Nullable FontVariationAxis[] mAxes;
- private final @NonNull String mLocaleList;
- private final int mSourceIdentifier; // An identifier of font source data.
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ private @NonNull ByteBuffer mBuffer = null;
+ @GuardedBy("mLock")
+ private boolean mIsFileInitialized = false;
+ @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
+ *
+ * Caller must increment underlying minikin::Font ref count.
+ *
+ * @hide
*/
- private Font(long nativePtr, @NonNull ByteBuffer buffer, @Nullable File file,
- @NonNull FontStyle fontStyle, @IntRange(from = 0) int ttcIndex,
- @Nullable FontVariationAxis[] axes, @NonNull String localeList,
- int sourceIdentifier) {
- mBuffer = buffer;
- mFile = file;
- mFontStyle = fontStyle;
+ public Font(long 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 @@
* @return a font buffer
*/
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 @@
* @return a file path of the font
*/
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 @@
* @return a font style
*/
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 @@
* @return a TTC index value
*/
public @IntRange(from = 0) int getTtcIndex() {
- return mTtcIndex;
+ return nGetIndex(mNativePtr);
}
/**
@@ -608,7 +620,23 @@
* @return font variation settings
*/
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 @@
* @return a locale list
*/
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 @@
* @return an unique identifier for the font source data.
*/
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 @@
private boolean isSameSource(@NonNull Font other) {
Objects.requireNonNull(other);
+ ByteBuffer myBuffer = getBuffer();
+ ByteBuffer otherBuffer = other.getBuffer();
+
// Shortcut for the same instance.
- if (mBuffer == other.mBuffer) {
+ if (myBuffer == otherBuffer) {
return true;
}
// Shortcut for different font buffer check by comparing size.
- if (mBuffer.capacity() != other.mBuffer.capacity()) {
+ if (myBuffer.capacity() != otherBuffer.capacity()) {
return false;
}
@@ -750,15 +804,15 @@
// 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,
// check buffer position even if the buffer points the same address.
- if (mSourceIdentifier == other.mSourceIdentifier
- && mBuffer.position() == other.mBuffer.position()) {
+ if (getSourceIdentifier() == other.getSourceIdentifier()
+ && myBuffer.position() == otherBuffer.position()) {
return true;
}
// 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
// differently. For being compatible with API30 ore before, compare with ByteBuffer#equals.
- return mBuffer.equals(other.mBuffer);
+ return myBuffer.equals(otherBuffer);
}
@Override
@@ -769,10 +823,20 @@
if (!(o instanceof Font)) {
return false;
}
+
Font f = (Font) o;
- boolean paramEqual = mFontStyle.equals(f.mFontStyle) && f.mTtcIndex == mTtcIndex
- && Arrays.equals(f.mAxes, mAxes) && Objects.equals(f.mLocaleList, mLocaleList)
- && Objects.equals(mFile, f.mFile);
+
+ // The underlying minikin::Font object is the source of the truth of font information. Thus,
+ // 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) {
return false;
@@ -784,64 +848,42 @@
@Override
public int hashCode() {
return Objects.hash(
- mFontStyle,
- mTtcIndex,
- Arrays.hashCode(mAxes),
+ getStyle(),
+ getTtcIndex(),
+ Arrays.hashCode(getAxes()),
// 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
// happens because it is unlikely happens the different font files has exactly the
// same size.
- mLocaleList);
+ getLocaleList());
}
@Override
public String toString() {
return "Font {"
- + "path=" + mFile
- + ", style=" + mFontStyle
- + ", ttcIndex=" + mTtcIndex
- + ", axes=" + FontVariationAxis.toFontVariationSettings(mAxes)
- + ", localeList=" + mLocaleList
- + ", buffer=" + mBuffer
+ + "path=" + getFile()
+ + ", style=" + getStyle()
+ + ", ttcIndex=" + getTtcIndex()
+ + ", axes=" + FontVariationAxis.toFontVariationSettings(getAxes())
+ + ", localeList=" + getLocaleList()
+ + ", buffer=" + getBuffer()
+ "}";
}
- /**
- * Lookup Font object from native pointer or create new one if not found.
- * @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;
- }
- }
+ @CriticalNative
+ private static native long nGetMinikinFontPtr(long font);
- // If not found, create Font object from native object for Java API users.
- ByteBuffer buffer = NativeFontBufferHelper.refByteBuffer(ptr);
- NativeFont.Font font = NativeFont.readNativeFont(ptr);
+ @CriticalNative
+ private static native long nCloneFont(long font);
- Font.Builder builder = new Font.Builder(buffer, font.getFile(), "")
- .setWeight(font.getStyle().getWeight())
- .setSlant(font.getStyle().getSlant())
- .setTtcIndex(font.getIndex())
- .setFontVariationSettings(font.getAxes());
+ @FastNative
+ private static native ByteBuffer nNewByteBuffer(long font);
- Font newFont = null;
- try {
- newFont = builder.build();
- FONT_PTR_MAP.append(ptr, new WeakReference<>(newFont));
- } catch (IOException e) {
- // 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;
- }
- }
+ @CriticalNative
+ private static native long nGetBufferAddress(long font);
+
+ @CriticalNative
+ private static native long nGetReleaseNativeFont();
@FastNative
private static native float nGetGlyphBounds(long font, int glyphId, long paint, RectF rect);
@@ -849,9 +891,21 @@
@FastNative
private static native float nGetFontMetrics(long font, long paint, Paint.FontMetrics metrics);
- @CriticalNative
- private static native long nGetNativeFontPtr(long ptr);
+ @FastNative
+ private static native String nGetFontPath(long fontPtr);
+
+ @FastNative
+ private static native String nGetLocaleList(long familyPtr);
@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);
}
diff --git a/graphics/java/android/graphics/fonts/FontFamily.java b/graphics/java/android/graphics/fonts/FontFamily.java
index 77f86fe..8c13d3e 100644
--- a/graphics/java/android/graphics/fonts/FontFamily.java
+++ b/graphics/java/android/graphics/fonts/FontFamily.java
@@ -143,12 +143,10 @@
private static native long nGetReleaseNativeFamily();
}
- private final ArrayList<Font> mFonts;
private final long mNativePtr;
// Use Builder instead.
private FontFamily(@NonNull ArrayList<Font> fonts, long ptr) {
- mFonts = fonts;
mNativePtr = ptr;
}
@@ -176,7 +174,10 @@
* @return a registered font
*/
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 @@
* @return the number of fonts registered in this family.
*/
public @IntRange(from = 1) int getSize() {
- return mFonts.size();
+ return nGetFontSize(mNativePtr);
}
/** @hide */
@@ -193,6 +194,12 @@
return mNativePtr;
}
+ @CriticalNative
+ private static native int nGetFontSize(long family);
+
+ @CriticalNative
+ private static native long nGetFont(long family, int i);
+
@FastNative
private static native String nGetLangTags(long family);
diff --git a/graphics/java/android/graphics/fonts/NativeFont.java b/graphics/java/android/graphics/fonts/NativeFont.java
deleted file mode 100644
index 9e9d76a..0000000
--- a/graphics/java/android/graphics/fonts/NativeFont.java
+++ /dev/null
@@ -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);
-}
diff --git a/graphics/java/android/graphics/fonts/NativeFontBufferHelper.java b/graphics/java/android/graphics/fonts/NativeFontBufferHelper.java
deleted file mode 100644
index 5655e7f..0000000
--- a/graphics/java/android/graphics/fonts/NativeFontBufferHelper.java
+++ /dev/null
@@ -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();
-}
diff --git a/graphics/java/android/graphics/text/PositionedGlyphs.java b/graphics/java/android/graphics/text/PositionedGlyphs.java
index c2de0ac..8d20e9c 100644
--- a/graphics/java/android/graphics/text/PositionedGlyphs.java
+++ b/graphics/java/android/graphics/text/PositionedGlyphs.java
@@ -184,7 +184,7 @@
long ptr = nGetFont(layoutPtr, i);
if (prevPtr != ptr) {
prevPtr = ptr;
- prevFont = Font.findOrCreateFontFromNativePtr(ptr);
+ prevFont = new Font(ptr);
}
mFonts.add(prevFont);
}
@@ -224,9 +224,7 @@
if (getGlyphId(i) != that.getGlyphId(i)) return false;
if (getGlyphX(i) != that.getGlyphX(i)) return false;
if (getGlyphY(i) != that.getGlyphY(i)) return false;
- // Intentionally using reference equality since font equality is heavy due to buffer
- // compare.
- if (getFont(i) != that.getFont(i)) return false;
+ if (!getFont(i).equals(that.getFont(i))) return false;
}
return true;
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index ce1d96c..f481228 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -335,7 +335,6 @@
"jni/YuvToJpegEncoder.cpp",
"jni/fonts/Font.cpp",
"jni/fonts/FontFamily.cpp",
- "jni/fonts/NativeFont.cpp",
"jni/text/LineBreaker.cpp",
"jni/text/MeasuredText.cpp",
"jni/text/TextShaper.cpp",
diff --git a/libs/hwui/apex/jni_runtime.cpp b/libs/hwui/apex/jni_runtime.cpp
index 0fad2d5..e1f5abd7 100644
--- a/libs/hwui/apex/jni_runtime.cpp
+++ b/libs/hwui/apex/jni_runtime.cpp
@@ -69,7 +69,6 @@
extern int register_android_graphics_drawable_VectorDrawable(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_NativeFont(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_PdfRenderer(JNIEnv* env);
@@ -136,7 +135,6 @@
REG_JNI(register_android_graphics_drawable_VectorDrawable),
REG_JNI(register_android_graphics_fonts_Font),
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_PdfEditor),
REG_JNI(register_android_graphics_pdf_PdfRenderer),
diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp
index b769d40..3392dac 100644
--- a/libs/hwui/jni/fonts/Font.cpp
+++ b/libs/hwui/jni/fonts/Font.cpp
@@ -34,6 +34,7 @@
#include <hwui/Typeface.h>
#include <minikin/FontFamily.h>
#include <minikin/FontFileParser.h>
+#include <minikin/LocaleList.h>
#include <ui/FatVector.h>
#include <memory>
@@ -149,12 +150,8 @@
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
static jfloat Font_getGlyphBounds(JNIEnv* env, jobject, jlong fontHandle, jint glyphId,
@@ -195,51 +192,92 @@
}
// Critical Native
-static jlong Font_getNativeFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontHandle) {
- FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
- return reinterpret_cast<jlong>(font->font.get());
+static jlong Font_getMinikinFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
+ FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
+ return reinterpret_cast<jlong>(font->font->typeface().get());
}
// Critical Native
-static jlong Font_GetBufferAddress(CRITICAL_JNI_PARAMS_COMMA jlong fontHandle) {
- FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
- const void* bufferPtr = font->font->typeface()->GetFontData();
- return reinterpret_cast<jlong>(bufferPtr);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-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()));
+static jlong Font_cloneFont(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
+ FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
+ std::shared_ptr<minikin::Font> ref = font->font;
+ return reinterpret_cast<jlong>(new FontWrapper(std::move(ref)));
}
// Fast Native
-static jobject FontBufferHelper_wrapByteBuffer(JNIEnv* env, jobject, jlong nativePtr) {
- FontBufferWrapper* wrapper = reinterpret_cast<FontBufferWrapper*>(nativePtr);
- return env->NewDirectByteBuffer(
- const_cast<void*>(wrapper->minikinFont->GetFontData()),
- wrapper->minikinFont->GetFontSize());
+static jobject Font_newByteBuffer(JNIEnv* env, jobject, jlong fontPtr) {
+ FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
+ const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
+ return env->NewDirectByteBuffer(const_cast<void*>(minikinFont->GetFontData()),
+ minikinFont->GetFontSize());
}
// Critical Native
-static jlong FontBufferHelper_getReleaseFunc(CRITICAL_JNI_PARAMS) {
- return reinterpret_cast<jlong>(unrefBuffer);
+static jlong Font_getBufferAddress(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
+ 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
static jlong FontFileUtil_getFontRevision(JNIEnv* env, jobject, jobject buffer, jint index) {
@@ -314,20 +352,23 @@
{"nBuild", "(JLjava/nio/ByteBuffer;Ljava/lang/String;Ljava/lang/String;IZI)J",
(void*)Font_Builder_build},
{"nClone", "(JJIZI)J", (void*)Font_Builder_clone},
- {"nGetReleaseNativeFont", "()J", (void*)Font_Builder_getReleaseNativeFont},
};
static const JNINativeMethod gFontMethods[] = {
- { "nGetGlyphBounds", "(JIJLandroid/graphics/RectF;)F", (void*) Font_getGlyphBounds },
- { "nGetFontMetrics", "(JJLandroid/graphics/Paint$FontMetrics;)F", (void*) Font_getFontMetrics },
- { "nGetNativeFontPtr", "(J)J", (void*) Font_getNativeFontPtr },
- { "nGetFontBufferAddress", "(J)J", (void*) Font_GetBufferAddress },
-};
-
-static const JNINativeMethod gFontBufferHelperMethods[] = {
- { "nRefFontBuffer", "(J)J", (void*) FontBufferHelper_refFontBuffer },
- { "nWrapByteBuffer", "(J)Ljava/nio/ByteBuffer;", (void*) FontBufferHelper_wrapByteBuffer },
- { "nGetReleaseFunc", "()J", (void*) FontBufferHelper_getReleaseFunc },
+ {"nGetMinikinFontPtr", "(J)J", (void*)Font_getMinikinFontPtr},
+ {"nCloneFont", "(J)J", (void*)Font_cloneFont},
+ {"nNewByteBuffer", "(J)Ljava/nio/ByteBuffer;", (void*)Font_newByteBuffer},
+ {"nGetBufferAddress", "(J)J", (void*)Font_getBufferAddress},
+ {"nGetReleaseNativeFont", "()J", (void*)Font_getReleaseNativeFontFunc},
+ {"nGetGlyphBounds", "(JIJLandroid/graphics/RectF;)F", (void*)Font_getGlyphBounds},
+ {"nGetFontMetrics", "(JJLandroid/graphics/Paint$FontMetrics;)F",
+ (void*)Font_getFontMetrics},
+ {"nGetFontPath", "(J)Ljava/lang/String;", (void*)Font_getFontPath},
+ {"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[] = {
@@ -343,8 +384,6 @@
NELEM(gFontBuilderMethods)) +
RegisterMethodsOrDie(env, "android/graphics/fonts/Font", gFontMethods,
NELEM(gFontMethods)) +
- RegisterMethodsOrDie(env, "android/graphics/fonts/NativeFontBufferHelper",
- gFontBufferHelperMethods, NELEM(gFontBufferHelperMethods)) +
RegisterMethodsOrDie(env, "android/graphics/fonts/FontFileUtil", gFontFileUtilMethods,
NELEM(gFontFileUtilMethods));
}
diff --git a/libs/hwui/jni/fonts/FontFamily.cpp b/libs/hwui/jni/fonts/FontFamily.cpp
index a07723f..c40594d 100644
--- a/libs/hwui/jni/fonts/FontFamily.cpp
+++ b/libs/hwui/jni/fonts/FontFamily.cpp
@@ -100,17 +100,31 @@
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[] = {
{ "nInitBuilder", "()J", (void*) FontFamily_Builder_initBuilder },
{ "nAddFont", "(JJ)V", (void*) FontFamily_Builder_addFont },
{ "nBuild", "(JLjava/lang/String;IZ)J", (void*) FontFamily_Builder_build },
-
{ "nGetReleaseNativeFamily", "()J", (void*) FontFamily_Builder_GetReleaseFunc },
};
static const JNINativeMethod gFontFamilyMethods[] = {
+ {"nGetFontSize", "(J)I", (void*)FontFamily_getFontSize},
+ {"nGetFont", "(JI)J", (void*)FontFamily_getFont},
{"nGetLangTags", "(J)Ljava/lang/String;", (void*)FontFamily_getLangTags},
{"nGetVariant", "(J)I", (void*)FontFamily_getVariant},
};
diff --git a/libs/hwui/jni/fonts/NativeFont.cpp b/libs/hwui/jni/fonts/NativeFont.cpp
deleted file mode 100644
index c5c5d46..0000000
--- a/libs/hwui/jni/fonts/NativeFont.cpp
+++ /dev/null
@@ -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
diff --git a/libs/hwui/jni/text/TextShaper.cpp b/libs/hwui/jni/text/TextShaper.cpp
index 9785aa5..a6fb958 100644
--- a/libs/hwui/jni/text/TextShaper.cpp
+++ b/libs/hwui/jni/text/TextShaper.cpp
@@ -23,13 +23,14 @@
#include <set>
#include <algorithm>
-#include "SkPaint.h"
-#include "SkTypeface.h"
#include <hwui/MinikinSkia.h>
#include <hwui/MinikinUtils.h>
#include <hwui/Paint.h>
-#include <minikin/MinikinPaint.h>
#include <minikin/MinikinFont.h>
+#include <minikin/MinikinPaint.h>
+#include "FontUtils.h"
+#include "SkPaint.h"
+#include "SkTypeface.h"
namespace android {
@@ -149,7 +150,8 @@
// CriticalNative
static jlong TextShaper_Result_getFont(CRITICAL_JNI_PARAMS_COMMA jlong ptr, jint i) {
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