* 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 "include/core/SkData.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSerialProcs.h"
#include "include/core/SkTypeface.h"
#include "include/private/SkTHash.h"
#include "include/utils/SkNoDrawCanvas.h"
#include "src/core/SkDevice.h"
#include "src/core/SkMakeUnique.h"
#include "src/core/SkStrikeInterface.h"
#include "src/core/SkTLazy.h"
class Deserializer;
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>;
class SK_API SkTextBlobCacheDiffCanvas : public SkNoDrawCanvas {
public:
struct SK_API Settings {
Settings();
bool fContextSupportsDistanceFieldText = true;
int fMaxTextureSize = 0;
size_t fMaxTextureBytes = 0u;
};
SkTextBlobCacheDiffCanvas(int width, int height, const SkSurfaceProps& props,
SkStrikeServer* strikeServer, bool DFTSupport = true);
SkTextBlobCacheDiffCanvas(int width, int height, const SkSurfaceProps& props,
SkStrikeServer* strikeServer, sk_sp<SkColorSpace> colorSpace,
Settings settings = Settings());
SkTextBlobCacheDiffCanvas(int width, int height, const SkSurfaceProps& props,
SkStrikeServer* strikeServer, sk_sp<SkColorSpace> colorSpace,
bool DFTSupport);
~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;
};
using SkDiscardableHandleId = uint32_t;
class SK_API SkStrikeServer final : public SkStrikeCacheInterface {
public:
class SK_API DiscardableHandleManager {
public:
virtual ~DiscardableHandleManager() = default;
virtual SkDiscardableHandleId createHandle() = 0;
virtual bool lockHandle(SkDiscardableHandleId) = 0;
virtual bool isHandleDeleted(SkDiscardableHandleId) { return false; }
};
explicit SkStrikeServer(DiscardableHandleManager* discardableHandleManager);
~SkStrikeServer() override;
sk_sp<SkData> serializeTypeface(SkTypeface*);
void writeStrikeData(std::vector<uint8_t>* memory);
class SkGlyphCacheState;
SkGlyphCacheState* getOrCreateCache(const SkPaint&,
const SkFont& font,
const SkSurfaceProps&,
const SkMatrix&,
SkScalerContextFlags flags,
SkScalerContextEffects* effects);
SkScopedStrike findOrCreateScopedStrike(const SkDescriptor& desc,
const SkScalerContextEffects& effects,
const SkTypeface& typeface) override;
static void AddGlyphForTesting(
SkGlyphCacheState* cache, SkPackedGlyphID glyphID, bool asPath);
void setMaxEntriesInDescriptorMapForTesting(size_t count) {
fMaxEntriesInDescriptorMap = count;
}
size_t remoteGlyphStateMapSizeForTesting() const { return fRemoteGlyphStateMap.size(); }
private:
static constexpr size_t kMaxEntriesInDescriptorMap = 2000u;
void checkForDeletedEntries();
SkGlyphCacheState* getOrCreateCache(const SkDescriptor& desc,
const SkTypeface& typeface,
SkScalerContextEffects effects);
SkDescriptorMap<std::unique_ptr<SkGlyphCacheState>> fRemoteGlyphStateMap;
DiscardableHandleManager* const fDiscardableHandleManager;
SkTHashSet<SkFontID> fCachedTypefaces;
size_t fMaxEntriesInDescriptorMap = kMaxEntriesInDescriptorMap;
SkTHashMap<SkFontID, sk_sp<SkData>> fSerializedTypefaces;
SkDescriptorSet fLockedDescs;
std::vector<WireTypeface> fTypefacesToSend;
};
class SK_API SkStrikeClient {
public:
enum CacheMissType : uint32_t {
kFontMetrics = 0,
kGlyphMetrics = 1,
kGlyphImage = 2,
kGlyphPath = 3,
kGlyphMetricsFallback = 4,
kGlyphPathFallback = 5,
kLast = kGlyphPathFallback
};
class DiscardableHandleManager : public SkRefCnt {
public:
~DiscardableHandleManager() override = default;
virtual bool deleteHandle(SkDiscardableHandleId) = 0;
virtual void notifyCacheMiss(CacheMissType) {}
struct ReadFailureData {
size_t memorySize;
size_t bytesRead;
uint64_t typefaceSize;
uint64_t strikeCount;
uint64_t glyphImagesCount;
uint64_t glyphPathsCount;
};
virtual void notifyReadFailure(const ReadFailureData& data) {}
};
explicit SkStrikeClient(sk_sp<DiscardableHandleManager>,
bool isLogging = true,
SkStrikeCache* strikeCache = nullptr);
~SkStrikeClient();
sk_sp<SkTypeface> deserializeTypeface(const void* data, size_t length);
static bool ReadGlyph(SkTLazy<SkGlyph>& glyph, Deserializer* deserializer);
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