static void BM_FontFamily_create(benchmark::State& state) { std::shared_ptr<MinikinFontForTest> minikinFont = std::make_shared<MinikinFontForTest>("/system/fonts/NotoSansCJK-Regular.ttc", 0); while (state.KeepRunning()) { std::shared_ptr<FontFamily> family = std::make_shared<FontFamily>( std::vector<Font>({Font(minikinFont, FontStyle())})); } }
// Resolve the 1..9 weight based on base weight and bold flag static void resolveStyle(Typeface* typeface) { int weight = typeface->fBaseWeight / 100; if (typeface->fSkiaStyle & SkTypeface::kBold) { weight += 3; } if (weight > 9) { weight = 9; } bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0; typeface->fStyle = FontStyle(weight, italic); }
bool Bend::setProperty(Pid id, const QVariant& v) { switch (id) { case Pid::FONT_FACE: _fontFace = v.toString(); break; case Pid::FONT_SIZE: _fontSize = v.toReal(); break; case Pid::FONT_STYLE: _fontStyle = FontStyle(v.toInt()); break; case Pid::PLAY: setPlayBend(v.toBool()); break; case Pid::LINE_WIDTH: _lineWidth = v.toReal(); break; default: return Element::setProperty(id, v); } triggerLayout(); return true; }
void LineBreaker::addReplacement(size_t start, size_t end, float width) { mCharWidths[start] = width; std::fill(&mCharWidths[start + 1], &mCharWidths[end], 0.0f); addStyleRun(nullptr, nullptr, FontStyle(), start, end, false); }
void AnimationBuilder::parseFonts(const skjson::ObjectValue* jfonts, const skjson::ArrayValue* jchars) { // Optional array of font entries, referenced (by name) from text layer document nodes. E.g. // "fonts": { // "list": [ // { // "ascent": 75, // "fClass": "", // "fFamily": "Roboto", // "fName": "Roboto-Regular", // "fPath": "https://fonts.googleapis.com/css?family=Roboto", // "fPath": "", // "fStyle": "Regular", // "fWeight": "", // "origin": 1 // } // ] // }, if (jfonts) { if (const skjson::ArrayValue* jlist = (*jfonts)["list"]) { for (const skjson::ObjectValue* jfont : *jlist) { if (!jfont) { continue; } const skjson::StringValue* jname = (*jfont)["fName"]; const skjson::StringValue* jfamily = (*jfont)["fFamily"]; const skjson::StringValue* jstyle = (*jfont)["fStyle"]; const skjson::StringValue* jpath = (*jfont)["fPath"]; if (!jname || !jname->size() || !jfamily || !jfamily->size() || !jstyle || !jstyle->size()) { this->log(Logger::Level::kError, jfont, "Invalid font."); continue; } const auto& fmgr = fLazyFontMgr.get(); // Typeface fallback order: // 1) externally-loaded font (provided by the embedder) // 2) system font (family/style) // 3) system default sk_sp<SkTypeface> tf = fmgr->makeFromData(fResourceProvider->loadFont(jname->begin(), jpath ? jpath->begin() : nullptr)); if (!tf) { tf.reset(fmgr->matchFamilyStyle(jfamily->begin(), FontStyle(this, jstyle->begin()))); } if (!tf) { this->log(Logger::Level::kError, nullptr, "Could not create typeface for %s|%s.", jfamily->begin(), jstyle->begin()); // Last resort. tf = fmgr->legacyMakeTypeface(nullptr, FontStyle(this, jstyle->begin())); if (!tf) { continue; } } fFonts.set(SkString(jname->begin(), jname->size()), { SkString(jfamily->begin(), jfamily->size()), SkString(jstyle->begin(), jstyle->size()), ParseDefault((*jfont)["ascent"] , 0.0f), std::move(tf) }); } } } // Optional array of glyphs, to be associated with one of the declared fonts. E.g. // "chars": [ // { // "ch": "t", // "data": { // "shapes": [...] // }, // "fFamily": "Roboto", // "size": 50, // "style": "Regular", // "w": 32.67 // } // ] if (jchars) { FontInfo* current_font = nullptr; for (const skjson::ObjectValue* jchar : *jchars) { if (!jchar) { continue; } const skjson::StringValue* jch = (*jchar)["ch"]; if (!jch) { continue; } const skjson::StringValue* jfamily = (*jchar)["fFamily"]; const skjson::StringValue* jstyle = (*jchar)["style"]; // "style", not "fStyle"... const auto* ch_ptr = jch->begin(); const auto ch_len = jch->size(); if (!jfamily || !jstyle || (SkUTF::CountUTF8(ch_ptr, ch_len) != 1)) { this->log(Logger::Level::kError, jchar, "Invalid glyph."); continue; } const auto uni = SkUTF::NextUTF8(&ch_ptr, ch_ptr + ch_len); SkASSERT(uni != -1); const auto* family = jfamily->begin(); const auto* style = jstyle->begin(); // Locate (and cache) the font info. Unlike text nodes, glyphs reference the font by // (family, style) -- not by name :( For now this performs a linear search over *all* // fonts: generally there are few of them, and glyph definitions are font-clustered. // If problematic, we can refactor as a two-level hashmap. if (!current_font || !current_font->matches(family, style)) { current_font = nullptr; fFonts.foreach([&](const SkString& name, FontInfo* finfo) { if (finfo->matches(family, style)) { current_font = finfo; // TODO: would be nice to break early here... } }); if (!current_font) { this->log(Logger::Level::kError, nullptr, "Font not found for codepoint (%d, %s, %s).", uni, family, style); continue; } } // TODO: parse glyphs } } }