| /* | |
| * 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 SkGlyphCache; | |
| 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(); | |
| ~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; | |
| void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, | |
| const SkPaint& paint) override; | |
| private: | |
| class TrackLayerDevice; | |
| }; | |
| 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 SkGlyphCache | |
| // entries on the remote client. | |
| class SK_API DiscardableHandleManager { | |
| public: | |
| virtual ~DiscardableHandleManager() {} | |
| // 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; | |
| // TODO(khushalsagar): Add an API which checks whether a handle is still | |
| // valid without locking, so we can avoid tracking stale handles once they | |
| // have been purged on the remote side. | |
| }; | |
| 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 SkSurfaceProps*, const SkMatrix*, | |
| SkScalerContextFlags flags, | |
| SkScalerContextEffects* effects); | |
| private: | |
| SkDescriptorMap<std::unique_ptr<SkGlyphCacheState>> fRemoteGlyphStateMap; | |
| DiscardableHandleManager* const fDiscardableHandleManager; | |
| SkTHashSet<SkFontID> fCachedTypefaces; | |
| // 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() {} | |
| // 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) {} | |
| }; | |
| 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 |