using HBBlob = std::unique_ptr<hb_blob_t, SkFunctionObject<hb_blob_destroy>>;
using HBFace = std::unique_ptr<hb_face_t, SkFunctionObject<hb_face_destroy>>;
using HBSubsetInput = std::unique_ptr<hb_subset_input_t, SkFunctionObject<hb_subset_input_destroy>>;
using HBSet = std::unique_ptr<hb_set_t, SkFunctionObject<hb_set_destroy>>;
HBFace stream_to_face(std::unique_ptr<SkStreamAsset> asset, int index) {
HBFace face;
HBBlob blob(stream_to_blob(std::move(asset))); // hb_face_create always succeeds. Check that the format is minimally recognized first. // See https://github.com/harfbuzz/harfbuzz/issues/248 unsignedint num_hb_faces = hb_face_count(blob.get()); if (0 < num_hb_faces && (unsigned)index < num_hb_faces) {
face.reset(hb_face_create(blob.get(), (unsigned)index)); // Check the number of glyphs as a basic sanitization step. if (face && hb_face_get_glyph_count(face.get()) == 0) {
face.reset();
}
} return face;
}
HBFace make_subset(hb_subset_input_t* input, hb_face_t* face, bool retainZeroGlyph) { // TODO: When possible, check if a font is 'tricky' with FT_IS_TRICKY. // If it isn't known if a font is 'tricky', retain the hints. unsignedint flags = HB_SUBSET_FLAGS_RETAIN_GIDS; if (retainZeroGlyph) {
flags |= HB_SUBSET_FLAGS_NOTDEF_OUTLINE;
}
hb_subset_input_set_flags(input, flags); return HBFace(hb_subset_or_fail(face, input));
}
sk_sp<SkData> subset_harfbuzz(const SkTypeface& typeface, const SkPDFGlyphUse& glyphUsage) {
HBFace face; if (!SkPDFCanSubsetTableBasedFonts()) { int index = 0;
std::unique_ptr<SkStreamAsset> typefaceAsset = typeface.openStream(&index); if (typefaceAsset) {
face = stream_to_face(std::move(typefaceAsset), index);
}
} else { int index = 0;
std::unique_ptr<SkStreamAsset> typefaceAsset = typeface.openExistingStream(&index); if (typefaceAsset && typefaceAsset->getMemoryBase()) {
face = stream_to_face(std::move(typefaceAsset), index);
} if (!face) { // Use hb_face_create_for_tables to try creating a working hb_face. // Using this creates empty subsets in HarfBuzz until 4.4.0.
face.reset(hb_face_create_for_tables(
skhb_get_table, const_cast<SkTypeface*>(SkRef(&typeface)),
[](void* user_data){ SkSafeUnref(reinterpret_cast<SkTypeface*>(user_data)); }));
hb_face_set_index(face.get(), (unsigned)index); #if HB_VERSION_ATLEAST(10, 0, 0)
hb_face_set_get_table_tags_func(
face.get(), skhb_get_table_tags_func, const_cast<SkTypeface*>(SkRef(&typeface)),
[](void* user_data){ SkSafeUnref(reinterpret_cast<SkTypeface*>(user_data)); }); #endif // Check the number of glyphs as a basic sanitization step. if (face && hb_face_get_glyph_count(face.get()) == 0) {
face.reset();
}
}
}
bool SkPDFCanSubsetTableBasedFonts() { // See https://github.com/harfbuzz/harfbuzz/issues/3609 // See https://github.com/harfbuzz/harfbuzz/issues/1697 // This file requires HarfBuzz 3.0 or later (when the public subsetter API shipped). // The default tables to search for subsetting were added in HarfBuzz 4.4.0. // The full fix (hb_face_set_get_table_tags_func) is in HarfBuzz 10.0.0. return hb_version_atleast(4, 4, 0);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.