blob: d78df3dca3b138b39aec15d19704dd7aa7f78d6d [file] [log] [blame]
Seigo Nonakaa1c21c02018-07-20 15:57:39 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Derek Sollenberger5368eda2019-10-25 11:20:03 -040017#undef LOG_TAG
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070018#define LOG_TAG "Minikin"
19
Kohsuke Yatoh1ca390e2020-11-06 16:21:30 -080020#include "Font.h"
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070021#include "SkData.h"
Seigo Nonaka1ed4f642020-09-10 17:19:34 -070022#include "SkFont.h"
23#include "SkFontMetrics.h"
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070024#include "SkFontMgr.h"
25#include "SkRefCnt.h"
26#include "SkTypeface.h"
27#include "GraphicsJNI.h"
28#include <nativehelper/ScopedUtfChars.h>
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070029#include "Utils.h"
30#include "FontUtils.h"
31
32#include <hwui/MinikinSkia.h>
Seigo Nonaka1ed4f642020-09-10 17:19:34 -070033#include <hwui/Paint.h>
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070034#include <hwui/Typeface.h>
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070035#include <minikin/FontFamily.h>
Seigo Nonaka47b6c1b2021-01-13 15:02:47 -080036#include <minikin/FontFileParser.h>
Seigo Nonaka1dd39f32021-02-05 19:15:29 -080037#include <minikin/LocaleList.h>
Seigo Nonakad5ecaba2021-05-27 15:49:37 -070038#include <minikin/SystemFonts.h>
Jagadeesh Pakaravoorb624af32020-05-01 00:01:40 +000039#include <ui/FatVector.h>
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070040
41#include <memory>
42
43namespace android {
44
45struct NativeFontBuilder {
46 std::vector<minikin::FontVariation> axes;
47};
48
49static inline NativeFontBuilder* toBuilder(jlong ptr) {
50 return reinterpret_cast<NativeFontBuilder*>(ptr);
51}
52
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070053static void releaseFont(jlong font) {
54 delete reinterpret_cast<FontWrapper*>(font);
55}
56
57static void release_global_ref(const void* /*data*/, void* context) {
Derek Sollenbergerc5882c42019-10-25 11:11:32 -040058 JNIEnv* env = GraphicsJNI::getJNIEnv();
59 bool needToAttach = (env == nullptr);
60 if (needToAttach) {
61 env = GraphicsJNI::attachJNIEnv("release_font_data");
62 if (env == nullptr) {
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070063 ALOGE("failed to attach to thread to release global ref.");
64 return;
65 }
66 }
67
68 jobject obj = reinterpret_cast<jobject>(context);
69 env->DeleteGlobalRef(obj);
70}
71
72// Regular JNI
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070073static jlong Font_Builder_initBuilder(JNIEnv*, jobject) {
74 return reinterpret_cast<jlong>(new NativeFontBuilder());
75}
76
77// Critical Native
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +010078static void Font_Builder_addAxis(CRITICAL_JNI_PARAMS_COMMA jlong builderPtr, jint tag, jfloat value) {
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070079 toBuilder(builderPtr)->axes.emplace_back(static_cast<minikin::AxisTag>(tag), value);
80}
81
82// Regular JNI
83static jlong Font_Builder_build(JNIEnv* env, jobject clazz, jlong builderPtr, jobject buffer,
Seigo Nonaka99c07562021-02-03 21:37:57 -080084 jstring filePath, jstring langTags, jint weight, jboolean italic,
85 jint ttcIndex) {
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070086 NPE_CHECK_RETURN_ZERO(env, buffer);
87 std::unique_ptr<NativeFontBuilder> builder(toBuilder(builderPtr));
88 const void* fontPtr = env->GetDirectBufferAddress(buffer);
89 if (fontPtr == nullptr) {
90 jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
91 return 0;
92 }
93 jlong fontSize = env->GetDirectBufferCapacity(buffer);
94 if (fontSize <= 0) {
95 jniThrowException(env, "java/lang/IllegalArgumentException",
96 "buffer size must not be zero or negative");
97 return 0;
98 }
Seigo Nonaka54c6a272018-10-25 15:44:32 -070099 ScopedUtfChars fontPath(env, filePath);
Seigo Nonaka99c07562021-02-03 21:37:57 -0800100 ScopedUtfChars langTagStr(env, langTags);
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700101 jobject fontRef = MakeGlobalRefOrDie(env, buffer);
102 sk_sp<SkData> data(SkData::MakeWithProc(fontPtr, fontSize,
103 release_global_ref, reinterpret_cast<void*>(fontRef)));
Kohsuke Yatoh1ca390e2020-11-06 16:21:30 -0800104 std::shared_ptr<minikin::MinikinFont> minikinFont = fonts::createMinikinFontSkia(
105 std::move(data), std::string_view(fontPath.c_str(), fontPath.size()),
106 fontPtr, fontSize, ttcIndex, builder->axes);
107 if (minikinFont == nullptr) {
xi yu61d6a90d2023-02-17 03:47:43 +0000108 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
109 "Failed to create internal object. maybe invalid font data. filePath %s",
110 fontPath.c_str());
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700111 return 0;
112 }
Seigo Nonaka99c07562021-02-03 21:37:57 -0800113 uint32_t localeListId = minikin::registerLocaleList(langTagStr.c_str());
114 std::shared_ptr<minikin::Font> font =
115 minikin::Font::Builder(minikinFont)
116 .setWeight(weight)
117 .setSlant(static_cast<minikin::FontStyle::Slant>(italic))
118 .setLocaleListId(localeListId)
119 .build();
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700120 return reinterpret_cast<jlong>(new FontWrapper(std::move(font)));
121}
122
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700123// Fast Native
124static jlong Font_Builder_clone(JNIEnv* env, jobject clazz, jlong fontPtr, jlong builderPtr,
125 jint weight, jboolean italic, jint ttcIndex) {
126 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
Seigo Nonaka760d3512020-10-01 12:29:03 -0700127 MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->typeface().get());
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700128 std::unique_ptr<NativeFontBuilder> builder(toBuilder(builderPtr));
129
130 // Reconstruct SkTypeface with different arguments from existing SkTypeface.
131 FatVector<SkFontArguments::VariationPosition::Coordinate, 2> skVariation;
132 for (const auto& axis : builder->axes) {
133 skVariation.push_back({axis.axisTag, axis.value});
134 }
135 SkFontArguments args;
136 args.setCollectionIndex(ttcIndex);
137 args.setVariationDesignPosition({skVariation.data(), static_cast<int>(skVariation.size())});
138
139 sk_sp<SkTypeface> newTypeface = minikinSkia->GetSkTypeface()->makeClone(args);
140
141 std::shared_ptr<minikin::MinikinFont> newMinikinFont = std::make_shared<MinikinFontSkia>(
Seigo Nonaka5dd6dd52021-02-11 20:02:27 -0800142 std::move(newTypeface), minikinSkia->GetSourceId(), minikinSkia->GetFontData(),
143 minikinSkia->GetFontSize(), minikinSkia->getFilePath(), minikinSkia->GetFontIndex(),
144 builder->axes);
Seigo Nonaka760d3512020-10-01 12:29:03 -0700145 std::shared_ptr<minikin::Font> newFont = minikin::Font::Builder(newMinikinFont)
146 .setWeight(weight)
147 .setSlant(static_cast<minikin::FontStyle::Slant>(italic))
148 .build();
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700149 return reinterpret_cast<jlong>(new FontWrapper(std::move(newFont)));
150}
151
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700152///////////////////////////////////////////////////////////////////////////////
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800153// Font JNI functions
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700154
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700155// Fast Native
156static jfloat Font_getGlyphBounds(JNIEnv* env, jobject, jlong fontHandle, jint glyphId,
157 jlong paintHandle, jobject rect) {
158 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
Seigo Nonaka760d3512020-10-01 12:29:03 -0700159 MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->typeface().get());
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700160 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
161
162 SkFont* skFont = &paint->getSkFont();
163 // We don't use populateSkFont since it is designed to be used for layout result with addressing
164 // auto fake-bolding.
165 skFont->setTypeface(minikinSkia->RefSkTypeface());
166
167 uint16_t glyph16 = glyphId;
168 SkRect skBounds;
169 SkScalar skWidth;
170 skFont->getWidthsBounds(&glyph16, 1, &skWidth, &skBounds, nullptr);
171 GraphicsJNI::rect_to_jrectf(skBounds, env, rect);
172 return SkScalarToFloat(skWidth);
173}
174
175// Fast Native
176static jfloat Font_getFontMetrics(JNIEnv* env, jobject, jlong fontHandle, jlong paintHandle,
177 jobject metricsObj) {
178 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
Seigo Nonaka760d3512020-10-01 12:29:03 -0700179 MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->typeface().get());
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700180 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
181
182 SkFont* skFont = &paint->getSkFont();
183 // We don't use populateSkFont since it is designed to be used for layout result with addressing
184 // auto fake-bolding.
185 skFont->setTypeface(minikinSkia->RefSkTypeface());
186
187 SkFontMetrics metrics;
188 SkScalar spacing = skFont->getMetrics(&metrics);
189 GraphicsJNI::set_metrics(env, metricsObj, metrics);
190 return spacing;
191}
192
Seigo Nonakaf3a19152020-09-14 15:29:42 -0700193// Critical Native
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800194static jlong Font_getMinikinFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
195 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000196 return reinterpret_cast<jlong>(font->font.get());
Seigo Nonaka760d3512020-10-01 12:29:03 -0700197}
198
Seigo Nonaka31bf8602020-10-14 15:04:01 -0700199// Critical Native
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800200static jlong Font_cloneFont(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
201 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
202 std::shared_ptr<minikin::Font> ref = font->font;
203 return reinterpret_cast<jlong>(new FontWrapper(std::move(ref)));
Seigo Nonakaf3a19152020-09-14 15:29:42 -0700204}
205
206// Fast Native
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800207static jobject Font_newByteBuffer(JNIEnv* env, jobject, jlong fontPtr) {
208 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
209 const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
210 return env->NewDirectByteBuffer(const_cast<void*>(minikinFont->GetFontData()),
211 minikinFont->GetFontSize());
Seigo Nonakaf3a19152020-09-14 15:29:42 -0700212}
213
214// Critical Native
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800215static jlong Font_getBufferAddress(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
216 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
217 return reinterpret_cast<jlong>(font->font->typeface()->GetFontData());
Seigo Nonakaf3a19152020-09-14 15:29:42 -0700218}
219
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800220// Critical Native
Jerome Gaillardb71861c2021-02-09 13:10:49 +0000221static jlong Font_getReleaseNativeFontFunc(CRITICAL_JNI_PARAMS) {
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800222 return reinterpret_cast<jlong>(releaseFont);
223}
224
225// Fast Native
226static jstring Font_getFontPath(JNIEnv* env, jobject, jlong fontPtr) {
227 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000228 minikin::BufferReader reader = font->font->typefaceMetadataReader();
229 if (reader.data() != nullptr) {
230 std::string path = std::string(reader.readString());
231 if (path.empty()) {
232 return nullptr;
233 }
234 return env->NewStringUTF(path.c_str());
235 } else {
236 const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
237 const std::string& path = minikinFont->GetFontPath();
238 if (path.empty()) {
239 return nullptr;
240 }
241 return env->NewStringUTF(path.c_str());
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800242 }
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800243}
244
245// Fast Native
246static jstring Font_getLocaleList(JNIEnv* env, jobject, jlong fontPtr) {
247 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
248 uint32_t localeListId = font->font->getLocaleListId();
249 if (localeListId == 0) {
250 return nullptr;
251 }
252 std::string langTags = minikin::getLocaleString(localeListId);
253 if (langTags.empty()) {
254 return nullptr;
255 }
256 return env->NewStringUTF(langTags.c_str());
257}
258
259// Critical Native
260static jint Font_getPackedStyle(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
261 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
262 uint32_t weight = font->font->style().weight();
263 uint32_t isItalic = font->font->style().slant() == minikin::FontStyle::Slant::ITALIC ? 1 : 0;
264 return (isItalic << 16) | weight;
265}
266
267// Critical Native
268static jint Font_getIndex(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
269 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000270 minikin::BufferReader reader = font->font->typefaceMetadataReader();
271 if (reader.data() != nullptr) {
272 reader.skipString(); // fontPath
273 return reader.read<int>();
274 } else {
275 const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
276 return minikinFont->GetFontIndex();
277 }
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800278}
279
280// Critical Native
281static jint Font_getAxisCount(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
282 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000283 minikin::BufferReader reader = font->font->typefaceMetadataReader();
284 if (reader.data() != nullptr) {
285 reader.skipString(); // fontPath
286 reader.skip<int>(); // fontIndex
287 return reader.readArray<minikin::FontVariation>().second;
288 } else {
289 const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
290 return minikinFont->GetAxes().size();
291 }
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800292}
293
294// Critical Native
295static jlong Font_getAxisInfo(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr, jint index) {
296 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000297 minikin::BufferReader reader = font->font->typefaceMetadataReader();
298 minikin::FontVariation var;
299 if (reader.data() != nullptr) {
300 reader.skipString(); // fontPath
301 reader.skip<int>(); // fontIndex
302 var = reader.readArray<minikin::FontVariation>().first[index];
303 } else {
304 const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->typeface();
305 var = minikinFont->GetAxes().at(index);
306 }
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800307 uint32_t floatBinary = *reinterpret_cast<const uint32_t*>(&var.value);
308 return (static_cast<uint64_t>(var.axisTag) << 32) | static_cast<uint64_t>(floatBinary);
309}
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700310
Seigo Nonaka5dd6dd52021-02-11 20:02:27 -0800311// Critical Native
312static jint Font_getSourceId(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
313 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
314 return font->font->typeface()->GetSourceId();
315}
316
Seigo Nonakad5ecaba2021-05-27 15:49:37 -0700317static jlongArray Font_getAvailableFontSet(JNIEnv* env, jobject) {
318 std::vector<jlong> refArray;
319 minikin::SystemFonts::getFontSet(
320 [&refArray](const std::vector<std::shared_ptr<minikin::Font>>& fontSet) {
321 refArray.reserve(fontSet.size());
322 for (const auto& font : fontSet) {
323 std::shared_ptr<minikin::Font> fontRef = font;
324 refArray.push_back(
325 reinterpret_cast<jlong>(new FontWrapper(std::move(fontRef))));
326 }
327 });
328 jlongArray r = env->NewLongArray(refArray.size());
329 env->SetLongArrayRegion(r, 0, refArray.size(), refArray.data());
330 return r;
331}
332
Seigo Nonaka47b6c1b2021-01-13 15:02:47 -0800333// Fast Native
334static jlong FontFileUtil_getFontRevision(JNIEnv* env, jobject, jobject buffer, jint index) {
335 NPE_CHECK_RETURN_ZERO(env, buffer);
336 const void* fontPtr = env->GetDirectBufferAddress(buffer);
337 if (fontPtr == nullptr) {
338 jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
339 return 0;
340 }
341 jlong fontSize = env->GetDirectBufferCapacity(buffer);
342 if (fontSize <= 0) {
343 jniThrowException(env, "java/lang/IllegalArgumentException",
344 "buffer size must not be zero or negative");
345 return 0;
346 }
347 minikin::FontFileParser parser(fontPtr, fontSize, index);
348 std::optional<uint32_t> revision = parser.getFontRevision();
349 if (!revision.has_value()) {
350 return -1L;
351 }
352 return revision.value();
353}
354
355static jstring FontFileUtil_getFontPostScriptName(JNIEnv* env, jobject, jobject buffer,
356 jint index) {
357 NPE_CHECK_RETURN_ZERO(env, buffer);
358 const void* fontPtr = env->GetDirectBufferAddress(buffer);
359 if (fontPtr == nullptr) {
360 jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
361 return nullptr;
362 }
363 jlong fontSize = env->GetDirectBufferCapacity(buffer);
364 if (fontSize <= 0) {
365 jniThrowException(env, "java/lang/IllegalArgumentException",
366 "buffer size must not be zero or negative");
367 return nullptr;
368 }
369 minikin::FontFileParser parser(fontPtr, fontSize, index);
370 std::optional<std::string> psName = parser.getPostScriptName();
371 if (!psName.has_value()) {
372 return nullptr; // null
373 }
374 return env->NewStringUTF(psName->c_str());
375}
Seigo Nonaka9d5ab7e2021-01-20 22:50:09 -0800376
377static jint FontFileUtil_isPostScriptType1Font(JNIEnv* env, jobject, jobject buffer, jint index) {
378 NPE_CHECK_RETURN_ZERO(env, buffer);
379 const void* fontPtr = env->GetDirectBufferAddress(buffer);
380 if (fontPtr == nullptr) {
381 jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
382 return -1;
383 }
384 jlong fontSize = env->GetDirectBufferCapacity(buffer);
385 if (fontSize <= 0) {
386 jniThrowException(env, "java/lang/IllegalArgumentException",
387 "buffer size must not be zero or negative");
388 return -1;
389 }
390 minikin::FontFileParser parser(fontPtr, fontSize, index);
391 std::optional<bool> isType1 = parser.isPostScriptType1Font();
392 if (!isType1.has_value()) {
393 return -1; // not an OpenType font. HarfBuzz failed to parse it.
394 }
395 return isType1.value();
396}
397
Seigo Nonaka47b6c1b2021-01-13 15:02:47 -0800398///////////////////////////////////////////////////////////////////////////////
399
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700400static const JNINativeMethod gFontBuilderMethods[] = {
Seigo Nonaka99c07562021-02-03 21:37:57 -0800401 {"nInitBuilder", "()J", (void*)Font_Builder_initBuilder},
402 {"nAddAxis", "(JIF)V", (void*)Font_Builder_addAxis},
403 {"nBuild", "(JLjava/nio/ByteBuffer;Ljava/lang/String;Ljava/lang/String;IZI)J",
404 (void*)Font_Builder_build},
405 {"nClone", "(JJIZI)J", (void*)Font_Builder_clone},
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700406};
407
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700408static const JNINativeMethod gFontMethods[] = {
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800409 {"nGetMinikinFontPtr", "(J)J", (void*)Font_getMinikinFontPtr},
410 {"nCloneFont", "(J)J", (void*)Font_cloneFont},
411 {"nNewByteBuffer", "(J)Ljava/nio/ByteBuffer;", (void*)Font_newByteBuffer},
412 {"nGetBufferAddress", "(J)J", (void*)Font_getBufferAddress},
413 {"nGetReleaseNativeFont", "()J", (void*)Font_getReleaseNativeFontFunc},
414 {"nGetGlyphBounds", "(JIJLandroid/graphics/RectF;)F", (void*)Font_getGlyphBounds},
415 {"nGetFontMetrics", "(JJLandroid/graphics/Paint$FontMetrics;)F",
416 (void*)Font_getFontMetrics},
417 {"nGetFontPath", "(J)Ljava/lang/String;", (void*)Font_getFontPath},
418 {"nGetLocaleList", "(J)Ljava/lang/String;", (void*)Font_getLocaleList},
419 {"nGetPackedStyle", "(J)I", (void*)Font_getPackedStyle},
420 {"nGetIndex", "(J)I", (void*)Font_getIndex},
421 {"nGetAxisCount", "(J)I", (void*)Font_getAxisCount},
422 {"nGetAxisInfo", "(JI)J", (void*)Font_getAxisInfo},
Seigo Nonaka5dd6dd52021-02-11 20:02:27 -0800423 {"nGetSourceId", "(J)I", (void*)Font_getSourceId},
Seigo Nonakad5ecaba2021-05-27 15:49:37 -0700424
425 // System font accessors
426 {"nGetAvailableFontSet", "()[J", (void*)Font_getAvailableFontSet},
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700427};
428
Seigo Nonaka47b6c1b2021-01-13 15:02:47 -0800429static const JNINativeMethod gFontFileUtilMethods[] = {
430 { "nGetFontRevision", "(Ljava/nio/ByteBuffer;I)J", (void*) FontFileUtil_getFontRevision },
431 { "nGetFontPostScriptName", "(Ljava/nio/ByteBuffer;I)Ljava/lang/String;",
432 (void*) FontFileUtil_getFontPostScriptName },
Seigo Nonaka9d5ab7e2021-01-20 22:50:09 -0800433 { "nIsPostScriptType1Font", "(Ljava/nio/ByteBuffer;I)I",
434 (void*) FontFileUtil_isPostScriptType1Font },
Seigo Nonaka47b6c1b2021-01-13 15:02:47 -0800435};
436
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700437int register_android_graphics_fonts_Font(JNIEnv* env) {
438 return RegisterMethodsOrDie(env, "android/graphics/fonts/Font$Builder", gFontBuilderMethods,
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700439 NELEM(gFontBuilderMethods)) +
440 RegisterMethodsOrDie(env, "android/graphics/fonts/Font", gFontMethods,
Seigo Nonakaf3a19152020-09-14 15:29:42 -0700441 NELEM(gFontMethods)) +
Seigo Nonaka47b6c1b2021-01-13 15:02:47 -0800442 RegisterMethodsOrDie(env, "android/graphics/fonts/FontFileUtil", gFontFileUtilMethods,
443 NELEM(gFontFileUtilMethods));
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700444}
445
Kohsuke Yatoh1ca390e2020-11-06 16:21:30 -0800446namespace fonts {
447
448std::shared_ptr<minikin::MinikinFont> createMinikinFontSkia(
449 sk_sp<SkData>&& data, std::string_view fontPath, const void *fontPtr, size_t fontSize,
450 int ttcIndex, const std::vector<minikin::FontVariation>& axes) {
451 FatVector<SkFontArguments::VariationPosition::Coordinate, 2> skVariation;
452 for (const auto& axis : axes) {
453 skVariation.push_back({axis.axisTag, axis.value});
454 }
455
456 std::unique_ptr<SkStreamAsset> fontData(new SkMemoryStream(std::move(data)));
457
458 SkFontArguments args;
459 args.setCollectionIndex(ttcIndex);
460 args.setVariationDesignPosition({skVariation.data(), static_cast<int>(skVariation.size())});
461
462 sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
463 sk_sp<SkTypeface> face(fm->makeFromStream(std::move(fontData), args));
464 if (face == nullptr) {
465 return nullptr;
466 }
Seigo Nonaka5dd6dd52021-02-11 20:02:27 -0800467 return std::make_shared<MinikinFontSkia>(std::move(face), getNewSourceId(), fontPtr, fontSize,
Kohsuke Yatoh1ca390e2020-11-06 16:21:30 -0800468 fontPath, ttcIndex, axes);
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700469}
Kohsuke Yatoh1ca390e2020-11-06 16:21:30 -0800470
Seigo Nonaka5dd6dd52021-02-11 20:02:27 -0800471int getNewSourceId() {
472 static std::atomic<int> sSourceId = {0};
473 return sSourceId++;
474}
475
Kohsuke Yatoh1ca390e2020-11-06 16:21:30 -0800476} // namespace fonts
477
478} // namespace android