explicit SkFontStyleSet_Android(const FontFamily& family, const SkTypeface_FreeType::Scanner& scanner) { const SkString* cannonicalFamilyName = NULL; if (family.fNames.count() > 0) { cannonicalFamilyName = &family.fNames[0]; } // TODO? make this lazy for (int i = 0; i < family.fFonts.count(); ++i) { const FontFileInfo& fontFile = family.fFonts[i]; SkString pathName(family.fBasePath); pathName.append(fontFile.fFileName); SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(pathName.c_str())); if (!stream.get()) { SkDEBUGF(("Requested font file %s does not exist or cannot be opened.\n", pathName.c_str())); continue; } const int ttcIndex = fontFile.fIndex; SkString familyName; SkFontStyle style; bool isFixedWidth; if (!scanner.scanFont(stream.get(), ttcIndex, &familyName, &style, &isFixedWidth)) { SkDEBUGF(("Requested font file %s exists, but is not a valid font.\n", pathName.c_str())); continue; } int weight = fontFile.fWeight != 0 ? fontFile.fWeight : style.weight(); SkFontStyle::Slant slant = style.slant(); switch (fontFile.fStyle) { case FontFileInfo::Style::kAuto: slant = style.slant(); break; case FontFileInfo::Style::kNormal: slant = SkFontStyle::kUpright_Slant; break; case FontFileInfo::Style::kItalic: slant = SkFontStyle::kItalic_Slant; break; default: SkASSERT(false); break; } style = SkFontStyle(weight, style.width(), slant); const SkLanguage& lang = family.fLanguage; uint32_t variant = family.fVariant; if (kDefault_FontVariant == variant) { variant = kCompact_FontVariant | kElegant_FontVariant; } // The first specified family name overrides the family name found in the font. // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return // all of the specified family names in addition to the names found in the font. if (cannonicalFamilyName != NULL) { familyName = *cannonicalFamilyName; } fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem, (pathName, ttcIndex, style, isFixedWidth, familyName, lang, variant))); } }
static void load_embedded_font(const SkTypeface_FreeType::Scanner& scanner, const uint8_t* data, size_t size, int index, SkFontMgr_Custom::Families* families) { auto stream = skstd::make_unique<SkMemoryStream>(data, size, false); int numFaces; if (!scanner.recognizedFont(stream.get(), &numFaces)) { SkDebugf("---- failed to open <%d> as a font\n", index); return; } for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { bool isFixedPitch; SkString realname; SkFontStyle style = SkFontStyle(); // avoid uninitialized warning if (!scanner.scanFont(stream.get(), faceIndex, &realname, &style, &isFixedPitch, nullptr)) { SkDebugf("---- failed to open <%d> <%d> as a font\n", index, faceIndex); return; } SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str()); if (nullptr == addTo) { addTo = new SkFontStyleSet_Custom(realname); families->push_back().reset(addTo); } auto data = skstd::make_unique<SkFontData>(std::move(stream), faceIndex, nullptr, 0); addTo->appendTypeface(sk_make_sp<SkTypeface_Stream>(std::move(data), style, isFixedPitch, true, realname)); } }
static void load_embedded_font(const SkTypeface_FreeType::Scanner& scanner, const uint8_t* data, size_t size, int index, SkFontMgr_Custom::Families* families) { SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(data, size, false)); int numFaces; if (!scanner.recognizedFont(stream, &numFaces)) { SkDebugf("---- failed to open <%d> as a font\n", index); return; } for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { bool isFixedPitch; SkString realname; SkFontStyle style = SkFontStyle(); // avoid uninitialized warning if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch, nullptr)) { SkDebugf("---- failed to open <%d> <%d> as a font\n", index, faceIndex); return; } SkTypeface_Custom* tf = new SkTypeface_Stream(style, isFixedPitch, true, // system-font (cannot delete) realname, stream.release(), faceIndex); SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str()); if (nullptr == addTo) { addTo = new SkFontStyleSet_Custom(realname); families->push_back().reset(addTo); } addTo->appendTypeface(tf); } }
sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream, const SkFontArguments& args) const override { using Scanner = SkTypeface_FreeType::Scanner; const size_t length = stream->getLength(); if (!length) { return nullptr; } if (length >= 1024 * 1024 * 1024) { return nullptr; // don't accept too large fonts (>= 1GB) for safety. } bool isFixedPitch; SkFontStyle style; SkString name; Scanner::AxisDefinitions axisDefinitions; if (!fScanner.scanFont(stream.get(), args.getCollectionIndex(), &name, &style, &isFixedPitch, &axisDefinitions)) { return nullptr; } SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count()); Scanner::computeAxisValues(axisDefinitions, args.getVariationDesignPosition(), axisValues, name); auto fontData = skstd::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(), axisValues.get(), axisDefinitions.count()); return sk_sp<SkTypeface>(SkTypeface_FCI::Create(std::move(fontData), std::move(name), style, isFixedPitch)); }
static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner, const SkString& directory, const char* suffix, SkFontMgr_Custom::Families* families) { SkOSFile::Iter iter(directory.c_str(), suffix); SkString name; while (iter.next(&name, false)) { SkString filename(SkOSPath::Join(directory.c_str(), name.c_str())); SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(filename.c_str())); if (!stream.get()) { SkDebugf("---- failed to open <%s>\n", filename.c_str()); continue; } int numFaces; if (!scanner.recognizedFont(stream, &numFaces)) { SkDebugf("---- failed to open <%s> as a font\n", filename.c_str()); continue; } for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { bool isFixedPitch; SkString realname; SkFontStyle style = SkFontStyle(); // avoid uninitialized warning if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch, NULL)) { SkDebugf("---- failed to open <%s> <%d> as a font\n", filename.c_str(), faceIndex); continue; } SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, ( style, isFixedPitch, true, // system-font (cannot delete) realname, filename.c_str(), faceIndex)); SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str()); if (NULL == addTo) { addTo = new SkFontStyleSet_Custom(realname); families->push_back().reset(addTo); } addTo->appendTypeface(tf); } } SkOSFile::Iter dirIter(directory.c_str()); while (dirIter.next(&name, true)) { if (name.startsWith(".")) { continue; } SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str())); load_directory_fonts(scanner, dirname, suffix, families); } }
SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override { SkAutoTDelete<SkStreamAsset> stream(bareStream); const size_t length = stream->getLength(); if (!length) { return nullptr; } if (length >= 1024 * 1024 * 1024) { return nullptr; // don't accept too large fonts (>= 1GB) for safety. } // TODO should the caller give us the style or should we get it from freetype? SkFontStyle style; bool isFixedWidth = false; if (!fScanner.scanFont(stream, 0, nullptr, &style, &isFixedWidth, nullptr)) { return nullptr; } return SkTypeface_FCI::Create(style, isFixedWidth, stream.release(), ttcIndex); }
sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream, int ttcIndex) const override { const size_t length = stream->getLength(); if (!length) { return nullptr; } if (length >= 1024 * 1024 * 1024) { return nullptr; // don't accept too large fonts (>= 1GB) for safety. } // TODO should the caller give us the style or should we get it from freetype? SkString name; SkFontStyle style; bool isFixedPitch = false; if (!fScanner.scanFont(stream.get(), 0, &name, &style, &isFixedPitch, nullptr)) { return nullptr; } auto fontData = skstd::make_unique<SkFontData>(std::move(stream), ttcIndex, nullptr, 0); return sk_sp<SkTypeface>(SkTypeface_FCI::Create(std::move(fontData), std::move(name), style, isFixedPitch)); }