| /* |
| * Copyright 2018 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SkRemoteGlyphCache_DEFINED |
| #define SkRemoteGlyphCache_DEFINED |
| |
| #include <memory> |
| #include <tuple> |
| #include <unordered_map> |
| #include <unordered_set> |
| #include <vector> |
| |
| #include "../private/SkTHash.h" |
| #include "SkData.h" |
| #include "SkDevice.h" |
| #include "SkDrawLooper.h" |
| #include "SkMakeUnique.h" |
| #include "SkNoDrawCanvas.h" |
| #include "SkRefCnt.h" |
| #include "SkSerialProcs.h" |
| #include "SkTypeface.h" |
| |
| class Serializer; |
| enum SkAxisAlignment : uint32_t; |
| class SkDescriptor; |
| class SkStrike; |
| struct SkPackedGlyphID; |
| enum SkScalerContextFlags : uint32_t; |
| class SkStrikeCache; |
| class SkTypefaceProxy; |
| struct WireTypeface; |
| |
| class SkStrikeServer; |
| |
| struct SkDescriptorMapOperators { |
| size_t operator()(const SkDescriptor* key) const; |
| bool operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const; |
| }; |
| |
| template <typename T> |
| using SkDescriptorMap = std::unordered_map<const SkDescriptor*, T, SkDescriptorMapOperators, |
| SkDescriptorMapOperators>; |
| |
| using SkDescriptorSet = |
| std::unordered_set<const SkDescriptor*, SkDescriptorMapOperators, SkDescriptorMapOperators>; |
| |
| // A SkTextBlobCacheDiffCanvas is used to populate the SkStrikeServer with ops |
| // which will be serialized and renderered using the SkStrikeClient. |
| class SK_API SkTextBlobCacheDiffCanvas : public SkNoDrawCanvas { |
| public: |
| struct SK_API Settings { |
| Settings(); |
| |
| bool fContextSupportsDistanceFieldText = true; |
| SkScalar fMinDistanceFieldFontSize = -1.f; |
| SkScalar fMaxDistanceFieldFontSize = -1.f; |
| int fMaxTextureSize = 0; |
| size_t fMaxTextureBytes = 0u; |
| }; |
| SkTextBlobCacheDiffCanvas(int width, int height, const SkSurfaceProps& props, |
| SkStrikeServer* strikeServer, Settings settings = Settings()); |
| |
| // TODO(khushalsagar): Remove once removed from chromium. |
| SkTextBlobCacheDiffCanvas(int width, int height, const SkMatrix& deviceMatrix, |
| const SkSurfaceProps& props, SkStrikeServer* strikeserver, |
| Settings settings = Settings()); |
| ~SkTextBlobCacheDiffCanvas() override; |
| |
| protected: |
| SkCanvas::SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override; |
| bool onDoSaveBehind(const SkRect*) override; |
| void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, |
| const SkPaint& paint) override; |
| |
| private: |
| class TrackLayerDevice; |
| |
| static SkScalar SetupForPath(SkPaint* paint, SkFont* font); |
| }; |
| |
| using SkDiscardableHandleId = uint32_t; |
| |
| // This class is not thread-safe. |
| class SK_API SkStrikeServer { |
| public: |
| // An interface used by the server to create handles for pinning SkStrike |
| // entries on the remote client. |
| class SK_API DiscardableHandleManager { |
| public: |
| virtual ~DiscardableHandleManager() = default; |
| |
| // Creates a new *locked* handle and returns a unique ID that can be used to identify |
| // it on the remote client. |
| virtual SkDiscardableHandleId createHandle() = 0; |
| |
| // Returns true if the handle could be successfully locked. The server can |
| // assume it will remain locked until the next set of serialized entries is |
| // pulled from the SkStrikeServer. |
| // If returns false, the cache entry mapped to the handle has been deleted |
| // on the client. Any subsequent attempts to lock the same handle are not |
| // allowed. |
| virtual bool lockHandle(SkDiscardableHandleId) = 0; |
| |
| // Returns true if a handle has been deleted on the remote client. It is |
| // invalid to use a handle id again with this manager once this returns true. |
| // TODO(khushalsagar): Make pure virtual once chrome implementation lands. |
| virtual bool isHandleDeleted(SkDiscardableHandleId) { return false; } |
| }; |
| |
| explicit SkStrikeServer(DiscardableHandleManager* discardableHandleManager); |
| ~SkStrikeServer(); |
| |
| // Serializes the typeface to be remoted using this server. |
| sk_sp<SkData> serializeTypeface(SkTypeface*); |
| |
| // Serializes the strike data captured using a SkTextBlobCacheDiffCanvas. Any |
| // handles locked using the DiscardableHandleManager will be assumed to be |
| // unlocked after this call. |
| void writeStrikeData(std::vector<uint8_t>* memory); |
| |
| // Methods used internally in skia ------------------------------------------ |
| class SkGlyphCacheState; |
| |
| SkGlyphCacheState* getOrCreateCache(const SkPaint&, |
| const SkFont& font, |
| const SkSurfaceProps&, |
| const SkMatrix&, |
| SkScalerContextFlags flags, |
| SkScalerContextEffects* effects); |
| |
| void setMaxEntriesInDescriptorMapForTesting(size_t count) { |
| fMaxEntriesInDescriptorMap = count; |
| } |
| size_t remoteGlyphStateMapSizeForTesting() const { return fRemoteGlyphStateMap.size(); } |
| |
| private: |
| static constexpr size_t kMaxEntriesInDescriptorMap = 2000u; |
| |
| void checkForDeletedEntries(); |
| |
| SkDescriptorMap<std::unique_ptr<SkGlyphCacheState>> fRemoteGlyphStateMap; |
| DiscardableHandleManager* const fDiscardableHandleManager; |
| SkTHashSet<SkFontID> fCachedTypefaces; |
| size_t fMaxEntriesInDescriptorMap = kMaxEntriesInDescriptorMap; |
| |
| // Cached serialized typefaces. |
| SkTHashMap<SkFontID, sk_sp<SkData>> fSerializedTypefaces; |
| |
| // State cached until the next serialization. |
| SkDescriptorSet fLockedDescs; |
| std::vector<WireTypeface> fTypefacesToSend; |
| }; |
| |
| class SK_API SkStrikeClient { |
| public: |
| // This enum is used in histogram reporting in chromium. Please don't re-order the list of |
| // entries, and consider it to be append-only. |
| enum CacheMissType : uint32_t { |
| // Hard failures where no fallback could be found. |
| kFontMetrics = 0, |
| kGlyphMetrics = 1, |
| kGlyphImage = 2, |
| kGlyphPath = 3, |
| |
| // The original glyph could not be found and a fallback was used. |
| kGlyphMetricsFallback = 4, |
| kGlyphPathFallback = 5, |
| |
| kLast = kGlyphPathFallback |
| }; |
| |
| // An interface to delete handles that may be pinned by the remote server. |
| class DiscardableHandleManager : public SkRefCnt { |
| public: |
| virtual ~DiscardableHandleManager() = default; |
| |
| // Returns true if the handle was unlocked and can be safely deleted. Once |
| // successful, subsequent attempts to delete the same handle are invalid. |
| virtual bool deleteHandle(SkDiscardableHandleId) = 0; |
| |
| virtual void notifyCacheMiss(CacheMissType) {} |
| }; |
| |
| explicit SkStrikeClient(sk_sp<DiscardableHandleManager>, |
| bool isLogging = true, |
| SkStrikeCache* strikeCache = nullptr); |
| ~SkStrikeClient(); |
| |
| // Deserializes the typeface previously serialized using the SkStrikeServer. Returns null if the |
| // data is invalid. |
| sk_sp<SkTypeface> deserializeTypeface(const void* data, size_t length); |
| |
| // Deserializes the strike data from a SkStrikeServer. All messages generated |
| // from a server when serializing the ops must be deserialized before the op |
| // is rasterized. |
| // Returns false if the data is invalid. |
| bool readStrikeData(const volatile void* memory, size_t memorySize); |
| |
| private: |
| class DiscardableStrikePinner; |
| |
| sk_sp<SkTypeface> addTypeface(const WireTypeface& wire); |
| |
| SkTHashMap<SkFontID, sk_sp<SkTypeface>> fRemoteFontIdToTypeface; |
| sk_sp<DiscardableHandleManager> fDiscardableHandleManager; |
| SkStrikeCache* const fStrikeCache; |
| const bool fIsLogging; |
| }; |
| |
| #endif // SkRemoteGlyphCache_DEFINED |