53#include <unordered_map>
67 StrikeSpec() =
default;
69 : fTypefaceID{typefaceID}, fDiscardableHandleId(discardableHandleId) {}
79 std::unique_ptr<SkScalerContext> context,
81 ~RemoteStrike()
override =
default;
83 void lock()
override {}
84 void unlock()
override {}
86 bool prepareForImage(
SkGlyph* glyph)
override {
87 this->ensureScalerContext();
89 return glyph->
image() !=
nullptr;
91 bool prepareForPath(
SkGlyph* glyph)
override {
92 this->ensureScalerContext();
94 return glyph->
path() !=
nullptr;
96 bool prepareForDrawable(
SkGlyph* glyph)
override {
97 this->ensureScalerContext();
107 return *fDescriptor.getDesc();
113 return fRoundingSpec;
118 bool hasPendingGlyphs()
const {
119 return !fMasksToSend.empty() || !fPathsToSend.empty() || !fDrawablesToSend.empty();
122 void resetScalerContext();
125 void ensureScalerContext();
133 std::unique_ptr<SkScalerContext>
fContext;
140 bool fHaveSentFontMetrics{
false};
147 std::vector<SkGlyph> fMasksToSend;
148 std::vector<SkGlyph> fPathsToSend;
149 std::vector<SkGlyph> fDrawablesToSend;
155RemoteStrike::RemoteStrike(
157 std::unique_ptr<SkScalerContext> context,
158 uint32_t discardableHandleId)
159 : fDescriptor{strikeSpec.descriptor()}
160 , fDiscardableHandleId(discardableHandleId)
161 , fRoundingSpec{context->isSubpixel(), context->computeAxisAlignmentForHText()}
164 SkASSERT(fDescriptor.getDesc() !=
nullptr);
172 buffer.writeUInt(fDiscardableHandleId);
173 fDescriptor.getDesc()->flatten(
buffer);
175 buffer.writeBool(fHaveSentFontMetrics);
176 if (!fHaveSentFontMetrics) {
179 fContext->getFontMetrics(&fontMetrics);
181 fHaveSentFontMetrics =
true;
185 for (
SkGlyph& glyph: fMasksToSend) {
186 this->prepareForImage(&glyph);
190 for (
SkGlyph& glyph: fPathsToSend) {
191 this->prepareForPath(&glyph);
195 for (
SkGlyph& glyph: fDrawablesToSend) {
196 this->prepareForDrawable(&glyph);
203 fMasksToSend.clear();
204 fPathsToSend.clear();
205 fDrawablesToSend.clear();
209void RemoteStrike::ensureScalerContext() {
211 fContext = fStrikeSpec->createScalerContext();
215void RemoteStrike::resetScalerContext() {
217 fStrikeSpec =
nullptr;
220void RemoteStrike::setStrikeSpec(
const SkStrikeSpec& strikeSpec) {
221 fStrikeSpec = &strikeSpec;
226 if (digestPtr !=
nullptr && digestPtr->
actionFor(actionType) != GlyphAction::kUnset) {
231 this->ensureScalerContext();
232 switch (actionType) {
234 fPathsToSend.emplace_back(
fContext->makeGlyph(packedGlyphID, &fAlloc));
235 glyph = &fPathsToSend.back();
239 fDrawablesToSend.emplace_back(
fContext->makeGlyph(packedGlyphID, &fAlloc));
240 glyph = &fDrawablesToSend.back();
244 fMasksToSend.emplace_back(
fContext->makeGlyph(packedGlyphID, &fAlloc));
245 glyph = &fMasksToSend.back();
250 if (digestPtr ==
nullptr) {
280 inline static constexpr size_t kMaxEntriesInDescriptorMap = 2000u;
282 void checkForDeletedEntries();
288 return key->getChecksum();
295 using DescToRemoteStrike =
296 std::unordered_map<const SkDescriptor*, sk_sp<RemoteStrike>, MapOps, MapOps>;
297 DescToRemoteStrike fDescToRemoteStrike;
301 size_t fMaxEntriesInDescriptorMap = kMaxEntriesInDescriptorMap;
305 std::vector<SkTypefaceProxyPrototype> fTypefacesToSend;
309 : fDiscardableHandleManager(dhm) {
310 SkASSERT(fDiscardableHandleManager);
314 fMaxEntriesInDescriptorMap =
count;
317 return fDescToRemoteStrike.size();
325 size_t strikesToSend = 0;
326 fRemoteStrikesToSend.
foreach([&](RemoteStrike* strike) {
327 if (strike->hasPendingGlyphs()) {
331 strike->resetScalerContext();
336 if (strikesToSend == 0 && fTypefacesToSend.empty()) {
337 fRemoteStrikesToSend.
reset();
343 buffer.writeInt(fTypefacesToSend.size());
344 for (
const auto& typeface: fTypefacesToSend) {
348 fTypefacesToSend.clear();
350 buffer.writeInt(strikesToSend);
352 [&](RemoteStrike* strike) {
353 if (strike->hasPendingGlyphs()) {
354 strike->writePendingGlyphs(buffer);
355 strike->resetScalerContext();
359 fRemoteStrikesToSend.
reset();
363 memory->assign(
data->bytes(),
data->bytes() +
data->size());
368 return this->getOrCreateCache(strikeSpec);
371void SkStrikeServerImpl::checkForDeletedEntries() {
372 auto it = fDescToRemoteStrike.begin();
373 while (fDescToRemoteStrike.size() > fMaxEntriesInDescriptorMap &&
374 it != fDescToRemoteStrike.end()) {
375 RemoteStrike* strike = it->second.get();
376 if (fDiscardableHandleManager->
isHandleDeleted(strike->discardableHandleId())) {
378 if (!fRemoteStrikesToSend.
contains(strike)) {
380 it = fDescToRemoteStrike.erase(it);
397 std::memcpy((
void*)&rec, ptr,
sizeof(rec));
403 if (
auto it = fDescToRemoteStrike.find(&strikeSpec.
descriptor());
404 it != fDescToRemoteStrike.end())
408 strike->setStrikeSpec(strikeSpec);
415 bool locked = fDiscardableHandleManager->
lockHandle(it->second->discardableHandleId());
417 fRemoteStrikesToSend.
add(strike.
get());
422 fDescToRemoteStrike.erase(it);
428 if (!fCachedTypefaces.
contains(typefaceId)) {
429 fCachedTypefaces.
add(typefaceId);
430 fTypefacesToSend.emplace_back(typeface);
434 auto newHandle = fDiscardableHandleManager->
createHandle();
435 auto remoteStrike = sk_make_sp<RemoteStrike>(strikeSpec, std::move(context), newHandle);
436 remoteStrike->setStrikeSpec(strikeSpec);
437 fRemoteStrikesToSend.
add(remoteStrike.get());
438 auto d = &remoteStrike->getDescriptor();
439 fDescToRemoteStrike[
d] = remoteStrike;
441 checkForDeletedEntries();
453 , fStrikeServerImpl(server)
455 SkASSERT(fStrikeServerImpl !=
nullptr);
483 auto container = SubRunContainer::MakeInAlloc(glyphRunList,
489 SubRunContainer::kStrikeCalculationsOnly,
524 bool DFTPerspSupport) {
525#if !defined(SK_DISABLE_SDF_TEXT)
529 constexpr float kMinDistanceFieldFontSize = 18.f;
531#if defined(SK_BUILD_FOR_ANDROID)
532 constexpr float kGlyphsAsPathsFontSize = 384.f;
533#elif defined(SK_BUILD_FOR_MAC)
534 constexpr float kGlyphsAsPathsFontSize = 256.f;
536 constexpr float kGlyphsAsPathsFontSize = 324.f;
541 kMinDistanceFieldFontSize,
542 kGlyphsAsPathsFontSize};
550 std::move(colorSpace),
552 return std::make_unique<SkCanvas>(std::move(trackingDevice));
556 fImpl->writeStrikeData(memory);
562 fImpl->setMaxEntriesInDescriptorMapForTesting(
count);
565 return fImpl->remoteStrikeMapSizeForTesting();
573 : fDiscardableHandleId(discardableHandleId), fManager(
std::move(
manager)) {}
588 bool isLogging =
true,
591 bool readStrikeData(
const volatile void* memory,
size_t memorySize);
596 class PictureBackedGlyphDrawable final :
public SkDrawable {
602 size_t onApproximateBytesUsed()
override {
613 const bool fIsLogging;
621 : fDiscardableHandleManager(
std::move(discardableManager)),
622 fStrikeCache{strikeCache ? strikeCache :
SkStrikeCache::GlobalStrikeCache()},
623 fIsLogging{isLogging} {}
627#define READ_FAILURE \
629 SkDebugf("Bad font data serialization line: %d", __LINE__); \
630 SkStrikeClient::DiscardableHandleManager::ReadFailureData data = { \
631 memorySize, deserializer.bytesRead(), typefaceSize, \
632 strikeCount, glyphImagesCount, __LINE__}; \
633 fDiscardableHandleManager->notifyReadFailure(data); \
645 buffer.setAllowSkSL(
false);
650 auto postError = [&](
int line) {
655 SkTo<uint64_t>(curTypeface),
656 SkTo<uint64_t>(curStrike),
663 const int typefaceCount =
buffer.readInt();
664 for (curTypeface = 0; curTypeface < typefaceCount; ++curTypeface) {
667 this->addTypeface(proto.value());
675 const int stirkeCount =
buffer.readInt();
676 for (curStrike = 0; curStrike < stirkeCount; ++curStrike) {
679 if (serverTypefaceID == 0 && !
buffer.isValid()) {
685 if (discardableHandleID == 0 && !
buffer.isValid()) {
691 if (!
buffer.validate(serverDescriptor.has_value())) {
696 const bool fontMetricsInitialized =
buffer.readBool();
697 if (!fontMetricsInitialized && !
buffer.isValid()) {
702 std::optional<SkFontMetrics> fontMetrics;
703 if (!fontMetricsInitialized) {
705 if (!fontMetrics || !
buffer.isValid()) {
711 auto* clientTypeface = fServerTypefaceIdToTypeface.
find(serverTypefaceID);
712 if (clientTypeface ==
nullptr) {
722 SkDescriptor* clientDescriptor = serverDescriptor->getDesc();
723 auto strike = fStrikeCache->
findStrike(*clientDescriptor);
725 if (strike ==
nullptr) {
728 if (fontMetricsInitialized) {
732 SkStrikeSpec strikeSpec{*clientDescriptor, *clientTypeface};
734 strikeSpec, &fontMetrics.value(),
735 std::make_unique<DiscardableStrikePinner>(
736 discardableHandleID, fDiscardableHandleManager));
740 strike->verifyPinnedStrike();
742 if (!strike->mergeFromBuffer(
buffer)) {
760 if (!ptr ||
size !=
sizeof(rec)) {
return false; }
761 std::memcpy((
void*)&rec, ptr,
size);
765 if (!tfPtr) {
return false; }
768 std::memcpy(ptr, &rec,
size);
777 auto* tfPtr = fServerTypefaceIdToTypeface.
find(typefaceID);
778 return tfPtr !=
nullptr ? *tfPtr :
nullptr;
786 if (typeface !=
nullptr) {
790 auto newTypeface = sk_make_sp<SkTypefaceProxy>(
791 typefaceProto, fDiscardableHandleManager, fIsLogging);
805 return fImpl->readStrikeData(memory, memorySize);
810 return fImpl->retrieveTypefaceUsingServerID(typefaceID);
814 return fImpl->translateTypefaceID(descriptor);
#define SkASSERT_RELEASE(cond)
uint32_t SkDiscardableHandleId
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define kRec_SkDescriptorTag
#define TRACE_STR_COPY(str)
bool canDelete() override
DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId, sk_sp< SkStrikeClient::DiscardableHandleManager > manager)
void assertValid() override
~DiscardableStrikePinner() override=default
sk_sp< SkDevice > createDevice(const CreateInfo &cinfo, const SkPaint *) override
sk_sp< sktext::gpu::Slug > convertGlyphRunListToSlug(const sktext::GlyphRunList &glyphRunList, const SkPaint &paint) override
SkStrikeDeviceInfo strikeDeviceInfo() const override
GlyphTrackingDevice(const SkISize &dimensions, const SkSurfaceProps &props, SkStrikeServerImpl *server, sk_sp< SkColorSpace > colorSpace, sktext::gpu::SDFTControl SDFTControl)
void onDrawGlyphRunList(SkCanvas *, const sktext::GlyphRunList &glyphRunList, const SkPaint &paint) override
SkDescriptor * getDesc() const
static std::optional< SkAutoDescriptor > MakeFromBuffer(SkReadBuffer &buffer)
void drawPicture(const SkPicture *picture)
const void * findEntry(uint32_t tag, uint32_t *length) const
SkScalerContextFlags scalerContextFlags() const
const SkMatrix & localToDevice() const
const SkSurfaceProps & surfaceProps() const
static void Flatten(SkWriteBuffer &buffer, const SkFontMetrics &metrics)
static std::optional< SkFontMetrics > MakeFromBuffer(SkReadBuffer &buffer)
void setActionFor(skglyph::ActionType, SkGlyph *, sktext::StrikeForGPU *)
skglyph::GlyphAction actionFor(skglyph::ActionType actionType) const
const SkPath * path() const
bool setDrawable(SkArenaAlloc *alloc, SkScalerContext *scalerContext)
bool setPath(SkArenaAlloc *alloc, SkScalerContext *scalerContext)
bool setImage(SkArenaAlloc *alloc, SkScalerContext *scalerContext)
SkDrawable * drawable() const
const void * image() const
SkMatrix & preTranslate(SkScalar dx, SkScalar dy)
virtual SkRect cullRect() const =0
virtual size_t approximateBytesUsed() const =0
sk_sp< SkStrike > createStrike(const SkStrikeSpec &strikeSpec, SkFontMetrics *maybeMetrics=nullptr, std::unique_ptr< SkStrikePinner >=nullptr) SK_EXCLUDES(fLock)
sk_sp< SkStrike > findStrike(const SkDescriptor &desc) SK_EXCLUDES(fLock)
bool translateTypefaceID(SkAutoDescriptor *descriptor) const
bool readStrikeData(const volatile void *memory, size_t memorySize)
SkStrikeClientImpl(sk_sp< SkStrikeClient::DiscardableHandleManager >, bool isLogging=true, SkStrikeCache *strikeCache=nullptr)
sk_sp< SkTypeface > retrieveTypefaceUsingServerID(SkTypefaceID) const
virtual void assertHandleValid(SkDiscardableHandleId)
virtual bool deleteHandle(SkDiscardableHandleId)=0
virtual void notifyReadFailure(const ReadFailureData &data)
SK_SPI bool readStrikeData(const volatile void *memory, size_t memorySize)
sk_sp< SkTypeface > retrieveTypefaceUsingServerIDForTest(SkTypefaceID) const
sk_sp< sktext::gpu::Slug > deserializeSlugForTest(const void *data, size_t size) const
SK_SPI SkStrikeClient(sk_sp< DiscardableHandleManager >, bool isLogging=true, SkStrikeCache *strikeCache=nullptr)
SK_SPI bool translateTypefaceID(SkAutoDescriptor *descriptor) const
SkStrikeServerImpl(SkStrikeServer::DiscardableHandleManager *discardableHandleManager)
sk_sp< sktext::StrikeForGPU > findOrCreateScopedStrike(const SkStrikeSpec &strikeSpec) override
size_t remoteStrikeMapSizeForTesting() const
void setMaxEntriesInDescriptorMapForTesting(size_t count)
void writeStrikeData(std::vector< uint8_t > *memory)
virtual SK_SPI bool lockHandle(SkDiscardableHandleId)=0
virtual SK_SPI SkDiscardableHandleId createHandle()=0
virtual SK_SPI bool isHandleDeleted(SkDiscardableHandleId)=0
void setMaxEntriesInDescriptorMapForTesting(size_t count)
SK_SPI SkStrikeServer(DiscardableHandleManager *discardableHandleManager)
SK_SPI void writeStrikeData(std::vector< uint8_t > *memory)
SK_API std::unique_ptr< SkCanvas > makeAnalysisCanvas(int width, int height, const SkSurfaceProps &props, sk_sp< SkColorSpace > colorSpace, bool DFTSupport, bool DFTPerspSupport=true)
size_t remoteStrikeMapSizeForTesting() const
const SkTypeface & typeface() const
std::unique_ptr< SkScalerContext > createScalerContext() const
const SkDescriptor & descriptor() const
static void FlattenGlyphsByType(SkWriteBuffer &buffer, SkSpan< SkGlyph > images, SkSpan< SkGlyph > paths, SkSpan< SkGlyph > drawables)
SkSurfaceProps cloneWithPixelGeometry(SkPixelGeometry newPixelGeometry) const
bool isUseDeviceIndependentFonts() const
void flatten(SkWriteBuffer &buffer) const
static std::optional< SkTypefaceProxyPrototype > MakeFromBuffer(SkReadBuffer &buffer)
SkTypefaceID serverTypefaceID() const
SkTypefaceID uniqueID() const
V * find(const K &key) const
bool contains(const T &item) const
void foreach(Fn &&fn) const
static sk_sp< Slug > Deserialize(const void *data, size_t size, const SkStrikeClient *client=nullptr)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
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 manager
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
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
sk_sp< Slug > MakeSlug(const SkMatrix &drawMatrix, const sktext::GlyphRunList &glyphRunList, const SkPaint &paint, SkStrikeDeviceInfo strikeDeviceInfo, sktext::StrikeForGPUCacheInterface *strikeCache)
const SkPixelGeometry fPixelGeometry
static constexpr SkISize Make(int32_t w, int32_t h)
sk_sp< SkColorSpace > refColorSpace() const
SkISize dimensions() const
constexpr float y() const
constexpr float x() const
std::shared_ptr< const fml::Mapping > data
#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val)