123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777 |
- /*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "src/core/SkRemoteGlyphCache.h"
- #include <iterator>
- #include <memory>
- #include <new>
- #include <string>
- #include <tuple>
- #include "src/core/SkDevice.h"
- #include "src/core/SkDraw.h"
- #include "src/core/SkGlyphRun.h"
- #include "src/core/SkRemoteGlyphCacheImpl.h"
- #include "src/core/SkStrike.h"
- #include "src/core/SkStrikeCache.h"
- #include "src/core/SkTLazy.h"
- #include "src/core/SkTraceEvent.h"
- #include "src/core/SkTypeface_remote.h"
- #if SK_SUPPORT_GPU
- #include "src/gpu/GrDrawOpAtlas.h"
- #include "src/gpu/text/GrTextContext.h"
- #endif
- static SkDescriptor* auto_descriptor_from_desc(const SkDescriptor* source_desc,
- SkFontID font_id,
- SkAutoDescriptor* ad) {
- ad->reset(source_desc->getLength());
- auto* desc = ad->getDesc();
- desc->init();
- // Rec.
- {
- uint32_t size;
- auto ptr = source_desc->findEntry(kRec_SkDescriptorTag, &size);
- SkScalerContextRec rec;
- std::memcpy(&rec, ptr, size);
- rec.fFontID = font_id;
- desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
- }
- // Effects.
- {
- uint32_t size;
- auto ptr = source_desc->findEntry(kEffects_SkDescriptorTag, &size);
- if (ptr) { desc->addEntry(kEffects_SkDescriptorTag, size, ptr); }
- }
- desc->computeChecksum();
- return desc;
- }
- static const SkDescriptor* create_descriptor(
- const SkPaint& paint, const SkFont& font, const SkMatrix& m,
- const SkSurfaceProps& props, SkScalerContextFlags flags,
- SkAutoDescriptor* ad, SkScalerContextEffects* effects) {
- SkScalerContextRec rec;
- SkScalerContext::MakeRecAndEffects(font, paint, props, flags, m, &rec, effects);
- return SkScalerContext::AutoDescriptorGivenRecAndEffects(rec, *effects, ad);
- }
- // -- Serializer ----------------------------------------------------------------------------------
- size_t pad(size_t size, size_t alignment) { return (size + (alignment - 1)) & ~(alignment - 1); }
- // Alignment between x86 and x64 differs for some types, in particular
- // int64_t and doubles have 4 and 8-byte alignment, respectively.
- // Be consistent even when writing and reading across different architectures.
- template<typename T>
- size_t serialization_alignment() {
- return sizeof(T) == 8 ? 8 : alignof(T);
- }
- class Serializer {
- public:
- Serializer(std::vector<uint8_t>* buffer) : fBuffer{buffer} { }
- template <typename T, typename... Args>
- T* emplace(Args&&... args) {
- auto result = allocate(sizeof(T), serialization_alignment<T>());
- return new (result) T{std::forward<Args>(args)...};
- }
- template <typename T>
- void write(const T& data) {
- T* result = (T*)allocate(sizeof(T), serialization_alignment<T>());
- memcpy(result, &data, sizeof(T));
- }
- template <typename T>
- T* allocate() {
- T* result = (T*)allocate(sizeof(T), serialization_alignment<T>());
- return result;
- }
- void writeDescriptor(const SkDescriptor& desc) {
- write(desc.getLength());
- auto result = allocate(desc.getLength(), alignof(SkDescriptor));
- memcpy(result, &desc, desc.getLength());
- }
- void* allocate(size_t size, size_t alignment) {
- size_t aligned = pad(fBuffer->size(), alignment);
- fBuffer->resize(aligned + size);
- return &(*fBuffer)[aligned];
- }
- private:
- std::vector<uint8_t>* fBuffer;
- };
- // -- Deserializer -------------------------------------------------------------------------------
- // Note that the Deserializer is reading untrusted data, we need to guard against invalid data.
- class Deserializer {
- public:
- Deserializer(const volatile char* memory, size_t memorySize)
- : fMemory(memory), fMemorySize(memorySize) {}
- template <typename T>
- bool read(T* val) {
- auto* result = this->ensureAtLeast(sizeof(T), serialization_alignment<T>());
- if (!result) return false;
- memcpy(val, const_cast<const char*>(result), sizeof(T));
- return true;
- }
- bool readDescriptor(SkAutoDescriptor* ad) {
- uint32_t descLength = 0u;
- if (!read<uint32_t>(&descLength)) return false;
- if (descLength < sizeof(SkDescriptor)) return false;
- if (descLength != SkAlign4(descLength)) return false;
- auto* result = this->ensureAtLeast(descLength, alignof(SkDescriptor));
- if (!result) return false;
- ad->reset(descLength);
- memcpy(ad->getDesc(), const_cast<const char*>(result), descLength);
- if (ad->getDesc()->getLength() > descLength) return false;
- return ad->getDesc()->isValid();
- }
- const volatile void* read(size_t size, size_t alignment) {
- return this->ensureAtLeast(size, alignment);
- }
- size_t bytesRead() const { return fBytesRead; }
- private:
- const volatile char* ensureAtLeast(size_t size, size_t alignment) {
- size_t padded = pad(fBytesRead, alignment);
- // Not enough data.
- if (padded > fMemorySize) return nullptr;
- if (size > fMemorySize - padded) return nullptr;
- auto* result = fMemory + padded;
- fBytesRead = padded + size;
- return result;
- }
- // Note that we read each piece of memory only once to guard against TOCTOU violations.
- const volatile char* fMemory;
- size_t fMemorySize;
- size_t fBytesRead = 0u;
- };
- // Paths use a SkWriter32 which requires 4 byte alignment.
- static const size_t kPathAlignment = 4u;
- size_t SkDescriptorMapOperators::operator()(const SkDescriptor* key) const {
- return key->getChecksum();
- }
- bool SkDescriptorMapOperators::operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const {
- return *lhs == *rhs;
- }
- struct StrikeSpec {
- StrikeSpec() {}
- StrikeSpec(SkFontID typefaceID_, SkDiscardableHandleId discardableHandleId_)
- : typefaceID{typefaceID_}, discardableHandleId(discardableHandleId_) {}
- SkFontID typefaceID = 0u;
- SkDiscardableHandleId discardableHandleId = 0u;
- /* desc */
- /* n X (glyphs ids) */
- };
- // -- TrackLayerDevice -----------------------------------------------------------------------------
- SkTextBlobCacheDiffCanvas::TrackLayerDevice::TrackLayerDevice(
- const SkIRect& bounds, const SkSurfaceProps& props, SkStrikeServer* server,
- sk_sp<SkColorSpace> colorSpace, const SkTextBlobCacheDiffCanvas::Settings& settings)
- : SkNoPixelsDevice(bounds, props, std::move(colorSpace))
- , fStrikeServer(server)
- , fSettings(settings)
- , fPainter{props, kUnknown_SkColorType, imageInfo().colorSpace(), fStrikeServer} {
- SkASSERT(fStrikeServer);
- }
- SkBaseDevice* SkTextBlobCacheDiffCanvas::TrackLayerDevice::onCreateDevice(
- const CreateInfo& cinfo, const SkPaint*) {
- const SkSurfaceProps surfaceProps(this->surfaceProps().flags(), cinfo.fPixelGeometry);
- return new TrackLayerDevice(this->getGlobalBounds(), surfaceProps, fStrikeServer,
- cinfo.fInfo.refColorSpace(), fSettings);
- }
- void SkTextBlobCacheDiffCanvas::TrackLayerDevice::drawGlyphRunList(
- const SkGlyphRunList& glyphRunList) {
- #if SK_SUPPORT_GPU
- GrTextContext::Options options;
- options.fMinDistanceFieldFontSize = fSettings.fMinDistanceFieldFontSize;
- options.fMaxDistanceFieldFontSize = fSettings.fMaxDistanceFieldFontSize;
- GrTextContext::SanitizeOptions(&options);
- fPainter.processGlyphRunList(glyphRunList,
- this->ctm(),
- this->surfaceProps(),
- fSettings.fContextSupportsDistanceFieldText,
- options,
- nullptr);
- #endif // SK_SUPPORT_GPU
- }
- // -- SkTextBlobCacheDiffCanvas -------------------------------------------------------------------
- SkTextBlobCacheDiffCanvas::Settings::Settings() = default;
- SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas(
- int width, int height, const SkSurfaceProps& props,
- SkStrikeServer* strikeServer, Settings settings)
- : SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>(
- SkIRect::MakeWH(width, height), props, strikeServer, nullptr, settings)} {}
- SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas(int width, int height,
- const SkSurfaceProps& props,
- SkStrikeServer* strikeServer,
- sk_sp<SkColorSpace> colorSpace,
- Settings settings)
- : SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>(SkIRect::MakeWH(width, height), props,
- strikeServer, std::move(colorSpace), settings)} {}
- SkTextBlobCacheDiffCanvas::~SkTextBlobCacheDiffCanvas() = default;
- SkCanvas::SaveLayerStrategy SkTextBlobCacheDiffCanvas::getSaveLayerStrategy(
- const SaveLayerRec& rec) {
- return kFullLayer_SaveLayerStrategy;
- }
- bool SkTextBlobCacheDiffCanvas::onDoSaveBehind(const SkRect*) {
- return false;
- }
- void SkTextBlobCacheDiffCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
- const SkPaint& paint) {
- ///
- SkCanvas::onDrawTextBlob(blob, x, y, paint);
- }
- struct WireTypeface {
- WireTypeface() = default;
- WireTypeface(SkFontID typeface_id, int glyph_count, SkFontStyle style, bool is_fixed)
- : typefaceID(typeface_id), glyphCount(glyph_count), style(style), isFixed(is_fixed) {}
- SkFontID typefaceID;
- int glyphCount;
- SkFontStyle style;
- bool isFixed;
- };
- // SkStrikeServer -----------------------------------------
- SkStrikeServer::SkStrikeServer(DiscardableHandleManager* discardableHandleManager)
- : fDiscardableHandleManager(discardableHandleManager) {
- SkASSERT(fDiscardableHandleManager);
- }
- SkStrikeServer::~SkStrikeServer() = default;
- sk_sp<SkData> SkStrikeServer::serializeTypeface(SkTypeface* tf) {
- auto* data = fSerializedTypefaces.find(SkTypeface::UniqueID(tf));
- if (data) {
- return *data;
- }
- WireTypeface wire(SkTypeface::UniqueID(tf), tf->countGlyphs(), tf->fontStyle(),
- tf->isFixedPitch());
- data = fSerializedTypefaces.set(SkTypeface::UniqueID(tf),
- SkData::MakeWithCopy(&wire, sizeof(wire)));
- return *data;
- }
- void SkStrikeServer::writeStrikeData(std::vector<uint8_t>* memory) {
- if (fLockedDescs.empty() && fTypefacesToSend.empty()) {
- return;
- }
- Serializer serializer(memory);
- serializer.emplace<uint64_t>(fTypefacesToSend.size());
- for (const auto& tf : fTypefacesToSend) serializer.write<WireTypeface>(tf);
- fTypefacesToSend.clear();
- serializer.emplace<uint64_t>(fLockedDescs.size());
- for (const auto* desc : fLockedDescs) {
- auto it = fRemoteGlyphStateMap.find(desc);
- SkASSERT(it != fRemoteGlyphStateMap.end());
- it->second->writePendingGlyphs(&serializer);
- }
- fLockedDescs.clear();
- }
- SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache(
- const SkPaint& paint,
- const SkFont& font,
- const SkSurfaceProps& props,
- const SkMatrix& matrix,
- SkScalerContextFlags flags,
- SkScalerContextEffects* effects) {
- SkAutoDescriptor descStorage;
- auto desc = create_descriptor(paint, font, matrix, props, flags, &descStorage, effects);
- return this->getOrCreateCache(*desc, *font.getTypefaceOrDefault(), *effects);
- }
- SkScopedStrike SkStrikeServer::findOrCreateScopedStrike(const SkDescriptor& desc,
- const SkScalerContextEffects& effects,
- const SkTypeface& typeface) {
- return SkScopedStrike{this->getOrCreateCache(desc, typeface, effects)};
- }
- void SkStrikeServer::checkForDeletedEntries() {
- auto it = fRemoteGlyphStateMap.begin();
- while (fRemoteGlyphStateMap.size() > fMaxEntriesInDescriptorMap &&
- it != fRemoteGlyphStateMap.end()) {
- if (fDiscardableHandleManager->isHandleDeleted(it->second->discardableHandleId())) {
- it = fRemoteGlyphStateMap.erase(it);
- } else {
- ++it;
- }
- }
- }
- SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache(
- const SkDescriptor& desc, const SkTypeface& typeface, SkScalerContextEffects effects) {
- // In cases where tracing is turned off, make sure not to get an unused function warning.
- // Lambdaize the function.
- TRACE_EVENT1("skia", "RecForDesc", "rec",
- TRACE_STR_COPY(
- [&desc](){
- auto ptr = desc.findEntry(kRec_SkDescriptorTag, nullptr);
- SkScalerContextRec rec;
- std::memcpy(&rec, ptr, sizeof(rec));
- return rec.dump();
- }().c_str()
- )
- );
- // Already locked.
- if (fLockedDescs.find(&desc) != fLockedDescs.end()) {
- auto it = fRemoteGlyphStateMap.find(&desc);
- SkASSERT(it != fRemoteGlyphStateMap.end());
- SkGlyphCacheState* cache = it->second.get();
- cache->setTypefaceAndEffects(&typeface, effects);
- return cache;
- }
- // Try to lock.
- auto it = fRemoteGlyphStateMap.find(&desc);
- if (it != fRemoteGlyphStateMap.end()) {
- SkGlyphCacheState* cache = it->second.get();
- bool locked = fDiscardableHandleManager->lockHandle(it->second->discardableHandleId());
- if (locked) {
- fLockedDescs.insert(it->first);
- cache->setTypefaceAndEffects(&typeface, effects);
- return cache;
- }
- // If the lock failed, the entry was deleted on the client. Remove our
- // tracking.
- fRemoteGlyphStateMap.erase(it);
- }
- const SkFontID typefaceId = typeface.uniqueID();
- if (!fCachedTypefaces.contains(typefaceId)) {
- fCachedTypefaces.add(typefaceId);
- fTypefacesToSend.emplace_back(typefaceId, typeface.countGlyphs(),
- typeface.fontStyle(),
- typeface.isFixedPitch());
- }
- auto context = typeface.createScalerContext(effects, &desc);
- // Create a new cache state and insert it into the map.
- auto newHandle = fDiscardableHandleManager->createHandle();
- auto cacheState = skstd::make_unique<SkGlyphCacheState>(desc, std::move(context), newHandle);
- auto* cacheStatePtr = cacheState.get();
- fLockedDescs.insert(&cacheStatePtr->getDescriptor());
- fRemoteGlyphStateMap[&cacheStatePtr->getDescriptor()] = std::move(cacheState);
- checkForDeletedEntries();
- cacheStatePtr->setTypefaceAndEffects(&typeface, effects);
- return cacheStatePtr;
- }
- // -- SkGlyphCacheState ----------------------------------------------------------------------------
- SkStrikeServer::SkGlyphCacheState::SkGlyphCacheState(
- const SkDescriptor& descriptor,
- std::unique_ptr<SkScalerContext> context,
- uint32_t discardableHandleId)
- : fDescriptor{descriptor}
- , fDiscardableHandleId(discardableHandleId)
- , fIsSubpixel{context->isSubpixel()}
- , fAxisAlignment{context->computeAxisAlignmentForHText()}
- // N.B. context must come last because it is used above.
- , fContext{std::move(context)} {
- SkASSERT(fDescriptor.getDesc() != nullptr);
- SkASSERT(fContext != nullptr);
- }
- SkStrikeServer::SkGlyphCacheState::~SkGlyphCacheState() = default;
- void SkStrikeServer::SkGlyphCacheState::addGlyph(SkPackedGlyphID glyph, bool asPath) {
- auto* cache = asPath ? &fCachedGlyphPaths : &fCachedGlyphImages;
- auto* pending = asPath ? &fPendingGlyphPaths : &fPendingGlyphImages;
- // Already cached.
- if (cache->contains(glyph)) {
- return;
- }
- // A glyph is going to be sent. Make sure we have a scaler context to send it.
- this->ensureScalerContext();
- // Serialize and cache. Also create the scalar context to use when serializing
- // this glyph.
- cache->add(glyph);
- pending->push_back(glyph);
- }
- // No need to write fForceBW because it is a flag private to SkScalerContext_DW, which will never
- // be called on the GPU side.
- static void writeGlyph(SkGlyph* glyph, Serializer* serializer) {
- serializer->write<SkPackedGlyphID>(glyph->getPackedID());
- serializer->write<float>(glyph->advanceX());
- serializer->write<float>(glyph->advanceY());
- serializer->write<uint16_t>(glyph->width());
- serializer->write<uint16_t>(glyph->height());
- serializer->write<int16_t>(glyph->top());
- serializer->write<int16_t>(glyph->left());
- serializer->write<uint8_t>(glyph->maskFormat());
- }
- void SkStrikeServer::SkGlyphCacheState::writePendingGlyphs(Serializer* serializer) {
- // TODO(khushalsagar): Write a strike only if it has any pending glyphs.
- serializer->emplace<bool>(this->hasPendingGlyphs());
- if (!this->hasPendingGlyphs()) {
- this->resetScalerContext();
- return;
- }
- // Write the desc.
- serializer->emplace<StrikeSpec>(fContext->getTypeface()->uniqueID(), fDiscardableHandleId);
- serializer->writeDescriptor(*fDescriptor.getDesc());
- // Write FontMetrics.
- // TODO(khushalsagar): Do we need to re-send each time?
- SkFontMetrics fontMetrics;
- fContext->getFontMetrics(&fontMetrics);
- serializer->write<SkFontMetrics>(fontMetrics);
- // Write glyphs images.
- serializer->emplace<uint64_t>(fPendingGlyphImages.size());
- for (const auto& glyphID : fPendingGlyphImages) {
- SkGlyph glyph{glyphID};
- fContext->getMetrics(&glyph);
- SkASSERT(SkMask::IsValidFormat(glyph.fMaskFormat));
- writeGlyph(&glyph, serializer);
- auto imageSize = glyph.imageSize();
- if (imageSize == 0u) continue;
- glyph.fImage = serializer->allocate(imageSize, glyph.formatAlignment());
- fContext->getImage(glyph);
- // TODO: Generating the image can change the mask format, do we need to update it in the
- // serialized glyph?
- }
- fPendingGlyphImages.clear();
- // Write glyphs paths.
- serializer->emplace<uint64_t>(fPendingGlyphPaths.size());
- for (const auto& glyphID : fPendingGlyphPaths) {
- SkGlyph glyph{glyphID};
- fContext->getMetrics(&glyph);
- SkASSERT(SkMask::IsValidFormat(glyph.fMaskFormat));
- writeGlyph(&glyph, serializer);
- writeGlyphPath(glyphID, serializer);
- }
- fPendingGlyphPaths.clear();
- this->resetScalerContext();
- }
- void SkStrikeServer::SkGlyphCacheState::ensureScalerContext() {
- if (fContext == nullptr) {
- fContext = fTypeface->createScalerContext(fEffects, fDescriptor.getDesc());
- }
- }
- void SkStrikeServer::SkGlyphCacheState::resetScalerContext() {
- fContext.reset();
- fTypeface = nullptr;
- }
- void SkStrikeServer::SkGlyphCacheState::setTypefaceAndEffects(
- const SkTypeface* typeface, SkScalerContextEffects effects) {
- fTypeface = typeface;
- fEffects = effects;
- }
- SkVector SkStrikeServer::SkGlyphCacheState::rounding() const {
- return SkStrikeCommon::PixelRounding(fIsSubpixel, fAxisAlignment);
- }
- void SkStrikeServer::SkGlyphCacheState::writeGlyphPath(const SkPackedGlyphID& glyphID,
- Serializer* serializer) const {
- SkPath path;
- if (!fContext->getPath(glyphID, &path)) {
- serializer->write<uint64_t>(0u);
- return;
- }
- size_t pathSize = path.writeToMemory(nullptr);
- serializer->write<uint64_t>(pathSize);
- path.writeToMemory(serializer->allocate(pathSize, kPathAlignment));
- }
- // Be sure to read and understand the comment for prepareForDrawing in SkStrikeInterface.h before
- // working on this code.
- SkSpan<const SkGlyphPos>
- SkStrikeServer::SkGlyphCacheState::prepareForDrawing(const SkPackedGlyphID packedGlyphIDs[],
- const SkPoint positions[], size_t n,
- int maxDimension, PreparationDetail detail,
- SkGlyphPos results[]) {
- for (size_t i = 0; i < n; i++) {
- SkPoint glyphPos = positions[i];
- // Check the cache for the glyph.
- SkGlyph* glyphPtr = fGlyphMap.findOrNull(packedGlyphIDs[i]);
- // Has this glyph ever been seen before?
- if (glyphPtr == nullptr) {
- // Never seen before. Make a new glyph.
- glyphPtr = fAlloc.make<SkGlyph>(packedGlyphIDs[i]);
- fGlyphMap.set(glyphPtr);
- this->ensureScalerContext();
- fContext->getMetrics(glyphPtr);
- if (glyphPtr->maxDimension() <= maxDimension) {
- // do nothing
- } else if (!glyphPtr->isColor()) {
- // The glyph is too big for the atlas, but it is not color, so it is handled with a
- // path.
- if (glyphPtr->setPath(&fAlloc, fContext.get())) {
- // Always send the path data, even if its not available, to make sure empty
- // paths are not incorrectly assumed to be cache misses.
- fCachedGlyphPaths.add(glyphPtr->getPackedID());
- fPendingGlyphPaths.push_back(glyphPtr->getPackedID());
- }
- } else {
- // This will be handled by the fallback strike.
- SkASSERT(glyphPtr->maxDimension() > maxDimension && glyphPtr->isColor());
- }
- // Make sure to send the glyph to the GPU because we always send the image for a glyph.
- fCachedGlyphImages.add(packedGlyphIDs[i]);
- fPendingGlyphImages.push_back(packedGlyphIDs[i]);
- }
- // Each glyph needs to be added as per the contract for prepareForDrawing.
- // TODO(herb): check if the empty glyphs need to be added here. They certainly need to be
- // sent, but do the need to be processed by the painter?
- results[i] = {i, glyphPtr, glyphPos};
- }
- return SkSpan<const SkGlyphPos>{results, n};
- }
- // SkStrikeClient -----------------------------------------
- class SkStrikeClient::DiscardableStrikePinner : public SkStrikePinner {
- public:
- DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId,
- sk_sp<DiscardableHandleManager> manager)
- : fDiscardableHandleId(discardableHandleId), fManager(std::move(manager)) {}
- ~DiscardableStrikePinner() override = default;
- bool canDelete() override { return fManager->deleteHandle(fDiscardableHandleId); }
- private:
- const SkDiscardableHandleId fDiscardableHandleId;
- sk_sp<DiscardableHandleManager> fManager;
- };
- SkStrikeClient::SkStrikeClient(sk_sp<DiscardableHandleManager> discardableManager,
- bool isLogging,
- SkStrikeCache* strikeCache)
- : fDiscardableHandleManager(std::move(discardableManager))
- , fStrikeCache{strikeCache ? strikeCache : SkStrikeCache::GlobalStrikeCache()}
- , fIsLogging{isLogging} {}
- SkStrikeClient::~SkStrikeClient() = default;
- #define READ_FAILURE \
- { \
- SkDebugf("Bad font data serialization line: %d", __LINE__); \
- DiscardableHandleManager::ReadFailureData data = { \
- memorySize, deserializer.bytesRead(), typefaceSize, \
- strikeCount, glyphImagesCount, glyphPathsCount}; \
- fDiscardableHandleManager->notifyReadFailure(data); \
- return false; \
- }
- // No need to read fForceBW because it is a flag private to SkScalerContext_DW, which will never
- // be called on the GPU side.
- bool SkStrikeClient::ReadGlyph(SkTLazy<SkGlyph>& glyph, Deserializer* deserializer) {
- SkPackedGlyphID glyphID;
- if (!deserializer->read<SkPackedGlyphID>(&glyphID)) return false;
- glyph.init(glyphID);
- if (!deserializer->read<float>(&glyph->fAdvanceX)) return false;
- if (!deserializer->read<float>(&glyph->fAdvanceY)) return false;
- if (!deserializer->read<uint16_t>(&glyph->fWidth)) return false;
- if (!deserializer->read<uint16_t>(&glyph->fHeight)) return false;
- if (!deserializer->read<int16_t>(&glyph->fTop)) return false;
- if (!deserializer->read<int16_t>(&glyph->fLeft)) return false;
- if (!deserializer->read<uint8_t>(&glyph->fMaskFormat)) return false;
- if (!SkMask::IsValidFormat(glyph->fMaskFormat)) return false;
- return true;
- }
- bool SkStrikeClient::readStrikeData(const volatile void* memory, size_t memorySize) {
- SkASSERT(memorySize != 0u);
- Deserializer deserializer(static_cast<const volatile char*>(memory), memorySize);
- uint64_t typefaceSize = 0u;
- uint64_t strikeCount = 0u;
- uint64_t glyphImagesCount = 0u;
- uint64_t glyphPathsCount = 0u;
- if (!deserializer.read<uint64_t>(&typefaceSize)) READ_FAILURE
- for (size_t i = 0; i < typefaceSize; ++i) {
- WireTypeface wire;
- if (!deserializer.read<WireTypeface>(&wire)) READ_FAILURE
- // TODO(khushalsagar): The typeface no longer needs a reference to the
- // SkStrikeClient, since all needed glyphs must have been pushed before
- // raster.
- addTypeface(wire);
- }
- if (!deserializer.read<uint64_t>(&strikeCount)) READ_FAILURE
- for (size_t i = 0; i < strikeCount; ++i) {
- bool has_glyphs = false;
- if (!deserializer.read<bool>(&has_glyphs)) READ_FAILURE
- if (!has_glyphs) continue;
- StrikeSpec spec;
- if (!deserializer.read<StrikeSpec>(&spec)) READ_FAILURE
- SkAutoDescriptor sourceAd;
- if (!deserializer.readDescriptor(&sourceAd)) READ_FAILURE
- SkFontMetrics fontMetrics;
- if (!deserializer.read<SkFontMetrics>(&fontMetrics)) READ_FAILURE
- // Get the local typeface from remote fontID.
- auto* tfPtr = fRemoteFontIdToTypeface.find(spec.typefaceID);
- // Received strikes for a typeface which doesn't exist.
- if (!tfPtr) READ_FAILURE
- auto* tf = tfPtr->get();
- // Replace the ContextRec in the desc from the server to create the client
- // side descriptor.
- // TODO: Can we do this in-place and re-compute checksum? Instead of a complete copy.
- SkAutoDescriptor ad;
- auto* client_desc = auto_descriptor_from_desc(sourceAd.getDesc(), tf->uniqueID(), &ad);
- auto strike = fStrikeCache->findStrikeExclusive(*client_desc);
- if (strike == nullptr) {
- // Note that we don't need to deserialize the effects since we won't be generating any
- // glyphs here anyway, and the desc is still correct since it includes the serialized
- // effects.
- SkScalerContextEffects effects;
- auto scaler = SkStrikeCache::CreateScalerContext(*client_desc, effects, *tf);
- strike = fStrikeCache->createStrikeExclusive(
- *client_desc, std::move(scaler), &fontMetrics,
- skstd::make_unique<DiscardableStrikePinner>(spec.discardableHandleId,
- fDiscardableHandleManager));
- auto proxyContext = static_cast<SkScalerContextProxy*>(strike->getScalerContext());
- proxyContext->initCache(strike.get(), fStrikeCache);
- }
- if (!deserializer.read<uint64_t>(&glyphImagesCount)) READ_FAILURE
- for (size_t j = 0; j < glyphImagesCount; j++) {
- SkTLazy<SkGlyph> glyph;
- if (!ReadGlyph(glyph, &deserializer)) READ_FAILURE
- if (!glyph->isEmpty()) {
- const volatile void* image =
- deserializer.read(glyph->imageSize(), glyph->formatAlignment());
- if (!image) READ_FAILURE
- glyph->fImage = (void*)image;
- }
- strike->mergeGlyphAndImage(glyph->getPackedID(), *glyph);
- }
- if (!deserializer.read<uint64_t>(&glyphPathsCount)) READ_FAILURE
- for (size_t j = 0; j < glyphPathsCount; j++) {
- SkTLazy<SkGlyph> glyph;
- if (!ReadGlyph(glyph, &deserializer)) READ_FAILURE
- SkGlyph* allocatedGlyph = strike->mergeGlyphAndImage(glyph->getPackedID(), *glyph);
- SkPath* pathPtr = nullptr;
- SkPath path;
- uint64_t pathSize = 0u;
- if (!deserializer.read<uint64_t>(&pathSize)) READ_FAILURE
- if (pathSize > 0) {
- auto* pathData = deserializer.read(pathSize, kPathAlignment);
- if (!pathData) READ_FAILURE
- if (!path.readFromMemory(const_cast<const void*>(pathData), pathSize)) READ_FAILURE
- pathPtr = &path;
- }
- strike->preparePath(allocatedGlyph, pathPtr);
- }
- }
- return true;
- }
- sk_sp<SkTypeface> SkStrikeClient::deserializeTypeface(const void* buf, size_t len) {
- WireTypeface wire;
- if (len != sizeof(wire)) return nullptr;
- memcpy(&wire, buf, sizeof(wire));
- return this->addTypeface(wire);
- }
- sk_sp<SkTypeface> SkStrikeClient::addTypeface(const WireTypeface& wire) {
- auto* typeface = fRemoteFontIdToTypeface.find(wire.typefaceID);
- if (typeface) return *typeface;
- auto newTypeface = sk_make_sp<SkTypefaceProxy>(
- wire.typefaceID, wire.glyphCount, wire.style, wire.isFixed,
- fDiscardableHandleManager, fIsLogging);
- fRemoteFontIdToTypeface.set(wire.typefaceID, newTypeface);
- return std::move(newTypeface);
- }
|