From 3ebdf5928cee55cf0a1a6fd740bf777e21733f5f Mon Sep 17 00:00:00 2001 From: rcancro Date: Tue, 8 Mar 2016 12:05:26 -0800 Subject: [PATCH 1/2] Made a few changes to font scale adjustment 1) cache the scale in the font adjuster. The adjuster will be dealloc'ed when the renderer that owns it is dealloc'ed (or invalidated). Until that time we can trust the scale that the adjuster has computed. 2) When measuring line count, make sure that we are not bounding the height of the container's size. This will cause the wrong number of lines to be returned. 3) Instead of setting the ascender/descender on an ASTextNode when an attributed string is added, wait until after the renderer calculates size. This way, if there is any need to scale the font to fit we can apply that scale to the ascender/descender. --- AsyncDisplayKit/ASTextNode.mm | 19 ++++++++++++------- .../TextKit/ASTextKitFontSizeAdjuster.mm | 16 +++++++++++++--- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/AsyncDisplayKit/ASTextNode.mm b/AsyncDisplayKit/ASTextNode.mm index 237c043431..daecff0714 100644 --- a/AsyncDisplayKit/ASTextNode.mm +++ b/AsyncDisplayKit/ASTextNode.mm @@ -337,7 +337,18 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; [self setNeedsDisplay]; - return [[self _renderer] size]; + CGSize size = [[self _renderer] size]; + if (self.attributedString.length > 0) { + CGFloat screenScale = ASScreenScale(); + self.ascender = round([[_attributedString attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL] ascender] * screenScale)/screenScale; + self.descender = round([[_attributedString attribute:NSFontAttributeName atIndex:_attributedString.length - 1 effectiveRange:NULL] descender] * screenScale)/screenScale; + if (_renderer.currentScaleFactor > 0 && _renderer.currentScaleFactor < 1.0) { + // while not perfect, this is a good estimate of what the ascender of the scaled font will be. + self.ascender *= _renderer.currentScaleFactor; + self.descender *= _renderer.currentScaleFactor; + } + } + return size; } #pragma mark - Modifying User Text @@ -375,12 +386,6 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; } else { self.isAccessibilityElement = YES; } - - if (attributedString.length > 0) { - CGFloat screenScale = ASScreenScale(); - self.ascender = round([[attributedString attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL] ascender] * screenScale)/screenScale; - self.descender = round([[attributedString attribute:NSFontAttributeName atIndex:attributedString.length - 1 effectiveRange:NULL] descender] * screenScale)/screenScale; - } } #pragma mark - Text Layout diff --git a/AsyncDisplayKit/TextKit/ASTextKitFontSizeAdjuster.mm b/AsyncDisplayKit/TextKit/ASTextKitFontSizeAdjuster.mm index f881ae5f34..5a2289582d 100644 --- a/AsyncDisplayKit/TextKit/ASTextKitFontSizeAdjuster.mm +++ b/AsyncDisplayKit/TextKit/ASTextKitFontSizeAdjuster.mm @@ -20,6 +20,8 @@ __weak ASTextKitContext *_context; ASTextKitAttributes _attributes; std::mutex _textKitMutex; + BOOL _measured; + CGFloat _scaleFactor; } - (instancetype)initWithContext:(ASTextKitContext *)context @@ -85,7 +87,7 @@ NSLayoutManager *layoutManager = _attributes.layoutManagerCreationBlock ? _attributes.layoutManagerCreationBlock() : [[ASLayoutManager alloc] init]; layoutManager.usesFontLeading = NO; [textStorage addLayoutManager:layoutManager]; - NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:_constrainedSize]; + NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(_constrainedSize.width, FLT_MAX)]; textContainer.lineFragmentPadding = 0; textContainer.lineBreakMode = _attributes.lineBreakMode; @@ -104,8 +106,14 @@ - (CGFloat)scaleFactor { + if (_measured) { + return _scaleFactor; + } + if ([_attributes.pointSizeScaleFactors count] == 0 || isinf(_constrainedSize.width)) { - return 1.0; + _measured = YES; + _scaleFactor = 1.0; + return _scaleFactor; } __block CGFloat adjustedScale = 1.0; @@ -177,7 +185,9 @@ } }]; - return adjustedScale; + _measured = YES; + _scaleFactor = adjustedScale; + return _scaleFactor; } @end From 06a6bd660619af8a2d116f3df042fc88175da0d8 Mon Sep 17 00:00:00 2001 From: rcancro Date: Tue, 8 Mar 2016 16:32:24 -0800 Subject: [PATCH 2/2] fix typo and kick off build again. --- AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm b/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm index 57fd1b4c6d..28f19ffd77 100644 --- a/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm +++ b/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm @@ -72,7 +72,7 @@ ASStackBaselinePositionedLayout ASStackBaselinePositionedLayout::compute(const A baseline will be larger so we will keep that as the max baseline. However, if were to align from the last baseline we'd find the max baseline by taking the height of node and adding - the font's descender (its negative). In the case of the first node, which is only 1 line, this should be the same value as the ascender. + the font's descender (it's negative). In the case of the first node, which is only 1 line, this should be the same value as the ascender. The second node, however, has a larger height and there will have a larger baseline offset. */ const auto baselineIt = std::max_element(positionedLayout.sublayouts.begin(), positionedLayout.sublayouts.end(), [&](const ASLayout *a, const ASLayout *b){