blob: 8cfdeeb7e128b26b108f2458f70880f9335bb394 [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"
Kevin Lubick1175dc02022-02-28 12:41:27 -050025#include "SkRect.h"
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070026#include "SkRefCnt.h"
Kevin Lubick1175dc02022-02-28 12:41:27 -050027#include "SkScalar.h"
28#include "SkStream.h"
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070029#include "SkTypeface.h"
30#include "GraphicsJNI.h"
31#include <nativehelper/ScopedUtfChars.h>
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070032#include "Utils.h"
33#include "FontUtils.h"
34
35#include <hwui/MinikinSkia.h>
Seigo Nonaka1ed4f642020-09-10 17:19:34 -070036#include <hwui/Paint.h>
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070037#include <hwui/Typeface.h>
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070038#include <minikin/FontFamily.h>
Seigo Nonaka47b6c1b2021-01-13 15:02:47 -080039#include <minikin/FontFileParser.h>
Seigo Nonaka1dd39f32021-02-05 19:15:29 -080040#include <minikin/LocaleList.h>
Seigo Nonakad5ecaba2021-05-27 15:49:37 -070041#include <minikin/SystemFonts.h>
Jagadeesh Pakaravoorb624af32020-05-01 00:01:40 +000042#include <ui/FatVector.h>
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070043
44#include <memory>
45
46namespace android {
47
48struct NativeFontBuilder {
49 std::vector<minikin::FontVariation> axes;
50};
51
52static inline NativeFontBuilder* toBuilder(jlong ptr) {
53 return reinterpret_cast<NativeFontBuilder*>(ptr);
54}
55
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070056static void releaseFont(jlong font) {
57 delete reinterpret_cast<FontWrapper*>(font);
58}
59
60static void release_global_ref(const void* /*data*/, void* context) {
Derek Sollenbergerc5882c42019-10-25 11:11:32 -040061 JNIEnv* env = GraphicsJNI::getJNIEnv();
62 bool needToAttach = (env == nullptr);
63 if (needToAttach) {
64 env = GraphicsJNI::attachJNIEnv("release_font_data");
65 if (env == nullptr) {
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070066 ALOGE("failed to attach to thread to release global ref.");
67 return;
68 }
69 }
70
71 jobject obj = reinterpret_cast<jobject>(context);
72 env->DeleteGlobalRef(obj);
73}
74
75// Regular JNI
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070076static jlong Font_Builder_initBuilder(JNIEnv*, jobject) {
77 return reinterpret_cast<jlong>(new NativeFontBuilder());
78}
79
80// Critical Native
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +010081static void Font_Builder_addAxis(CRITICAL_JNI_PARAMS_COMMA jlong builderPtr, jint tag, jfloat value) {
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070082 toBuilder(builderPtr)->axes.emplace_back(static_cast<minikin::AxisTag>(tag), value);
83}
84
85// Regular JNI
86static jlong Font_Builder_build(JNIEnv* env, jobject clazz, jlong builderPtr, jobject buffer,
Seigo Nonaka99c07562021-02-03 21:37:57 -080087 jstring filePath, jstring langTags, jint weight, jboolean italic,
88 jint ttcIndex) {
Seigo Nonakaa1c21c02018-07-20 15:57:39 -070089 NPE_CHECK_RETURN_ZERO(env, buffer);
90 std::unique_ptr<NativeFontBuilder> builder(toBuilder(builderPtr));
91 const void* fontPtr = env->GetDirectBufferAddress(buffer);
92 if (fontPtr == nullptr) {
93 jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
94 return 0;
95 }
96 jlong fontSize = env->GetDirectBufferCapacity(buffer);
97 if (fontSize <= 0) {
98 jniThrowException(env, "java/lang/IllegalArgumentException",
99 "buffer size must not be zero or negative");
100 return 0;
101 }
Seigo Nonaka54c6a272018-10-25 15:44:32 -0700102 ScopedUtfChars fontPath(env, filePath);
Seigo Nonaka99c07562021-02-03 21:37:57 -0800103 ScopedUtfChars langTagStr(env, langTags);
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700104 jobject fontRef = MakeGlobalRefOrDie(env, buffer);
105 sk_sp<SkData> data(SkData::MakeWithProc(fontPtr, fontSize,
106 release_global_ref, reinterpret_cast<void*>(fontRef)));
Kohsuke Yatoh1ca390e2020-11-06 16:21:30 -0800107 std::shared_ptr<minikin::MinikinFont> minikinFont = fonts::createMinikinFontSkia(
108 std::move(data), std::string_view(fontPath.c_str(), fontPath.size()),
109 fontPtr, fontSize, ttcIndex, builder->axes);
110 if (minikinFont == nullptr) {
xi yu61d6a90d2023-02-17 03:47:43 +0000111 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
112 "Failed to create internal object. maybe invalid font data. filePath %s",
113 fontPath.c_str());
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700114 return 0;
115 }
Seigo Nonaka99c07562021-02-03 21:37:57 -0800116 uint32_t localeListId = minikin::registerLocaleList(langTagStr.c_str());
117 std::shared_ptr<minikin::Font> font =
118 minikin::Font::Builder(minikinFont)
119 .setWeight(weight)
120 .setSlant(static_cast<minikin::FontStyle::Slant>(italic))
121 .setLocaleListId(localeListId)
122 .build();
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700123 return reinterpret_cast<jlong>(new FontWrapper(std::move(font)));
124}
125
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700126// Fast Native
127static jlong Font_Builder_clone(JNIEnv* env, jobject clazz, jlong fontPtr, jlong builderPtr,
128 jint weight, jboolean italic, jint ttcIndex) {
129 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
Seigo Nonaka032aac92023-05-26 10:15:53 +0900130 MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->baseTypeface().get());
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700131 std::unique_ptr<NativeFontBuilder> builder(toBuilder(builderPtr));
132
133 // Reconstruct SkTypeface with different arguments from existing SkTypeface.
134 FatVector<SkFontArguments::VariationPosition::Coordinate, 2> skVariation;
135 for (const auto& axis : builder->axes) {
136 skVariation.push_back({axis.axisTag, axis.value});
137 }
138 SkFontArguments args;
139 args.setCollectionIndex(ttcIndex);
140 args.setVariationDesignPosition({skVariation.data(), static_cast<int>(skVariation.size())});
141
142 sk_sp<SkTypeface> newTypeface = minikinSkia->GetSkTypeface()->makeClone(args);
143
144 std::shared_ptr<minikin::MinikinFont> newMinikinFont = std::make_shared<MinikinFontSkia>(
Seigo Nonaka5dd6dd52021-02-11 20:02:27 -0800145 std::move(newTypeface), minikinSkia->GetSourceId(), minikinSkia->GetFontData(),
146 minikinSkia->GetFontSize(), minikinSkia->getFilePath(), minikinSkia->GetFontIndex(),
147 builder->axes);
Seigo Nonaka760d3512020-10-01 12:29:03 -0700148 std::shared_ptr<minikin::Font> newFont = minikin::Font::Builder(newMinikinFont)
149 .setWeight(weight)
150 .setSlant(static_cast<minikin::FontStyle::Slant>(italic))
151 .build();
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700152 return reinterpret_cast<jlong>(new FontWrapper(std::move(newFont)));
153}
154
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700155///////////////////////////////////////////////////////////////////////////////
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800156// Font JNI functions
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700157
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700158// Fast Native
159static jfloat Font_getGlyphBounds(JNIEnv* env, jobject, jlong fontHandle, jint glyphId,
160 jlong paintHandle, jobject rect) {
161 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
Seigo Nonaka032aac92023-05-26 10:15:53 +0900162 MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->baseTypeface().get());
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700163 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
164
165 SkFont* skFont = &paint->getSkFont();
166 // We don't use populateSkFont since it is designed to be used for layout result with addressing
167 // auto fake-bolding.
168 skFont->setTypeface(minikinSkia->RefSkTypeface());
169
170 uint16_t glyph16 = glyphId;
171 SkRect skBounds;
172 SkScalar skWidth;
173 skFont->getWidthsBounds(&glyph16, 1, &skWidth, &skBounds, nullptr);
174 GraphicsJNI::rect_to_jrectf(skBounds, env, rect);
175 return SkScalarToFloat(skWidth);
176}
177
178// Fast Native
179static jfloat Font_getFontMetrics(JNIEnv* env, jobject, jlong fontHandle, jlong paintHandle,
180 jobject metricsObj) {
181 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
Seigo Nonaka032aac92023-05-26 10:15:53 +0900182 MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->baseTypeface().get());
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700183 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
184
185 SkFont* skFont = &paint->getSkFont();
186 // We don't use populateSkFont since it is designed to be used for layout result with addressing
187 // auto fake-bolding.
188 skFont->setTypeface(minikinSkia->RefSkTypeface());
189
190 SkFontMetrics metrics;
191 SkScalar spacing = skFont->getMetrics(&metrics);
192 GraphicsJNI::set_metrics(env, metricsObj, metrics);
193 return spacing;
194}
195
Seigo Nonakaf3a19152020-09-14 15:29:42 -0700196// Critical Native
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800197static jlong Font_getMinikinFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
198 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000199 return reinterpret_cast<jlong>(font->font.get());
Seigo Nonaka760d3512020-10-01 12:29:03 -0700200}
201
Seigo Nonaka31bf8602020-10-14 15:04:01 -0700202// Critical Native
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800203static jlong Font_cloneFont(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
204 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
205 std::shared_ptr<minikin::Font> ref = font->font;
206 return reinterpret_cast<jlong>(new FontWrapper(std::move(ref)));
Seigo Nonakaf3a19152020-09-14 15:29:42 -0700207}
208
209// Fast Native
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800210static jobject Font_newByteBuffer(JNIEnv* env, jobject, jlong fontPtr) {
211 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
Seigo Nonaka032aac92023-05-26 10:15:53 +0900212 const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->baseTypeface();
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800213 return env->NewDirectByteBuffer(const_cast<void*>(minikinFont->GetFontData()),
214 minikinFont->GetFontSize());
Seigo Nonakaf3a19152020-09-14 15:29:42 -0700215}
216
217// Critical Native
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800218static jlong Font_getBufferAddress(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
219 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
Seigo Nonaka032aac92023-05-26 10:15:53 +0900220 return reinterpret_cast<jlong>(font->font->baseTypeface()->GetFontData());
Seigo Nonakaf3a19152020-09-14 15:29:42 -0700221}
222
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800223// Critical Native
Jerome Gaillardb71861c2021-02-09 13:10:49 +0000224static jlong Font_getReleaseNativeFontFunc(CRITICAL_JNI_PARAMS) {
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800225 return reinterpret_cast<jlong>(releaseFont);
226}
227
228// Fast Native
229static jstring Font_getFontPath(JNIEnv* env, jobject, jlong fontPtr) {
230 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000231 minikin::BufferReader reader = font->font->typefaceMetadataReader();
Kohsuke Yatoh711a1202022-07-29 00:46:39 +0000232 if (reader.current() != nullptr) {
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000233 std::string path = std::string(reader.readString());
234 if (path.empty()) {
235 return nullptr;
236 }
237 return env->NewStringUTF(path.c_str());
238 } else {
Seigo Nonaka032aac92023-05-26 10:15:53 +0900239 const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->baseTypeface();
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000240 const std::string& path = minikinFont->GetFontPath();
241 if (path.empty()) {
242 return nullptr;
243 }
244 return env->NewStringUTF(path.c_str());
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800245 }
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800246}
247
248// Fast Native
249static jstring Font_getLocaleList(JNIEnv* env, jobject, jlong fontPtr) {
250 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
251 uint32_t localeListId = font->font->getLocaleListId();
252 if (localeListId == 0) {
253 return nullptr;
254 }
255 std::string langTags = minikin::getLocaleString(localeListId);
256 if (langTags.empty()) {
257 return nullptr;
258 }
259 return env->NewStringUTF(langTags.c_str());
260}
261
262// Critical Native
263static jint Font_getPackedStyle(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
264 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
265 uint32_t weight = font->font->style().weight();
266 uint32_t isItalic = font->font->style().slant() == minikin::FontStyle::Slant::ITALIC ? 1 : 0;
267 return (isItalic << 16) | weight;
268}
269
270// Critical Native
271static jint Font_getIndex(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
272 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000273 minikin::BufferReader reader = font->font->typefaceMetadataReader();
Kohsuke Yatoh711a1202022-07-29 00:46:39 +0000274 if (reader.current() != nullptr) {
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000275 reader.skipString(); // fontPath
276 return reader.read<int>();
277 } else {
Seigo Nonaka032aac92023-05-26 10:15:53 +0900278 const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->baseTypeface();
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000279 return minikinFont->GetFontIndex();
280 }
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800281}
282
283// Critical Native
284static jint Font_getAxisCount(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
285 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000286 minikin::BufferReader reader = font->font->typefaceMetadataReader();
Kohsuke Yatoh711a1202022-07-29 00:46:39 +0000287 if (reader.current() != nullptr) {
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000288 reader.skipString(); // fontPath
289 reader.skip<int>(); // fontIndex
290 return reader.readArray<minikin::FontVariation>().second;
291 } else {
Seigo Nonaka032aac92023-05-26 10:15:53 +0900292 const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->baseTypeface();
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000293 return minikinFont->GetAxes().size();
294 }
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800295}
296
297// Critical Native
298static jlong Font_getAxisInfo(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr, jint index) {
299 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000300 minikin::BufferReader reader = font->font->typefaceMetadataReader();
301 minikin::FontVariation var;
Kohsuke Yatoh711a1202022-07-29 00:46:39 +0000302 if (reader.current() != nullptr) {
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000303 reader.skipString(); // fontPath
304 reader.skip<int>(); // fontIndex
305 var = reader.readArray<minikin::FontVariation>().first[index];
306 } else {
Seigo Nonaka032aac92023-05-26 10:15:53 +0900307 const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->baseTypeface();
Kohsuke Yatoha3f5f222021-06-09 20:09:49 +0000308 var = minikinFont->GetAxes().at(index);
309 }
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800310 uint32_t floatBinary = *reinterpret_cast<const uint32_t*>(&var.value);
311 return (static_cast<uint64_t>(var.axisTag) << 32) | static_cast<uint64_t>(floatBinary);
312}
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700313
Seigo Nonaka5dd6dd52021-02-11 20:02:27 -0800314// Critical Native
315static jint Font_getSourceId(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
316 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
Seigo Nonaka032aac92023-05-26 10:15:53 +0900317 return font->font->baseTypeface()->GetSourceId();
Seigo Nonaka5dd6dd52021-02-11 20:02:27 -0800318}
319
Seigo Nonakad5ecaba2021-05-27 15:49:37 -0700320static jlongArray Font_getAvailableFontSet(JNIEnv* env, jobject) {
321 std::vector<jlong> refArray;
322 minikin::SystemFonts::getFontSet(
323 [&refArray](const std::vector<std::shared_ptr<minikin::Font>>& fontSet) {
324 refArray.reserve(fontSet.size());
325 for (const auto& font : fontSet) {
326 std::shared_ptr<minikin::Font> fontRef = font;
327 refArray.push_back(
328 reinterpret_cast<jlong>(new FontWrapper(std::move(fontRef))));
329 }
330 });
331 jlongArray r = env->NewLongArray(refArray.size());
332 env->SetLongArrayRegion(r, 0, refArray.size(), refArray.data());
333 return r;
334}
335
Seigo Nonaka47b6c1b2021-01-13 15:02:47 -0800336// Fast Native
337static jlong FontFileUtil_getFontRevision(JNIEnv* env, jobject, jobject buffer, jint index) {
338 NPE_CHECK_RETURN_ZERO(env, buffer);
339 const void* fontPtr = env->GetDirectBufferAddress(buffer);
340 if (fontPtr == nullptr) {
341 jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
342 return 0;
343 }
344 jlong fontSize = env->GetDirectBufferCapacity(buffer);
345 if (fontSize <= 0) {
346 jniThrowException(env, "java/lang/IllegalArgumentException",
347 "buffer size must not be zero or negative");
348 return 0;
349 }
350 minikin::FontFileParser parser(fontPtr, fontSize, index);
351 std::optional<uint32_t> revision = parser.getFontRevision();
352 if (!revision.has_value()) {
353 return -1L;
354 }
355 return revision.value();
356}
357
358static jstring FontFileUtil_getFontPostScriptName(JNIEnv* env, jobject, jobject buffer,
359 jint index) {
360 NPE_CHECK_RETURN_ZERO(env, buffer);
361 const void* fontPtr = env->GetDirectBufferAddress(buffer);
362 if (fontPtr == nullptr) {
363 jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
364 return nullptr;
365 }
366 jlong fontSize = env->GetDirectBufferCapacity(buffer);
367 if (fontSize <= 0) {
368 jniThrowException(env, "java/lang/IllegalArgumentException",
369 "buffer size must not be zero or negative");
370 return nullptr;
371 }
372 minikin::FontFileParser parser(fontPtr, fontSize, index);
373 std::optional<std::string> psName = parser.getPostScriptName();
374 if (!psName.has_value()) {
375 return nullptr; // null
376 }
377 return env->NewStringUTF(psName->c_str());
378}
Seigo Nonaka9d5ab7e2021-01-20 22:50:09 -0800379
380static jint FontFileUtil_isPostScriptType1Font(JNIEnv* env, jobject, jobject buffer, jint index) {
381 NPE_CHECK_RETURN_ZERO(env, buffer);
382 const void* fontPtr = env->GetDirectBufferAddress(buffer);
383 if (fontPtr == nullptr) {
384 jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
385 return -1;
386 }
387 jlong fontSize = env->GetDirectBufferCapacity(buffer);
388 if (fontSize <= 0) {
389 jniThrowException(env, "java/lang/IllegalArgumentException",
390 "buffer size must not be zero or negative");
391 return -1;
392 }
393 minikin::FontFileParser parser(fontPtr, fontSize, index);
394 std::optional<bool> isType1 = parser.isPostScriptType1Font();
395 if (!isType1.has_value()) {
396 return -1; // not an OpenType font. HarfBuzz failed to parse it.
397 }
398 return isType1.value();
399}
400
Seigo Nonaka47b6c1b2021-01-13 15:02:47 -0800401///////////////////////////////////////////////////////////////////////////////
402
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700403static const JNINativeMethod gFontBuilderMethods[] = {
Seigo Nonaka99c07562021-02-03 21:37:57 -0800404 {"nInitBuilder", "()J", (void*)Font_Builder_initBuilder},
405 {"nAddAxis", "(JIF)V", (void*)Font_Builder_addAxis},
406 {"nBuild", "(JLjava/nio/ByteBuffer;Ljava/lang/String;Ljava/lang/String;IZI)J",
407 (void*)Font_Builder_build},
408 {"nClone", "(JJIZI)J", (void*)Font_Builder_clone},
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700409};
410
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700411static const JNINativeMethod gFontMethods[] = {
Seigo Nonaka1dd39f32021-02-05 19:15:29 -0800412 {"nGetMinikinFontPtr", "(J)J", (void*)Font_getMinikinFontPtr},
413 {"nCloneFont", "(J)J", (void*)Font_cloneFont},
414 {"nNewByteBuffer", "(J)Ljava/nio/ByteBuffer;", (void*)Font_newByteBuffer},
415 {"nGetBufferAddress", "(J)J", (void*)Font_getBufferAddress},
416 {"nGetReleaseNativeFont", "()J", (void*)Font_getReleaseNativeFontFunc},
417 {"nGetGlyphBounds", "(JIJLandroid/graphics/RectF;)F", (void*)Font_getGlyphBounds},
418 {"nGetFontMetrics", "(JJLandroid/graphics/Paint$FontMetrics;)F",
419 (void*)Font_getFontMetrics},
420 {"nGetFontPath", "(J)Ljava/lang/String;", (void*)Font_getFontPath},
421 {"nGetLocaleList", "(J)Ljava/lang/String;", (void*)Font_getLocaleList},
422 {"nGetPackedStyle", "(J)I", (void*)Font_getPackedStyle},
423 {"nGetIndex", "(J)I", (void*)Font_getIndex},
424 {"nGetAxisCount", "(J)I", (void*)Font_getAxisCount},
425 {"nGetAxisInfo", "(JI)J", (void*)Font_getAxisInfo},
Seigo Nonaka5dd6dd52021-02-11 20:02:27 -0800426 {"nGetSourceId", "(J)I", (void*)Font_getSourceId},
Seigo Nonakad5ecaba2021-05-27 15:49:37 -0700427
428 // System font accessors
429 {"nGetAvailableFontSet", "()[J", (void*)Font_getAvailableFontSet},
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700430};
431
Seigo Nonaka47b6c1b2021-01-13 15:02:47 -0800432static const JNINativeMethod gFontFileUtilMethods[] = {
433 { "nGetFontRevision", "(Ljava/nio/ByteBuffer;I)J", (void*) FontFileUtil_getFontRevision },
434 { "nGetFontPostScriptName", "(Ljava/nio/ByteBuffer;I)Ljava/lang/String;",
435 (void*) FontFileUtil_getFontPostScriptName },
Seigo Nonaka9d5ab7e2021-01-20 22:50:09 -0800436 { "nIsPostScriptType1Font", "(Ljava/nio/ByteBuffer;I)I",
437 (void*) FontFileUtil_isPostScriptType1Font },
Seigo Nonaka47b6c1b2021-01-13 15:02:47 -0800438};
439
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700440int register_android_graphics_fonts_Font(JNIEnv* env) {
441 return RegisterMethodsOrDie(env, "android/graphics/fonts/Font$Builder", gFontBuilderMethods,
Seigo Nonaka1ed4f642020-09-10 17:19:34 -0700442 NELEM(gFontBuilderMethods)) +
443 RegisterMethodsOrDie(env, "android/graphics/fonts/Font", gFontMethods,
Seigo Nonakaf3a19152020-09-14 15:29:42 -0700444 NELEM(gFontMethods)) +
Seigo Nonaka47b6c1b2021-01-13 15:02:47 -0800445 RegisterMethodsOrDie(env, "android/graphics/fonts/FontFileUtil", gFontFileUtilMethods,
446 NELEM(gFontFileUtilMethods));
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700447}
448
Kohsuke Yatoh1ca390e2020-11-06 16:21:30 -0800449namespace fonts {
450
451std::shared_ptr<minikin::MinikinFont> createMinikinFontSkia(
452 sk_sp<SkData>&& data, std::string_view fontPath, const void *fontPtr, size_t fontSize,
453 int ttcIndex, const std::vector<minikin::FontVariation>& axes) {
454 FatVector<SkFontArguments::VariationPosition::Coordinate, 2> skVariation;
455 for (const auto& axis : axes) {
456 skVariation.push_back({axis.axisTag, axis.value});
457 }
458
459 std::unique_ptr<SkStreamAsset> fontData(new SkMemoryStream(std::move(data)));
460
461 SkFontArguments args;
462 args.setCollectionIndex(ttcIndex);
463 args.setVariationDesignPosition({skVariation.data(), static_cast<int>(skVariation.size())});
464
465 sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
466 sk_sp<SkTypeface> face(fm->makeFromStream(std::move(fontData), args));
467 if (face == nullptr) {
468 return nullptr;
469 }
Seigo Nonaka5dd6dd52021-02-11 20:02:27 -0800470 return std::make_shared<MinikinFontSkia>(std::move(face), getNewSourceId(), fontPtr, fontSize,
Kohsuke Yatoh1ca390e2020-11-06 16:21:30 -0800471 fontPath, ttcIndex, axes);
Seigo Nonakaa1c21c02018-07-20 15:57:39 -0700472}
Kohsuke Yatoh1ca390e2020-11-06 16:21:30 -0800473
Seigo Nonaka5dd6dd52021-02-11 20:02:27 -0800474int getNewSourceId() {
475 static std::atomic<int> sSourceId = {0};
476 return sSourceId++;
477}
478
Kohsuke Yatoh1ca390e2020-11-06 16:21:30 -0800479} // namespace fonts
480
481} // namespace android