1 /* 2 * Copyright 2018 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkRemoteGlyphCache.h" 9 10 #include <iterator> 11 #include <memory> 12 #include <new> 13 #include <string> 14 #include <tuple> 15 16 #include "SkDevice.h" 17 #include "SkDraw.h" 18 #include "SkGlyphRun.h" 19 #include "SkRemoteGlyphCacheImpl.h" 20 #include "SkStrike.h" 21 #include "SkStrikeCache.h" 22 #include "SkTLazy.h" 23 #include "SkTraceEvent.h" 24 #include "SkTypeface_remote.h" 25 26 #if SK_SUPPORT_GPU 27 #include "GrDrawOpAtlas.h" 28 #include "text/GrTextContext.h" 29 #endif 30 31 static SkDescriptor* auto_descriptor_from_desc(const SkDescriptor* source_desc, 32 SkFontID font_id, 33 SkAutoDescriptor* ad) { 34 ad->reset(source_desc->getLength()); 35 auto* desc = ad->getDesc(); 36 desc->init(); 37 38 // Rec. 39 { 40 uint32_t size; 41 auto ptr = source_desc->findEntry(kRec_SkDescriptorTag, &size); 42 SkScalerContextRec rec; 43 std::memcpy(&rec, ptr, size); 44 rec.fFontID = font_id; 45 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); 46 } 47 48 // Effects. 49 { 50 uint32_t size; 51 auto ptr = source_desc->findEntry(kEffects_SkDescriptorTag, &size); 52 if (ptr) { desc->addEntry(kEffects_SkDescriptorTag, size, ptr); } 53 } 54 55 desc->computeChecksum(); 56 return desc; 57 } 58 59 enum DescriptorType : bool { kKey = false, kDevice = true }; 60 static const SkDescriptor* create_descriptor( 61 DescriptorType type, const SkPaint& paint, const SkFont& font, const SkMatrix& m, 62 const SkSurfaceProps& props, SkScalerContextFlags flags, 63 SkAutoDescriptor* ad, SkScalerContextEffects* effects) { 64 SkScalerContextRec deviceRec; 65 bool enableTypefaceFiltering = (type == kDevice); 66 SkScalerContext::MakeRecAndEffects( 67 font, paint, props, flags, m, &deviceRec, effects, enableTypefaceFiltering); 68 return SkScalerContext::AutoDescriptorGivenRecAndEffects(deviceRec, *effects, ad); 69 } 70 71 // -- Serializer ---------------------------------------------------------------------------------- 72 73 size_t pad(size_t size, size_t alignment) { return (size + (alignment - 1)) & ~(alignment - 1); } 74 75 class Serializer { 76 public: 77 Serializer(std::vector<uint8_t>* buffer) : fBuffer{buffer} { } 78 79 template <typename T, typename... Args> 80 T* emplace(Args&&... args) { 81 auto result = allocate(sizeof(T), alignof(T)); 82 return new (result) T{std::forward<Args>(args)...}; 83 } 84 85 template <typename T> 86 void write(const T& data) { 87 T* result = (T*)allocate(sizeof(T), alignof(T)); 88 memcpy(result, &data, sizeof(T)); 89 } 90 91 template <typename T> 92 T* allocate() { 93 T* result = (T*)allocate(sizeof(T), alignof(T)); 94 return result; 95 } 96 97 void writeDescriptor(const SkDescriptor& desc) { 98 write(desc.getLength()); 99 auto result = allocate(desc.getLength(), alignof(SkDescriptor)); 100 memcpy(result, &desc, desc.getLength()); 101 } 102 103 void* allocate(size_t size, size_t alignment) { 104 size_t aligned = pad(fBuffer->size(), alignment); 105 fBuffer->resize(aligned + size); 106 return &(*fBuffer)[aligned]; 107 } 108 109 private: 110 std::vector<uint8_t>* fBuffer; 111 }; 112 113 // -- Deserializer ------------------------------------------------------------------------------- 114 // Note that the Deserializer is reading untrusted data, we need to guard against invalid data. 115 class Deserializer { 116 public: 117 Deserializer(const volatile char* memory, size_t memorySize) 118 : fMemory(memory), fMemorySize(memorySize) {} 119 120 template <typename T> 121 bool read(T* val) { 122 auto* result = this->ensureAtLeast(sizeof(T), alignof(T)); 123 if (!result) return false; 124 125 memcpy(val, const_cast<const char*>(result), sizeof(T)); 126 return true; 127 } 128 129 bool readDescriptor(SkAutoDescriptor* ad) { 130 uint32_t desc_length = 0u; 131 if (!read<uint32_t>(&desc_length)) return false; 132 133 auto* result = this->ensureAtLeast(desc_length, alignof(SkDescriptor)); 134 if (!result) return false; 135 136 ad->reset(desc_length); 137 memcpy(ad->getDesc(), const_cast<const char*>(result), desc_length); 138 return true; 139 } 140 141 const volatile void* read(size_t size, size_t alignment) { 142 return this->ensureAtLeast(size, alignment); 143 } 144 145 private: 146 const volatile char* ensureAtLeast(size_t size, size_t alignment) { 147 size_t padded = pad(fBytesRead, alignment); 148 149 // Not enough data 150 if (padded + size > fMemorySize) return nullptr; 151 152 auto* result = fMemory + padded; 153 fBytesRead = padded + size; 154 return result; 155 } 156 157 // Note that we read each piece of memory only once to guard against TOCTOU violations. 158 const volatile char* fMemory; 159 size_t fMemorySize; 160 size_t fBytesRead = 0u; 161 }; 162 163 // Paths use a SkWriter32 which requires 4 byte alignment. 164 static const size_t kPathAlignment = 4u; 165 166 bool read_path(Deserializer* deserializer, SkGlyph* glyph, SkStrike* cache) { 167 uint64_t pathSize = 0u; 168 if (!deserializer->read<uint64_t>(&pathSize)) return false; 169 170 if (pathSize == 0u) return true; 171 172 auto* path = deserializer->read(pathSize, kPathAlignment); 173 if (!path) return false; 174 175 return cache->initializePath(glyph, path, pathSize); 176 } 177 178 size_t SkDescriptorMapOperators::operator()(const SkDescriptor* key) const { 179 return key->getChecksum(); 180 } 181 182 bool SkDescriptorMapOperators::operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const { 183 return *lhs == *rhs; 184 } 185 186 struct StrikeSpec { 187 StrikeSpec() {} 188 StrikeSpec(SkFontID typefaceID_, SkDiscardableHandleId discardableHandleId_) 189 : typefaceID{typefaceID_}, discardableHandleId(discardableHandleId_) {} 190 SkFontID typefaceID = 0u; 191 SkDiscardableHandleId discardableHandleId = 0u; 192 /* desc */ 193 /* n X (glyphs ids) */ 194 }; 195 196 // -- TrackLayerDevice ----------------------------------------------------------------------------- 197 SkTextBlobCacheDiffCanvas::TrackLayerDevice::TrackLayerDevice( 198 const SkIRect& bounds, const SkSurfaceProps& props, SkStrikeServer* server, 199 const SkTextBlobCacheDiffCanvas::Settings& settings) 200 : SkNoPixelsDevice(bounds, props) 201 , fStrikeServer(server) 202 , fSettings(settings) 203 , fPainter{props, kUnknown_SkColorType, SkScalerContextFlags::kFakeGammaAndBoostContrast} { 204 SkASSERT(fStrikeServer); 205 } 206 207 SkBaseDevice* SkTextBlobCacheDiffCanvas::TrackLayerDevice::onCreateDevice( 208 const CreateInfo& cinfo, const SkPaint*) { 209 const SkSurfaceProps surfaceProps(this->surfaceProps().flags(), cinfo.fPixelGeometry); 210 return new TrackLayerDevice(this->getGlobalBounds(), surfaceProps, fStrikeServer, fSettings); 211 } 212 213 void SkTextBlobCacheDiffCanvas::TrackLayerDevice::drawGlyphRunList( 214 const SkGlyphRunList& glyphRunList) { 215 for (auto& glyphRun : glyphRunList) { 216 this->processGlyphRun(glyphRunList.origin(), glyphRun, glyphRunList.paint()); 217 } 218 } 219 220 // -- SkTextBlobCacheDiffCanvas ------------------------------------------------------------------- 221 SkTextBlobCacheDiffCanvas::Settings::Settings() = default; 222 223 SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas(int width, int height, 224 const SkMatrix& deviceMatrix, 225 const SkSurfaceProps& props, 226 SkStrikeServer* strikeServer, 227 Settings settings) 228 : SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>(SkIRect::MakeWH(width, height), props, 229 strikeServer, settings)} {} 230 231 SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas( 232 int width, int height, const SkSurfaceProps& props, 233 SkStrikeServer* strikeServer, Settings settings) 234 : SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>( 235 SkIRect::MakeWH(width, height), props, strikeServer, settings)} {} 236 237 SkTextBlobCacheDiffCanvas::~SkTextBlobCacheDiffCanvas() = default; 238 239 SkCanvas::SaveLayerStrategy SkTextBlobCacheDiffCanvas::getSaveLayerStrategy( 240 const SaveLayerRec& rec) { 241 return kFullLayer_SaveLayerStrategy; 242 } 243 244 bool SkTextBlobCacheDiffCanvas::onDoSaveBehind(const SkRect*) { 245 return false; 246 } 247 248 void SkTextBlobCacheDiffCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 249 const SkPaint& paint) { 250 SkCanvas::onDrawTextBlob(blob, x, y, paint); 251 } 252 253 struct WireTypeface { 254 WireTypeface() = default; 255 WireTypeface(SkFontID typeface_id, int glyph_count, SkFontStyle style, bool is_fixed) 256 : typefaceID(typeface_id), glyphCount(glyph_count), style(style), isFixed(is_fixed) {} 257 258 SkFontID typefaceID; 259 int glyphCount; 260 SkFontStyle style; 261 bool isFixed; 262 }; 263 264 // SkStrikeServer ----------------------------------------- 265 266 SkStrikeServer::SkStrikeServer(DiscardableHandleManager* discardableHandleManager) 267 : fDiscardableHandleManager(discardableHandleManager) { 268 SkASSERT(fDiscardableHandleManager); 269 } 270 271 SkStrikeServer::~SkStrikeServer() = default; 272 273 sk_sp<SkData> SkStrikeServer::serializeTypeface(SkTypeface* tf) { 274 auto* data = fSerializedTypefaces.find(SkTypeface::UniqueID(tf)); 275 if (data) { 276 return *data; 277 } 278 279 WireTypeface wire(SkTypeface::UniqueID(tf), tf->countGlyphs(), tf->fontStyle(), 280 tf->isFixedPitch()); 281 data = fSerializedTypefaces.set(SkTypeface::UniqueID(tf), 282 SkData::MakeWithCopy(&wire, sizeof(wire))); 283 return *data; 284 } 285 286 void SkStrikeServer::writeStrikeData(std::vector<uint8_t>* memory) { 287 if (fLockedDescs.empty() && fTypefacesToSend.empty()) { 288 return; 289 } 290 291 Serializer serializer(memory); 292 serializer.emplace<uint64_t>(fTypefacesToSend.size()); 293 for (const auto& tf : fTypefacesToSend) serializer.write<WireTypeface>(tf); 294 fTypefacesToSend.clear(); 295 296 serializer.emplace<uint64_t>(fLockedDescs.size()); 297 for (const auto* desc : fLockedDescs) { 298 auto it = fRemoteGlyphStateMap.find(desc); 299 SkASSERT(it != fRemoteGlyphStateMap.end()); 300 it->second->writePendingGlyphs(&serializer); 301 } 302 fLockedDescs.clear(); 303 } 304 305 SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache( 306 const SkPaint& paint, 307 const SkFont& font, 308 const SkSurfaceProps& props, 309 const SkMatrix& matrix, 310 SkScalerContextFlags flags, 311 SkScalerContextEffects* effects) { 312 SkAutoDescriptor keyAutoDesc; 313 auto keyDesc = create_descriptor( 314 kKey, paint, font, matrix, props, flags, &keyAutoDesc, effects); 315 316 // In cases where tracing is turned off, make sure not to get an unused function warning. 317 // Lambdaize the function. 318 TRACE_EVENT1("skia", "RecForDesc", "rec", 319 TRACE_STR_COPY( 320 [keyDesc](){ 321 auto ptr = keyDesc->findEntry(kRec_SkDescriptorTag, nullptr); 322 SkScalerContextRec rec; 323 std::memcpy(&rec, ptr, sizeof(rec)); 324 return rec.dump(); 325 }().c_str() 326 ) 327 ); 328 329 // Already locked. 330 if (fLockedDescs.find(keyDesc) != fLockedDescs.end()) { 331 auto it = fRemoteGlyphStateMap.find(keyDesc); 332 SkASSERT(it != fRemoteGlyphStateMap.end()); 333 SkGlyphCacheState* cache = it->second.get(); 334 cache->setFontAndEffects(font, SkScalerContextEffects{paint}); 335 return cache; 336 } 337 338 // Try to lock. 339 auto it = fRemoteGlyphStateMap.find(keyDesc); 340 if (it != fRemoteGlyphStateMap.end()) { 341 SkGlyphCacheState* cache = it->second.get(); 342 #ifdef SK_DEBUG 343 SkScalerContextEffects deviceEffects; 344 SkAutoDescriptor deviceAutoDesc; 345 auto deviceDesc = create_descriptor( 346 kDevice, paint, font, matrix, props, flags, &deviceAutoDesc, &deviceEffects); 347 SkASSERT(cache->getDeviceDescriptor() == *deviceDesc); 348 #endif 349 bool locked = fDiscardableHandleManager->lockHandle(it->second->discardableHandleId()); 350 if (locked) { 351 fLockedDescs.insert(it->first); 352 cache->setFontAndEffects(font, SkScalerContextEffects{paint}); 353 return cache; 354 } 355 356 // If the lock failed, the entry was deleted on the client. Remove our 357 // tracking. 358 fRemoteGlyphStateMap.erase(it); 359 } 360 361 auto* tf = font.getTypefaceOrDefault(); 362 const SkFontID typefaceId = tf->uniqueID(); 363 if (!fCachedTypefaces.contains(typefaceId)) { 364 fCachedTypefaces.add(typefaceId); 365 fTypefacesToSend.emplace_back(typefaceId, tf->countGlyphs(), tf->fontStyle(), 366 tf->isFixedPitch()); 367 } 368 369 SkScalerContextEffects deviceEffects; 370 SkAutoDescriptor deviceAutoDesc; 371 auto deviceDesc = create_descriptor( 372 kDevice, paint, font, matrix, props, flags, &deviceAutoDesc, &deviceEffects); 373 374 auto context = tf->createScalerContext(deviceEffects, deviceDesc); 375 376 // Create a new cache state and insert it into the map. 377 auto newHandle = fDiscardableHandleManager->createHandle(); 378 auto cacheState = skstd::make_unique<SkGlyphCacheState>( 379 *keyDesc, *deviceDesc, std::move(context), newHandle); 380 381 auto* cacheStatePtr = cacheState.get(); 382 383 fLockedDescs.insert(&cacheStatePtr->getKeyDescriptor()); 384 fRemoteGlyphStateMap[&cacheStatePtr->getKeyDescriptor()] = std::move(cacheState); 385 386 checkForDeletedEntries(); 387 388 cacheStatePtr->setFontAndEffects(font, SkScalerContextEffects{paint}); 389 return cacheStatePtr; 390 } 391 392 void SkStrikeServer::checkForDeletedEntries() { 393 auto it = fRemoteGlyphStateMap.begin(); 394 while (fRemoteGlyphStateMap.size() > fMaxEntriesInDescriptorMap && 395 it != fRemoteGlyphStateMap.end()) { 396 if (fDiscardableHandleManager->isHandleDeleted(it->second->discardableHandleId())) { 397 it = fRemoteGlyphStateMap.erase(it); 398 } else { 399 ++it; 400 } 401 } 402 } 403 404 // -- SkGlyphCacheState ---------------------------------------------------------------------------- 405 SkStrikeServer::SkGlyphCacheState::SkGlyphCacheState( 406 const SkDescriptor& keyDescriptor, 407 const SkDescriptor& deviceDescriptor, 408 std::unique_ptr<SkScalerContext> context, 409 uint32_t discardableHandleId) 410 : fKeyDescriptor{keyDescriptor} 411 , fDeviceDescriptor{deviceDescriptor} 412 , fDiscardableHandleId(discardableHandleId) 413 , fIsSubpixel{context->isSubpixel()} 414 , fAxisAlignmentForHText{context->computeAxisAlignmentForHText()} 415 // N.B. context must come last because it is used above. 416 , fContext{std::move(context)} { 417 SkASSERT(fKeyDescriptor.getDesc() != nullptr); 418 SkASSERT(fDeviceDescriptor.getDesc() != nullptr); 419 SkASSERT(fContext != nullptr); 420 } 421 422 SkStrikeServer::SkGlyphCacheState::~SkGlyphCacheState() = default; 423 424 void SkStrikeServer::SkGlyphCacheState::addGlyph(SkPackedGlyphID glyph, bool asPath) { 425 auto* cache = asPath ? &fCachedGlyphPaths : &fCachedGlyphImages; 426 auto* pending = asPath ? &fPendingGlyphPaths : &fPendingGlyphImages; 427 428 // Already cached. 429 if (cache->contains(glyph)) { 430 return; 431 } 432 433 // A glyph is going to be sent. Make sure we have a scaler context to send it. 434 this->ensureScalerContext(); 435 436 // Serialize and cache. Also create the scalar context to use when serializing 437 // this glyph. 438 cache->add(glyph); 439 pending->push_back(glyph); 440 } 441 442 static void writeGlyph(SkGlyph* glyph, Serializer* serializer) { 443 serializer->write<SkPackedGlyphID>(glyph->getPackedID()); 444 serializer->write<float>(glyph->fAdvanceX); 445 serializer->write<float>(glyph->fAdvanceY); 446 serializer->write<uint16_t>(glyph->fWidth); 447 serializer->write<uint16_t>(glyph->fHeight); 448 serializer->write<int16_t>(glyph->fTop); 449 serializer->write<int16_t>(glyph->fLeft); 450 serializer->write<int8_t>(glyph->fForceBW); 451 serializer->write<uint8_t>(glyph->fMaskFormat); 452 } 453 454 void SkStrikeServer::SkGlyphCacheState::writePendingGlyphs(Serializer* serializer) { 455 // TODO(khushalsagar): Write a strike only if it has any pending glyphs. 456 serializer->emplace<bool>(this->hasPendingGlyphs()); 457 if (!this->hasPendingGlyphs()) { 458 this->resetScalerContext(); 459 return; 460 } 461 462 // Write the desc. 463 serializer->emplace<StrikeSpec>(fContext->getTypeface()->uniqueID(), fDiscardableHandleId); 464 serializer->writeDescriptor(*fKeyDescriptor.getDesc()); 465 466 // Write FontMetrics. 467 // TODO(khushalsagar): Do we need to re-send each time? 468 SkFontMetrics fontMetrics; 469 fContext->getFontMetrics(&fontMetrics); 470 serializer->write<SkFontMetrics>(fontMetrics); 471 472 // Write glyphs images. 473 serializer->emplace<uint64_t>(fPendingGlyphImages.size()); 474 for (const auto& glyphID : fPendingGlyphImages) { 475 SkGlyph glyph{glyphID}; 476 fContext->getMetrics(&glyph); 477 writeGlyph(&glyph, serializer); 478 479 auto imageSize = glyph.computeImageSize(); 480 if (imageSize == 0u) continue; 481 482 glyph.fImage = serializer->allocate(imageSize, glyph.formatAlignment()); 483 fContext->getImage(glyph); 484 // TODO: Generating the image can change the mask format, do we need to update it in the 485 // serialized glyph? 486 } 487 fPendingGlyphImages.clear(); 488 489 // Write glyphs paths. 490 serializer->emplace<uint64_t>(fPendingGlyphPaths.size()); 491 for (const auto& glyphID : fPendingGlyphPaths) { 492 SkGlyph glyph{glyphID}; 493 fContext->getMetrics(&glyph); 494 writeGlyph(&glyph, serializer); 495 writeGlyphPath(glyphID, serializer); 496 } 497 fPendingGlyphPaths.clear(); 498 this->resetScalerContext(); 499 } 500 501 const SkGlyph& SkStrikeServer::SkGlyphCacheState::findGlyph(SkPackedGlyphID glyphID) { 502 SkGlyph* glyphPtr = fGlyphMap.findOrNull(glyphID); 503 if (glyphPtr == nullptr) { 504 glyphPtr = fAlloc.make<SkGlyph>(glyphID); 505 fGlyphMap.set(glyphPtr); 506 this->ensureScalerContext(); 507 fContext->getMetrics(glyphPtr); 508 } 509 510 return *glyphPtr; 511 } 512 513 void SkStrikeServer::SkGlyphCacheState::ensureScalerContext() { 514 if (fContext == nullptr) { 515 auto tf = fFont->getTypefaceOrDefault(); 516 fContext = tf->createScalerContext(fEffects, fDeviceDescriptor.getDesc()); 517 } 518 } 519 520 void SkStrikeServer::SkGlyphCacheState::resetScalerContext() { 521 fContext.reset(); 522 fFont = nullptr; 523 } 524 525 void SkStrikeServer::SkGlyphCacheState::setFontAndEffects( 526 const SkFont& font, SkScalerContextEffects effects) { 527 fFont = &font; 528 fEffects = effects; 529 } 530 531 SkVector SkStrikeServer::SkGlyphCacheState::rounding() const { 532 return SkStrikeCommon::PixelRounding(fIsSubpixel, fAxisAlignmentForHText); 533 } 534 535 const SkGlyph& SkStrikeServer::SkGlyphCacheState::getGlyphMetrics( 536 SkGlyphID glyphID, SkPoint position) { 537 SkIPoint lookupPoint = SkStrikeCommon::SubpixelLookup(fAxisAlignmentForHText, position); 538 SkPackedGlyphID packedGlyphID = fIsSubpixel ? SkPackedGlyphID{glyphID, lookupPoint} 539 : SkPackedGlyphID{glyphID}; 540 541 return this->findGlyph(packedGlyphID); 542 } 543 544 bool SkStrikeServer::SkGlyphCacheState::hasImage(const SkGlyph& glyph) { 545 // If a glyph has width and height, it must have an image available to it. 546 return !glyph.isEmpty(); 547 } 548 549 bool SkStrikeServer::SkGlyphCacheState::hasPath(const SkGlyph& glyph) { 550 return const_cast<SkGlyph&>(glyph).addPath(fContext.get(), &fAlloc) != nullptr; 551 } 552 553 void SkStrikeServer::SkGlyphCacheState::writeGlyphPath(const SkPackedGlyphID& glyphID, 554 Serializer* serializer) const { 555 SkPath path; 556 if (!fContext->getPath(glyphID, &path)) { 557 serializer->write<uint64_t>(0u); 558 return; 559 } 560 561 size_t pathSize = path.writeToMemory(nullptr); 562 serializer->write<uint64_t>(pathSize); 563 path.writeToMemory(serializer->allocate(pathSize, kPathAlignment)); 564 } 565 566 // SkStrikeClient ----------------------------------------- 567 class SkStrikeClient::DiscardableStrikePinner : public SkStrikePinner { 568 public: 569 DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId, 570 sk_sp<DiscardableHandleManager> manager) 571 : fDiscardableHandleId(discardableHandleId), fManager(std::move(manager)) {} 572 573 ~DiscardableStrikePinner() override = default; 574 bool canDelete() override { return fManager->deleteHandle(fDiscardableHandleId); } 575 576 private: 577 const SkDiscardableHandleId fDiscardableHandleId; 578 sk_sp<DiscardableHandleManager> fManager; 579 }; 580 581 SkStrikeClient::SkStrikeClient(sk_sp<DiscardableHandleManager> discardableManager, 582 bool isLogging, 583 SkStrikeCache* strikeCache) 584 : fDiscardableHandleManager(std::move(discardableManager)) 585 , fStrikeCache{strikeCache ? strikeCache : SkStrikeCache::GlobalStrikeCache()} 586 , fIsLogging{isLogging} {} 587 588 SkStrikeClient::~SkStrikeClient() = default; 589 590 #define READ_FAILURE \ 591 { \ 592 SkDEBUGFAIL("Bad serialization"); \ 593 return false; \ 594 } 595 596 static bool readGlyph(SkTLazy<SkGlyph>& glyph, Deserializer* deserializer) { 597 SkPackedGlyphID glyphID; 598 if (!deserializer->read<SkPackedGlyphID>(&glyphID)) return false; 599 glyph.init(glyphID); 600 if (!deserializer->read<float>(&glyph->fAdvanceX)) return false; 601 if (!deserializer->read<float>(&glyph->fAdvanceY)) return false; 602 if (!deserializer->read<uint16_t>(&glyph->fWidth)) return false; 603 if (!deserializer->read<uint16_t>(&glyph->fHeight)) return false; 604 if (!deserializer->read<int16_t>(&glyph->fTop)) return false; 605 if (!deserializer->read<int16_t>(&glyph->fLeft)) return false; 606 if (!deserializer->read<int8_t>(&glyph->fForceBW)) return false; 607 if (!deserializer->read<uint8_t>(&glyph->fMaskFormat)) return false; 608 return true; 609 } 610 611 bool SkStrikeClient::readStrikeData(const volatile void* memory, size_t memorySize) { 612 SkASSERT(memorySize != 0u); 613 Deserializer deserializer(static_cast<const volatile char*>(memory), memorySize); 614 615 uint64_t typefaceSize = 0u; 616 if (!deserializer.read<uint64_t>(&typefaceSize)) READ_FAILURE 617 618 for (size_t i = 0; i < typefaceSize; ++i) { 619 WireTypeface wire; 620 if (!deserializer.read<WireTypeface>(&wire)) READ_FAILURE 621 622 // TODO(khushalsagar): The typeface no longer needs a reference to the 623 // SkStrikeClient, since all needed glyphs must have been pushed before 624 // raster. 625 addTypeface(wire); 626 } 627 628 uint64_t strikeCount = 0u; 629 if (!deserializer.read<uint64_t>(&strikeCount)) READ_FAILURE 630 631 for (size_t i = 0; i < strikeCount; ++i) { 632 bool has_glyphs = false; 633 if (!deserializer.read<bool>(&has_glyphs)) READ_FAILURE 634 635 if (!has_glyphs) continue; 636 637 StrikeSpec spec; 638 if (!deserializer.read<StrikeSpec>(&spec)) READ_FAILURE 639 640 SkAutoDescriptor sourceAd; 641 if (!deserializer.readDescriptor(&sourceAd)) READ_FAILURE 642 643 SkFontMetrics fontMetrics; 644 if (!deserializer.read<SkFontMetrics>(&fontMetrics)) READ_FAILURE 645 646 // Get the local typeface from remote fontID. 647 auto* tf = fRemoteFontIdToTypeface.find(spec.typefaceID)->get(); 648 // Received strikes for a typeface which doesn't exist. 649 if (!tf) READ_FAILURE 650 651 // Replace the ContextRec in the desc from the server to create the client 652 // side descriptor. 653 // TODO: Can we do this in-place and re-compute checksum? Instead of a complete copy. 654 SkAutoDescriptor ad; 655 auto* client_desc = auto_descriptor_from_desc(sourceAd.getDesc(), tf->uniqueID(), &ad); 656 657 auto strike = fStrikeCache->findStrikeExclusive(*client_desc); 658 if (strike == nullptr) { 659 // Note that we don't need to deserialize the effects since we won't be generating any 660 // glyphs here anyway, and the desc is still correct since it includes the serialized 661 // effects. 662 SkScalerContextEffects effects; 663 auto scaler = SkStrikeCache::CreateScalerContext(*client_desc, effects, *tf); 664 strike = fStrikeCache->createStrikeExclusive( 665 *client_desc, std::move(scaler), &fontMetrics, 666 skstd::make_unique<DiscardableStrikePinner>(spec.discardableHandleId, 667 fDiscardableHandleManager)); 668 auto proxyContext = static_cast<SkScalerContextProxy*>(strike->getScalerContext()); 669 proxyContext->initCache(strike.get(), fStrikeCache); 670 } 671 672 uint64_t glyphImagesCount = 0u; 673 if (!deserializer.read<uint64_t>(&glyphImagesCount)) READ_FAILURE 674 for (size_t j = 0; j < glyphImagesCount; j++) { 675 SkTLazy<SkGlyph> glyph; 676 if (!readGlyph(glyph, &deserializer)) READ_FAILURE 677 678 SkGlyph* allocatedGlyph = strike->getRawGlyphByID(glyph->getPackedID()); 679 680 // Update the glyph unless it's already got an image (from fallback), 681 // preserving any path that might be present. 682 if (allocatedGlyph->fImage == nullptr) { 683 auto* glyphPath = allocatedGlyph->fPathData; 684 *allocatedGlyph = *glyph; 685 allocatedGlyph->fPathData = glyphPath; 686 } 687 688 auto imageSize = glyph->computeImageSize(); 689 if (imageSize == 0u) continue; 690 691 auto* image = deserializer.read(imageSize, allocatedGlyph->formatAlignment()); 692 if (!image) READ_FAILURE 693 strike->initializeImage(image, imageSize, allocatedGlyph); 694 } 695 696 uint64_t glyphPathsCount = 0u; 697 if (!deserializer.read<uint64_t>(&glyphPathsCount)) READ_FAILURE 698 for (size_t j = 0; j < glyphPathsCount; j++) { 699 SkTLazy<SkGlyph> glyph; 700 if (!readGlyph(glyph, &deserializer)) READ_FAILURE 701 702 SkGlyph* allocatedGlyph = strike->getRawGlyphByID(glyph->getPackedID()); 703 704 // Update the glyph unless it's already got a path (from fallback), 705 // preserving any image that might be present. 706 if (allocatedGlyph->fPathData == nullptr) { 707 auto* glyphImage = allocatedGlyph->fImage; 708 *allocatedGlyph = *glyph; 709 allocatedGlyph->fImage = glyphImage; 710 } 711 712 if (!read_path(&deserializer, allocatedGlyph, strike.get())) READ_FAILURE 713 } 714 } 715 716 return true; 717 } 718 719 sk_sp<SkTypeface> SkStrikeClient::deserializeTypeface(const void* buf, size_t len) { 720 WireTypeface wire; 721 if (len != sizeof(wire)) return nullptr; 722 memcpy(&wire, buf, sizeof(wire)); 723 return this->addTypeface(wire); 724 } 725 726 sk_sp<SkTypeface> SkStrikeClient::addTypeface(const WireTypeface& wire) { 727 auto* typeface = fRemoteFontIdToTypeface.find(wire.typefaceID); 728 if (typeface) return *typeface; 729 730 auto newTypeface = sk_make_sp<SkTypefaceProxy>( 731 wire.typefaceID, wire.glyphCount, wire.style, wire.isFixed, 732 fDiscardableHandleManager, fIsLogging); 733 fRemoteFontIdToTypeface.set(wire.typefaceID, newTypeface); 734 return std::move(newTypeface); 735 } 736