Flutter Engine
The Flutter Engine
SkPDFSubsetFont.cpp
Go to the documentation of this file.
1// Copyright 2018 Google LLC.
2// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
3
5
6#if defined(SK_PDF_USE_HARFBUZZ_SUBSET)
7
16
17#include "hb.h" // NO_G3_REWRITE
18#include "hb-subset.h" // NO_G3_REWRITE
19
20#include <cstddef>
21#include <memory>
22#include <utility>
23
24namespace {
25
26using HBBlob = std::unique_ptr<hb_blob_t, SkFunctionObject<hb_blob_destroy>>;
27using HBFace = std::unique_ptr<hb_face_t, SkFunctionObject<hb_face_destroy>>;
28using HBSubsetInput = std::unique_ptr<hb_subset_input_t, SkFunctionObject<hb_subset_input_destroy>>;
29using HBSet = std::unique_ptr<hb_set_t, SkFunctionObject<hb_set_destroy>>;
30
31HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
32 size_t size = asset->getLength();
33 HBBlob blob;
34 if (const void* base = asset->getMemoryBase()) {
35 blob.reset(hb_blob_create(const_cast<char*>(static_cast<const char*>(base)), SkToUInt(size),
36 HB_MEMORY_MODE_READONLY, asset.release(),
37 [](void* p) { delete (SkStreamAsset*)p; }));
38 } else {
39 void* ptr = size ? sk_malloc_throw(size) : nullptr;
40 asset->read(ptr, size);
41 blob.reset(hb_blob_create((char*)ptr, SkToUInt(size),
42 HB_MEMORY_MODE_READONLY, ptr, sk_free));
43 }
44 SkASSERT(blob);
45 hb_blob_make_immutable(blob.get());
46 return blob;
47}
48
49sk_sp<SkData> to_data(HBBlob blob) {
50 if (!blob) {
51 return nullptr;
52 }
53 unsigned int length;
54 const char* data = hb_blob_get_data(blob.get(), &length);
55 if (!data || !length) {
56 return nullptr;
57 }
59 [](const void*, void* ctx) { hb_blob_destroy((hb_blob_t*)ctx); },
60 blob.release());
61}
62
63HBFace make_subset(hb_subset_input_t* input, hb_face_t* face, bool retainZeroGlyph) {
64 // TODO: When possible, check if a font is 'tricky' with FT_IS_TRICKY.
65 // If it isn't known if a font is 'tricky', retain the hints.
66 unsigned int flags = HB_SUBSET_FLAGS_RETAIN_GIDS;
67 if (retainZeroGlyph) {
68 flags |= HB_SUBSET_FLAGS_NOTDEF_OUTLINE;
69 }
70 hb_subset_input_set_flags(input, flags);
71 return HBFace(hb_subset_or_fail(face, input));
72}
73
74sk_sp<SkData> subset_harfbuzz(const SkTypeface& typeface, const SkPDFGlyphUse& glyphUsage) {
75 int index = 0;
76 std::unique_ptr<SkStreamAsset> typefaceAsset = typeface.openStream(&index);
77 HBFace face;
78 HBBlob blob(stream_to_blob(std::move(typefaceAsset)));
79 // hb_face_create always succeeds. Check that the format is minimally recognized first.
80 // See https://github.com/harfbuzz/harfbuzz/issues/248
81 unsigned int num_hb_faces = hb_face_count(blob.get());
82 if (0 < num_hb_faces && (unsigned)index < num_hb_faces) {
83 face.reset(hb_face_create(blob.get(), (unsigned)index));
84 // Check the number of glyphs as a basic sanitization step.
85 if (face && hb_face_get_glyph_count(face.get()) == 0) {
86 face.reset();
87 }
88 }
89
90 HBSubsetInput input(hb_subset_input_create_or_fail());
91 SkASSERT(input);
92 if (!face || !input) {
93 return nullptr;
94 }
95 hb_set_t* glyphs = hb_subset_input_glyph_set(input.get());
96 glyphUsage.getSetValues([&glyphs](unsigned gid) { hb_set_add(glyphs, gid);});
97
98 HBFace subset = make_subset(input.get(), face.get(), glyphUsage.has(0));
99 if (!subset) {
100 return nullptr;
101 }
102 HBBlob result(hb_face_reference_blob(subset.get()));
103 return to_data(std::move(result));
104}
105
106} // namespace
107
108sk_sp<SkData> SkPDFSubsetFont(const SkTypeface& typeface, const SkPDFGlyphUse& glyphUsage) {
109 return subset_harfbuzz(typeface, glyphUsage);
110}
111
112#else
113
115 return nullptr;
116}
117
118#endif // defined(SK_PDF_USE_HARFBUZZ_SUBSET)
uint16_t glyphs[5]
Definition: FontMgrTest.cpp:46
#define SkASSERT(cond)
Definition: SkAssert.h:116
SK_API void sk_free(void *)
static void * sk_malloc_throw(size_t size)
Definition: SkMalloc.h:67
sk_sp< SkData > SkPDFSubsetFont(const SkTypeface &, const SkPDFGlyphUse &)
constexpr size_t SkToSizeT(S x)
Definition: SkTo.h:31
constexpr unsigned SkToUInt(S x)
Definition: SkTo.h:30
static sk_sp< SkData > MakeWithProc(const void *ptr, size_t length, ReleaseProc proc, void *ctx)
Definition: SkData.cpp:128
bool has(SkGlyphID gid) const
Definition: SkPDFGlyphUse.h:23
void getSetValues(FN f) const
Definition: SkPDFGlyphUse.h:26
std::unique_ptr< SkStreamAsset > openStream(int *ttcIndex) const
Definition: SkTypeface.cpp:332
FlutterSemanticsFlag flags
GAsyncResult * result
size_t length
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63