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) {
233 case skglyph::kPath: {
234 fPathsToSend.emplace_back(
fContext->makeGlyph(packedGlyphID, &fAlloc));
235 glyph = &fPathsToSend.back();
238 case skglyph::kDrawable: {
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);
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 {
601 SkRect onGetBounds()
override {
return fSelf->cullRect(); }
602 size_t onApproximateBytesUsed()
override {
603 return sizeof(PictureBackedGlyphDrawable) + fSelf->approximateBytesUsed();
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); \
650 auto postError = [&](
int line) {
651 SkDebugf(
"Read Error Posted %s : %d", __FILE__, 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)
void setAllowSkSL(bool allow)
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)
static SubRunContainerOwner MakeInAlloc(const GlyphRunList &glyphRunList, const SkMatrix &positionMatrix, const SkPaint &runPaint, SkStrikeDeviceInfo strikeDeviceInfo, StrikeForGPUCacheInterface *strikeCache, sktext::gpu::SubRunAllocator *alloc, SubRunCreationBehavior creationBehavior, const char *tag)
@ kStrikeCalculationsOnly
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
static const uint8_t buffer[]
AutoTArray< uint8_t > data((int) 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
#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val)