1 /*
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
17 #include "Font.h"
18 #include "SkData.h"
19 #include "SkFont.h"
20 #include "SkFontMetrics.h"
21 #include "SkFontMgr.h"
22 #include "SkRect.h"
23 #include "SkRefCnt.h"
24 #include "SkScalar.h"
25 #include "SkStream.h"
26 #include "SkTypeface.h"
27 #include "GraphicsJNI.h"
28 #include <nativehelper/ScopedUtfChars.h>
29 #include "Utils.h"
30 #include "FontUtils.h"
31
32 #include <hwui/MinikinSkia.h>
33 #include <hwui/Paint.h>
34 #include <hwui/Typeface.h>
35 #include <minikin/FontFamily.h>
36 #include <minikin/FontFileParser.h>
37 #include <minikin/LocaleList.h>
38 #include <minikin/SystemFonts.h>
39 #include <ui/FatVector.h>
40 #include <utils/TypefaceUtils.h>
41
42 #include <memory>
43
44 namespace android {
45
46 struct NativeFontBuilder {
47 std::vector<minikin::FontVariation> axes;
48 };
49
toBuilder(jlong ptr)50 static inline NativeFontBuilder* toBuilder(jlong ptr) {
51 return reinterpret_cast<NativeFontBuilder*>(ptr);
52 }
53
releaseFont(jlong font)54 static void releaseFont(jlong font) {
55 delete reinterpret_cast<FontWrapper*>(font);
56 }
57
release_global_ref(const void *,void * context)58 static void release_global_ref(const void* /*data*/, void* context) {
59 JNIEnv* env = GraphicsJNI::getJNIEnv();
60 bool needToAttach = (env == nullptr);
61 if (needToAttach) {
62 env = GraphicsJNI::attachJNIEnv("release_font_data");
63 if (env == nullptr) {
64 ALOGE("failed to attach to thread to release global ref.");
65 return;
66 }
67 }
68
69 jobject obj = reinterpret_cast<jobject>(context);
70 env->DeleteGlobalRef(obj);
71 }
72
73 // Regular JNI
Font_Builder_initBuilder(JNIEnv *,jobject)74 static jlong Font_Builder_initBuilder(JNIEnv*, jobject) {
75 return reinterpret_cast<jlong>(new NativeFontBuilder());
76 }
77
78 // Critical Native
Font_Builder_addAxis(CRITICAL_JNI_PARAMS_COMMA jlong builderPtr,jint tag,jfloat value)79 static void Font_Builder_addAxis(CRITICAL_JNI_PARAMS_COMMA jlong builderPtr, jint tag, jfloat value) {
80 toBuilder(builderPtr)->axes.emplace_back(static_cast<minikin::AxisTag>(tag), value);
81 }
82
83 // Regular JNI
Font_Builder_build(JNIEnv * env,jobject clazz,jlong builderPtr,jobject buffer,jstring filePath,jstring langTags,jint weight,jboolean italic,jint ttcIndex)84 static jlong Font_Builder_build(JNIEnv* env, jobject clazz, jlong builderPtr, jobject buffer,
85 jstring filePath, jstring langTags, jint weight, jboolean italic,
86 jint ttcIndex) {
87 NPE_CHECK_RETURN_ZERO(env, buffer);
88 std::unique_ptr<NativeFontBuilder> builder(toBuilder(builderPtr));
89 const void* fontPtr = env->GetDirectBufferAddress(buffer);
90 if (fontPtr == nullptr) {
91 jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
92 return 0;
93 }
94 jlong fontSize = env->GetDirectBufferCapacity(buffer);
95 if (fontSize <= 0) {
96 jniThrowException(env, "java/lang/IllegalArgumentException",
97 "buffer size must not be zero or negative");
98 return 0;
99 }
100 ScopedUtfChars fontPath(env, filePath);
101 ScopedUtfChars langTagStr(env, langTags);
102 jobject fontRef = MakeGlobalRefOrDie(env, buffer);
103 sk_sp<SkData> data(SkData::MakeWithProc(fontPtr, fontSize,
104 release_global_ref, reinterpret_cast<void*>(fontRef)));
105 std::shared_ptr<minikin::MinikinFont> minikinFont = fonts::createMinikinFontSkia(
106 std::move(data), std::string_view(fontPath.c_str(), fontPath.size()),
107 fontPtr, fontSize, ttcIndex, builder->axes);
108 if (minikinFont == nullptr) {
109 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
110 "Failed to create internal object. maybe invalid font data. filePath %s",
111 fontPath.c_str());
112 return 0;
113 }
114 uint32_t localeListId = minikin::registerLocaleList(langTagStr.c_str());
115 std::shared_ptr<minikin::Font> font =
116 minikin::Font::Builder(minikinFont)
117 .setWeight(weight)
118 .setSlant(static_cast<minikin::FontStyle::Slant>(italic))
119 .setLocaleListId(localeListId)
120 .build();
121 return reinterpret_cast<jlong>(new FontWrapper(std::move(font)));
122 }
123
124 // Fast Native
Font_Builder_clone(JNIEnv * env,jobject clazz,jlong fontPtr,jlong builderPtr,jint weight,jboolean italic,jint ttcIndex)125 static jlong Font_Builder_clone(JNIEnv* env, jobject clazz, jlong fontPtr, jlong builderPtr,
126 jint weight, jboolean italic, jint ttcIndex) {
127 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
128 MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->baseTypeface().get());
129 std::unique_ptr<NativeFontBuilder> builder(toBuilder(builderPtr));
130
131 // Reconstruct SkTypeface with different arguments from existing SkTypeface.
132 FatVector<SkFontArguments::VariationPosition::Coordinate, 2> skVariation;
133 for (const auto& axis : builder->axes) {
134 skVariation.push_back({axis.axisTag, axis.value});
135 }
136 SkFontArguments args;
137 args.setCollectionIndex(ttcIndex);
138 args.setVariationDesignPosition({skVariation.data(), static_cast<int>(skVariation.size())});
139
140 sk_sp<SkTypeface> newTypeface = minikinSkia->GetSkTypeface()->makeClone(args);
141
142 std::shared_ptr<minikin::MinikinFont> newMinikinFont = std::make_shared<MinikinFontSkia>(
143 std::move(newTypeface), minikinSkia->GetSourceId(), minikinSkia->GetFontData(),
144 minikinSkia->GetFontSize(), minikinSkia->getFilePath(), minikinSkia->GetFontIndex(),
145 builder->axes);
146 std::shared_ptr<minikin::Font> newFont = minikin::Font::Builder(newMinikinFont)
147 .setWeight(weight)
148 .setSlant(static_cast<minikin::FontStyle::Slant>(italic))
149 .build();
150 return reinterpret_cast<jlong>(new FontWrapper(std::move(newFont)));
151 }
152
153 ///////////////////////////////////////////////////////////////////////////////
154 // Font JNI functions
155
156 // Fast Native
Font_getGlyphBounds(JNIEnv * env,jobject,jlong fontHandle,jint glyphId,jlong paintHandle,jobject rect)157 static jfloat Font_getGlyphBounds(JNIEnv* env, jobject, jlong fontHandle, jint glyphId,
158 jlong paintHandle, jobject rect) {
159 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
160 MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->baseTypeface().get());
161 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
162
163 SkFont* skFont = &paint->getSkFont();
164 // We don't use populateSkFont since it is designed to be used for layout result with addressing
165 // auto fake-bolding.
166 skFont->setTypeface(minikinSkia->RefSkTypeface());
167
168 uint16_t glyph16 = glyphId;
169 SkRect skBounds;
170 SkScalar skWidth;
171 skFont->getWidthsBounds(&glyph16, 1, &skWidth, &skBounds, nullptr);
172 GraphicsJNI::rect_to_jrectf(skBounds, env, rect);
173 return SkScalarToFloat(skWidth);
174 }
175
176 // Fast Native
Font_getFontMetrics(JNIEnv * env,jobject,jlong fontHandle,jlong paintHandle,jobject metricsObj)177 static jfloat Font_getFontMetrics(JNIEnv* env, jobject, jlong fontHandle, jlong paintHandle,
178 jobject metricsObj) {
179 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
180 MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->baseTypeface().get());
181 Paint* paint = reinterpret_cast<Paint*>(paintHandle);
182
183 SkFont* skFont = &paint->getSkFont();
184 // We don't use populateSkFont since it is designed to be used for layout result with addressing
185 // auto fake-bolding.
186 skFont->setTypeface(minikinSkia->RefSkTypeface());
187
188 SkFontMetrics metrics;
189 SkScalar spacing = skFont->getMetrics(&metrics);
190 GraphicsJNI::set_metrics(env, metricsObj, metrics);
191 return spacing;
192 }
193
194 // Critical Native
Font_getMinikinFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr)195 static jlong Font_getMinikinFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
196 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
197 return reinterpret_cast<jlong>(font->font.get());
198 }
199
200 // Critical Native
Font_cloneFont(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr)201 static jlong Font_cloneFont(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
202 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
203 std::shared_ptr<minikin::Font> ref = font->font;
204 return reinterpret_cast<jlong>(new FontWrapper(std::move(ref)));
205 }
206
207 // Fast Native
Font_newByteBuffer(JNIEnv * env,jobject,jlong fontPtr)208 static jobject Font_newByteBuffer(JNIEnv* env, jobject, jlong fontPtr) {
209 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
210 const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->baseTypeface();
211 return env->NewDirectByteBuffer(const_cast<void*>(minikinFont->GetFontData()),
212 minikinFont->GetFontSize());
213 }
214
215 // Critical Native
Font_getBufferAddress(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr)216 static jlong Font_getBufferAddress(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
217 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
218 return reinterpret_cast<jlong>(font->font->baseTypeface()->GetFontData());
219 }
220
221 // Critical Native
Font_getReleaseNativeFontFunc(CRITICAL_JNI_PARAMS)222 static jlong Font_getReleaseNativeFontFunc(CRITICAL_JNI_PARAMS) {
223 return reinterpret_cast<jlong>(releaseFont);
224 }
225
226 // Fast Native
Font_getFontPath(JNIEnv * env,jobject,jlong fontPtr)227 static jstring Font_getFontPath(JNIEnv* env, jobject, jlong fontPtr) {
228 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
229 minikin::BufferReader reader = font->font->typefaceMetadataReader();
230 if (reader.current() != nullptr) {
231 std::string path = std::string(reader.readString());
232 if (path.empty()) {
233 return nullptr;
234 }
235 return env->NewStringUTF(path.c_str());
236 } else {
237 const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->baseTypeface();
238 const std::string& path = minikinFont->GetFontPath();
239 if (path.empty()) {
240 return nullptr;
241 }
242 return env->NewStringUTF(path.c_str());
243 }
244 }
245
246 // Fast Native
Font_getLocaleList(JNIEnv * env,jobject,jlong fontPtr)247 static jstring Font_getLocaleList(JNIEnv* env, jobject, jlong fontPtr) {
248 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
249 uint32_t localeListId = font->font->getLocaleListId();
250 if (localeListId == 0) {
251 return nullptr;
252 }
253 std::string langTags = minikin::getLocaleString(localeListId);
254 if (langTags.empty()) {
255 return nullptr;
256 }
257 return env->NewStringUTF(langTags.c_str());
258 }
259
260 // Critical Native
Font_getPackedStyle(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr)261 static jint Font_getPackedStyle(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
262 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
263 uint32_t weight = font->font->style().weight();
264 uint32_t isItalic = font->font->style().slant() == minikin::FontStyle::Slant::ITALIC ? 1 : 0;
265 return (isItalic << 16) | weight;
266 }
267
268 // Critical Native
Font_getIndex(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr)269 static jint Font_getIndex(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
270 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
271 minikin::BufferReader reader = font->font->typefaceMetadataReader();
272 if (reader.current() != nullptr) {
273 reader.skipString(); // fontPath
274 return reader.read<int>();
275 } else {
276 const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->baseTypeface();
277 return minikinFont->GetFontIndex();
278 }
279 }
280
281 // Critical Native
Font_getAxisCount(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr)282 static jint Font_getAxisCount(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
283 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
284 minikin::BufferReader reader = font->font->typefaceMetadataReader();
285 if (reader.current() != nullptr) {
286 reader.skipString(); // fontPath
287 reader.skip<int>(); // fontIndex
288 return reader.readArray<minikin::FontVariation>().second;
289 } else {
290 const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->baseTypeface();
291 return minikinFont->GetAxes().size();
292 }
293 }
294
295 // Critical Native
Font_getAxisInfo(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr,jint index)296 static jlong Font_getAxisInfo(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr, jint index) {
297 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
298 minikin::BufferReader reader = font->font->typefaceMetadataReader();
299 minikin::FontVariation var;
300 if (reader.current() != nullptr) {
301 reader.skipString(); // fontPath
302 reader.skip<int>(); // fontIndex
303 var = reader.readArray<minikin::FontVariation>().first[index];
304 } else {
305 const std::shared_ptr<minikin::MinikinFont>& minikinFont = font->font->baseTypeface();
306 var = minikinFont->GetAxes().at(index);
307 }
308 uint32_t floatBinary = *reinterpret_cast<const uint32_t*>(&var.value);
309 return (static_cast<uint64_t>(var.axisTag) << 32) | static_cast<uint64_t>(floatBinary);
310 }
311
312 // Critical Native
Font_getSourceId(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr)313 static jint Font_getSourceId(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
314 FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
315 return font->font->baseTypeface()->GetSourceId();
316 }
317
Font_getAvailableFontSet(JNIEnv * env,jobject)318 static jlongArray Font_getAvailableFontSet(JNIEnv* env, jobject) {
319 std::vector<jlong> refArray;
320 minikin::SystemFonts::getFontSet(
321 [&refArray](const std::vector<std::shared_ptr<minikin::Font>>& fontSet) {
322 refArray.reserve(fontSet.size());
323 for (const auto& font : fontSet) {
324 std::shared_ptr<minikin::Font> fontRef = font;
325 refArray.push_back(
326 reinterpret_cast<jlong>(new FontWrapper(std::move(fontRef))));
327 }
328 });
329 jlongArray r = env->NewLongArray(refArray.size());
330 env->SetLongArrayRegion(r, 0, refArray.size(), refArray.data());
331 return r;
332 }
333
334 // Fast Native
FontFileUtil_getFontRevision(JNIEnv * env,jobject,jobject buffer,jint index)335 static jlong FontFileUtil_getFontRevision(JNIEnv* env, jobject, jobject buffer, jint index) {
336 NPE_CHECK_RETURN_ZERO(env, buffer);
337 const void* fontPtr = env->GetDirectBufferAddress(buffer);
338 if (fontPtr == nullptr) {
339 jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
340 return 0;
341 }
342 jlong fontSize = env->GetDirectBufferCapacity(buffer);
343 if (fontSize <= 0) {
344 jniThrowException(env, "java/lang/IllegalArgumentException",
345 "buffer size must not be zero or negative");
346 return 0;
347 }
348 minikin::FontFileParser parser(fontPtr, fontSize, index);
349 std::optional<uint32_t> revision = parser.getFontRevision();
350 if (!revision.has_value()) {
351 return -1L;
352 }
353 return revision.value();
354 }
355
FontFileUtil_getFontPostScriptName(JNIEnv * env,jobject,jobject buffer,jint index)356 static jstring FontFileUtil_getFontPostScriptName(JNIEnv* env, jobject, jobject buffer,
357 jint index) {
358 NPE_CHECK_RETURN_ZERO(env, buffer);
359 const void* fontPtr = env->GetDirectBufferAddress(buffer);
360 if (fontPtr == nullptr) {
361 jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
362 return nullptr;
363 }
364 jlong fontSize = env->GetDirectBufferCapacity(buffer);
365 if (fontSize <= 0) {
366 jniThrowException(env, "java/lang/IllegalArgumentException",
367 "buffer size must not be zero or negative");
368 return nullptr;
369 }
370 minikin::FontFileParser parser(fontPtr, fontSize, index);
371 std::optional<std::string> psName = parser.getPostScriptName();
372 if (!psName.has_value()) {
373 return nullptr; // null
374 }
375 return env->NewStringUTF(psName->c_str());
376 }
377
FontFileUtil_isPostScriptType1Font(JNIEnv * env,jobject,jobject buffer,jint index)378 static jint FontFileUtil_isPostScriptType1Font(JNIEnv* env, jobject, jobject buffer, jint index) {
379 NPE_CHECK_RETURN_ZERO(env, buffer);
380 const void* fontPtr = env->GetDirectBufferAddress(buffer);
381 if (fontPtr == nullptr) {
382 jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
383 return -1;
384 }
385 jlong fontSize = env->GetDirectBufferCapacity(buffer);
386 if (fontSize <= 0) {
387 jniThrowException(env, "java/lang/IllegalArgumentException",
388 "buffer size must not be zero or negative");
389 return -1;
390 }
391 minikin::FontFileParser parser(fontPtr, fontSize, index);
392 std::optional<bool> isType1 = parser.isPostScriptType1Font();
393 if (!isType1.has_value()) {
394 return -1; // not an OpenType font. HarfBuzz failed to parse it.
395 }
396 return isType1.value();
397 }
398
399 ///////////////////////////////////////////////////////////////////////////////
400
401 static const JNINativeMethod gFontBuilderMethods[] = {
402 {"nInitBuilder", "()J", (void*)Font_Builder_initBuilder},
403 {"nAddAxis", "(JIF)V", (void*)Font_Builder_addAxis},
404 {"nBuild", "(JLjava/nio/ByteBuffer;Ljava/lang/String;Ljava/lang/String;IZI)J",
405 (void*)Font_Builder_build},
406 {"nClone", "(JJIZI)J", (void*)Font_Builder_clone},
407 };
408
409 static const JNINativeMethod gFontMethods[] = {
410 {"nGetMinikinFontPtr", "(J)J", (void*)Font_getMinikinFontPtr},
411 {"nCloneFont", "(J)J", (void*)Font_cloneFont},
412 {"nNewByteBuffer", "(J)Ljava/nio/ByteBuffer;", (void*)Font_newByteBuffer},
413 {"nGetBufferAddress", "(J)J", (void*)Font_getBufferAddress},
414 {"nGetReleaseNativeFont", "()J", (void*)Font_getReleaseNativeFontFunc},
415 {"nGetGlyphBounds", "(JIJLandroid/graphics/RectF;)F", (void*)Font_getGlyphBounds},
416 {"nGetFontMetrics", "(JJLandroid/graphics/Paint$FontMetrics;)F",
417 (void*)Font_getFontMetrics},
418 {"nGetFontPath", "(J)Ljava/lang/String;", (void*)Font_getFontPath},
419 {"nGetLocaleList", "(J)Ljava/lang/String;", (void*)Font_getLocaleList},
420 {"nGetPackedStyle", "(J)I", (void*)Font_getPackedStyle},
421 {"nGetIndex", "(J)I", (void*)Font_getIndex},
422 {"nGetAxisCount", "(J)I", (void*)Font_getAxisCount},
423 {"nGetAxisInfo", "(JI)J", (void*)Font_getAxisInfo},
424 {"nGetSourceId", "(J)I", (void*)Font_getSourceId},
425
426 // System font accessors
427 {"nGetAvailableFontSet", "()[J", (void*)Font_getAvailableFontSet},
428 };
429
430 static const JNINativeMethod gFontFileUtilMethods[] = {
431 { "nGetFontRevision", "(Ljava/nio/ByteBuffer;I)J", (void*) FontFileUtil_getFontRevision },
432 { "nGetFontPostScriptName", "(Ljava/nio/ByteBuffer;I)Ljava/lang/String;",
433 (void*) FontFileUtil_getFontPostScriptName },
434 { "nIsPostScriptType1Font", "(Ljava/nio/ByteBuffer;I)I",
435 (void*) FontFileUtil_isPostScriptType1Font },
436 };
437
register_android_graphics_fonts_Font(JNIEnv * env)438 int register_android_graphics_fonts_Font(JNIEnv* env) {
439 return RegisterMethodsOrDie(env, "android/graphics/fonts/Font$Builder", gFontBuilderMethods,
440 NELEM(gFontBuilderMethods)) +
441 RegisterMethodsOrDie(env, "android/graphics/fonts/Font", gFontMethods,
442 NELEM(gFontMethods)) +
443 RegisterMethodsOrDie(env, "android/graphics/fonts/FontFileUtil", gFontFileUtilMethods,
444 NELEM(gFontFileUtilMethods));
445 }
446
447 namespace fonts {
448
createMinikinFontSkia(sk_sp<SkData> && data,std::string_view fontPath,const void * fontPtr,size_t fontSize,int ttcIndex,const std::vector<minikin::FontVariation> & axes)449 std::shared_ptr<minikin::MinikinFont> createMinikinFontSkia(
450 sk_sp<SkData>&& data, std::string_view fontPath, const void *fontPtr, size_t fontSize,
451 int ttcIndex, const std::vector<minikin::FontVariation>& axes) {
452 FatVector<SkFontArguments::VariationPosition::Coordinate, 2> skVariation;
453 for (const auto& axis : axes) {
454 skVariation.push_back({axis.axisTag, axis.value});
455 }
456
457 std::unique_ptr<SkStreamAsset> fontData(new SkMemoryStream(std::move(data)));
458
459 SkFontArguments args;
460 args.setCollectionIndex(ttcIndex);
461 args.setVariationDesignPosition({skVariation.data(), static_cast<int>(skVariation.size())});
462
463 sk_sp<SkFontMgr> fm = android::FreeTypeFontMgr();
464 sk_sp<SkTypeface> face(fm->makeFromStream(std::move(fontData), args));
465 if (face == nullptr) {
466 return nullptr;
467 }
468 return std::make_shared<MinikinFontSkia>(std::move(face), getNewSourceId(), fontPtr, fontSize,
469 fontPath, ttcIndex, axes);
470 }
471
getNewSourceId()472 int getNewSourceId() {
473 static std::atomic<int> sSourceId = {0};
474 return sSourceId++;
475 }
476
477 } // namespace fonts
478
479 } // namespace android
480