@@ -429,6 +429,33 @@ void SkStrikeServer::writeStrikeData(std::vector<uint8_t>* memory) {
429429 fLockedDescs .clear ();
430430}
431431
432+ SkStrikeServer::SkGlyphCacheState::SkGlyphCacheState (
433+ std::unique_ptr<SkDescriptor> keyDescriptor, uint32_t discardableHandleId)
434+ : fKeyDescriptor(std::move(keyDescriptor))
435+ , fDiscardableHandleId(discardableHandleId) {
436+ SkASSERT (fKeyDescriptor );
437+ }
438+
439+ SkStrikeServer::SkGlyphCacheState::~SkGlyphCacheState () = default ;
440+
441+ void SkStrikeServer::SkGlyphCacheState::ensureScalerContext (
442+ const SkPaint& paint,
443+ const SkSurfaceProps* props,
444+ const SkMatrix* matrix,
445+ SkScalerContextFlags flags,
446+ SkScalerContextEffects* effects) {
447+ if (fContext == nullptr || fDeviceDescriptor == nullptr ) {
448+ SkScalerContextRec deviceRec;
449+ SkScalerContext::MakeRecAndEffects (paint, props, matrix, flags, &deviceRec, effects, true );
450+ auto deviceDesc = SkScalerContext::DescriptorGivenRecAndEffects (deviceRec, *effects);
451+ auto * tf = paint.getTypeface ();
452+ fContext = tf->createScalerContext (*effects, deviceDesc.get (), false );
453+ fIsSubpixel = fContext ->isSubpixel ();
454+ fAxisAlignmentForHText = fContext ->computeAxisAlignmentForHText ();
455+ fDeviceDescriptor = std::move (deviceDesc);
456+ }
457+ }
458+
432459SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache (
433460 const SkPaint& paint,
434461 const SkSurfaceProps* props,
@@ -444,22 +471,26 @@ SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache(
444471 if (fLockedDescs .find (keyDesc.get ()) != fLockedDescs .end ()) {
445472 auto it = fRemoteGlyphStateMap .find (keyDesc.get ());
446473 SkASSERT (it != fRemoteGlyphStateMap .end ());
447- return it->second .get ();
474+ SkGlyphCacheState* cache = it->second .get ();
475+ cache->ensureScalerContext (paint, props, matrix, flags, effects);
476+ return cache;
448477 }
449478
450479 // Try to lock.
451480 auto it = fRemoteGlyphStateMap .find (keyDesc.get ());
452481 if (it != fRemoteGlyphStateMap .end ()) {
482+ SkGlyphCacheState* cache = it->second .get ();
453483#ifdef SK_DEBUG
454484 SkScalerContextRec deviceRec;
455485 SkScalerContext::MakeRecAndEffects (paint, props, matrix, flags, &deviceRec, effects, true );
456486 auto deviceDesc = SkScalerContext::DescriptorGivenRecAndEffects (deviceRec, *effects);
457- SkASSERT (it-> second ->getDeviceDescriptor () == *deviceDesc);
487+ SkASSERT (cache ->getDeviceDescriptor () == *deviceDesc);
458488#endif
459489 bool locked = fDiscardableHandleManager ->lockHandle (it->second ->discardableHandleId ());
460490 if (locked) {
461491 fLockedDescs .insert (it->first );
462- return it->second .get ();
492+ cache->ensureScalerContext (paint, props, matrix, flags, effects);
493+ return cache;
463494 }
464495
465496 // If the lock failed, the entry was deleted on the client. Remove our
@@ -475,39 +506,18 @@ SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache(
475506 tf->isFixedPitch ());
476507 }
477508
478- SkScalerContextRec deviceRec;
479- SkScalerContext::MakeRecAndEffects (paint, props, matrix, flags, &deviceRec, effects, true );
480- auto deviceDesc = SkScalerContext::DescriptorGivenRecAndEffects (deviceRec, *effects);
481-
509+ // Create a new cache state and insert it into the map.
482510 auto * keyDescPtr = keyDesc.get ();
483511 auto newHandle = fDiscardableHandleManager ->createHandle ();
484- auto scalerContext = tf->createScalerContext (*effects, deviceDesc.get (), false );
485- auto cacheState = skstd::make_unique<SkGlyphCacheState>(
486- std::move (deviceDesc), std::move (keyDesc), newHandle, std::move (scalerContext));
512+ auto cacheState = skstd::make_unique<SkGlyphCacheState>(std::move (keyDesc), newHandle);
487513 auto * cacheStatePtr = cacheState.get ();
488514
489515 fLockedDescs .insert (keyDescPtr);
490516 fRemoteGlyphStateMap [keyDescPtr] = std::move (cacheState);
517+ cacheStatePtr->ensureScalerContext (paint, props, matrix, flags, effects);
491518 return cacheStatePtr;
492519}
493520
494- SkStrikeServer::SkGlyphCacheState::SkGlyphCacheState (std::unique_ptr<SkDescriptor> deviceDescriptor,
495- std::unique_ptr<SkDescriptor>
496- keyDescriptor,
497- uint32_t discardableHandleId,
498- std::unique_ptr<SkScalerContext> context)
499- : fDeviceDescriptor(std::move(deviceDescriptor))
500- , fKeyDescriptor(std::move(keyDescriptor))
501- , fDiscardableHandleId(discardableHandleId)
502- , fContext(std::move(context))
503- , fIsSubpixel(fContext ->isSubpixel ())
504- , fAxisAlignmentForHText(fContext ->computeAxisAlignmentForHText ()) {
505- SkASSERT (fDeviceDescriptor );
506- SkASSERT (fKeyDescriptor );
507- }
508-
509- SkStrikeServer::SkGlyphCacheState::~SkGlyphCacheState () = default ;
510-
511521void SkStrikeServer::SkGlyphCacheState::addGlyph (SkPackedGlyphID glyph, bool asPath) {
512522 auto * cache = asPath ? &fCachedGlyphPaths : &fCachedGlyphImages ;
513523 auto * pending = asPath ? &fPendingGlyphPaths : &fPendingGlyphImages ;
@@ -525,6 +535,8 @@ void SkStrikeServer::SkGlyphCacheState::writePendingGlyphs(Serializer* serialize
525535 // TODO(khushalsagar): Write a strike only if it has any pending glyphs.
526536 serializer->emplace <bool >(this ->hasPendingGlyphs ());
527537 if (!this ->hasPendingGlyphs ()) {
538+ // See comment below for reset.
539+ fContext .reset ();
528540 return ;
529541 }
530542
@@ -591,6 +603,10 @@ void SkStrikeServer::SkGlyphCacheState::writePendingGlyphs(Serializer* serialize
591603 writeGlyphPath (glyphID, serializer);
592604 }
593605 fPendingGlyphPaths .clear ();
606+
607+ // Note that we reset the context after serializing pending glyphs since we
608+ // don't want to extend the lifetime of the typeface.
609+ fContext .reset ();
594610}
595611
596612const SkGlyph& SkStrikeServer::SkGlyphCacheState::findGlyph (SkPackedGlyphID glyphID) {
0 commit comments