/*
* 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 "SkData.h"
#include "SkDescriptor.h"
#include "SkSerialProcs.h"
#include "SkTHash.h"
#include "SkTypeface.h"
#include "SkTypeface_remote.h"
class SkScalerContextRecDescriptor {
public:
SkScalerContextRecDescriptor() {}
explicit SkScalerContextRecDescriptor(const SkScalerContextRec& rec) {
auto desc = reinterpret_cast<SkDescriptor*>(&fDescriptor);
desc->init();
desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
SkASSERT(sizeof(fDescriptor) == desc->getLength());
}
SkScalerContextRecDescriptor& operator=(const SkScalerContextRecDescriptor& rhs) {
std::memcpy(&fDescriptor, &rhs.fDescriptor, rhs.desc().getLength());
return *this;
}
const SkDescriptor& desc() const {
return *reinterpret_cast<const SkDescriptor*>(&fDescriptor);
}
struct Hash {
uint32_t operator()(SkScalerContextRecDescriptor const& s) const {
return s.desc().getChecksum();
}
};
friend bool operator==(const SkScalerContextRecDescriptor& lhs,
const SkScalerContextRecDescriptor& rhs ) {
return lhs.desc() == rhs.desc();
}
private:
// The system only passes descriptors without effects. That is why it uses a fixed size
// descriptor. storageFor is needed because some of the constructors below are private.
template <typename T>
using storageFor = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
struct {
storageFor<SkDescriptor> dummy1;
storageFor<SkDescriptor::Entry> dummy2;
storageFor<SkScalerContextRec> dummy3;
} fDescriptor;
};
class SkRemoteGlyphCacheRenderer {
public:
void prepareSerializeProcs(SkSerialProcs* procs);
SkScalerContext* generateScalerContext(
const SkScalerContextRecDescriptor& desc, SkFontID typefaceId);
private:
sk_sp<SkData> encodeTypeface(SkTypeface* tf);
SkTHashMap<SkFontID, sk_sp<SkTypeface>> fTypefaceMap;
using DescriptorToContextMap =
SkTHashMap<
SkScalerContextRecDescriptor,
std::unique_ptr<SkScalerContext>,
SkScalerContextRecDescriptor::Hash>;
DescriptorToContextMap fScalerContextMap;
};
class SkRemoteGlyphCacheGPU {
public:
explicit SkRemoteGlyphCacheGPU(std::unique_ptr<SkRemoteScalerContext> remoteScalerContext);
void prepareDeserializeProcs(SkDeserialProcs* procs);
private:
sk_sp<SkTypeface> decodeTypeface(const void* buf, size_t len);
std::unique_ptr<SkRemoteScalerContext> fRemoteScalerContext;
// TODO: Figure out how to manage the entries for the following maps.
SkTHashMap<SkFontID, sk_sp<SkTypefaceProxy>> fMapIdToTypeface;
};
#endif // SkRemoteGlyphCache_DEFINED