Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Experimental Text Node Implementation #259

Merged
merged 6 commits into from
May 14, 2017
Merged

Conversation

Adlai-Holler
Copy link
Member

https://paper.dropbox.com/doc/ASTextNode-Experimental-Replacement-bswIlZJjmjDj1fJjwegzH

I'd like to get this reviewed and merged so that we can start experimenting with it in Pinterest and YouTube, even though the experimental implementation is missing some features.

@garrettmoon @nguyenhuy @maicki @appleguy

cc #221 & #227

@ghost
Copy link

ghost commented May 11, 2017

🚫 CI failed with log

@nguyenhuy
Copy link
Member

nguyenhuy commented May 11, 2017

Not sure if GitHub is messing with me, or this diff actually has 10k lines :P

Can we somehow break it into chunks? And/or link against YYText (if you haven't done so)?

@maicki
Copy link
Contributor

maicki commented May 11, 2017

@nguyenhuy My understanding is that this diff is really 10k lines :) We don't fully link against YYText as we don't need all of the components, furthermore it seems like the projects is kind of a dead state :/

@Adlai-Holler
Copy link
Member Author

Lol yep the diff is 10k lines. I think we shouldn't link to YYText since it's dead, since we don't need most of it, since we will need to fork it to make modifications (I've already found one, around the shadowing of truncated lines), and also because it's a hassle to our users.

@nguyenhuy
Copy link
Member

OK. So that's 10k lines we're gonna closely review now and maintain later. However, if the code quality and architecture is better than our current implementation, and if in the future we'll completely switch to it, it might actually turn out to be a net gain!

Copy link
Member

@garrettmoon garrettmoon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jesus I hope I reviewed the right parts.


// They must call this before allocating any text nodes.
ASDisplayNodeAssertFalse(_hasAllocatedNode);
ASDisplayNodeAssert(_experimentOptions == 0, @"Can't call +setExperimentOptions: more than once.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You sure can't it's in a dispatch_once

{
NSString *plainString = [[self.attributedText string] stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
if (plainString.length > 50) {
plainString = [[plainString substringToIndex:50] stringByAppendingString:@"\u2026"];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super super nit, I assume this evaluates to , maybe just use the character?

// We discard the backing store and renderer to prevent the very large
// memory overhead of maintaining these for all text nodes. They can be
// regenerated when layout is necessary.
[super clearContents]; // ASDisplayNode will set layer.contents = nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this method necessary?

return layout.textBoundingSize;


// ASTextKitRenderer *renderer = [self _rendererWithBoundsSlow:{.size = constrainedSize}];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete?


// Accessiblity
self.accessibilityLabel = attributedText.string;
self.isAccessibilityElement = (length != 0); // We're an accessibility element by default if there is a string.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not, but is there any way attributedText.length could be different than attributedText.string.length?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No I don't think so.

textLayoutCache = [[NSCache alloc] init];
});

ASTextCacheValue *cacheValue = ({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens below when a bunch of nodes with the same text all go through this path? The first one sets an empty cache value and the rest of them get it. Then they all 'cache miss' below and layout?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. It's an acceptable tradeoff, since (1) we will mostly be doing sequential passes on the same attributed string, not parallel ones and (2) the alternative would either be complex or amount to having all other text-layout work wait.

{
std::lock_guard<std::mutex> lock(cacheValue->_m);
cacheValue->_layouts.push_front(std::make_tuple(container.size, layout));
if (cacheValue->_layouts.size() > 3) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is 3 a magic number? I wonder if there's value in having control of this. My guess is specific strings have layouts that would be worth caching and most have 0

Copy link
Member Author

@Adlai-Holler Adlai-Holler May 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is 3 a magic number?

Yes.

I wonder if there's value in having control of this. My guess is specific strings have layouts that would be worth caching and most have 0

No probably not. This cache is primarily intended to serve between layout passes and displays of the same text node. Any benefit that we get across the app is negligible (but great!).

std::lock_guard<std::mutex> lock(cacheValue->_m);
cacheValue->_layouts.push_front(std::make_tuple(container.size, layout));
if (cacheValue->_layouts.size() > 3) {
cacheValue->_layouts.pop_back();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh, not sure how much it's worth optimizing, but it may be worth making this LRU as opposed to first layout loses.

Copy link
Member Author

@Adlai-Holler Adlai-Holler May 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, a couple lines up there is a TODO for this.

return _shadowColor;
}

- (void)setShadowColor:(CGColorRef)shadowColor
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should take this opportunity to make it a UIColor?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No because this property is inherited from ASDisplayNode.

ASTextTruncationType yyType;
switch (truncationMode) {
case NSLineBreakByTruncatingHead:
yyType = ASTextTruncationTypeStart;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the license at the top of this needs to give credit to yy?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No this file uses code from YY but it's all our code.

@Adlai-Holler
Copy link
Member Author

@garrettmoon Thanks for reviewing this. What should we do about the license text? Two issues we need to deal with:

  • KittenNode.mm: This is just the fact that our example apps never got that initial header-update pass. We should open a new PR that updates them.
  • The files from YYText: We need to figure out a way to get danger to accept the YYText-modified version of the header.

Or we can remove the header danger rule. I don't think it's adding much value right now.

@ghost
Copy link

ghost commented May 14, 2017

21 Warnings
⚠️ This is a big PR, please consider splitting it up to ease code review.
⚠️ Please ensure license is correct for ASTextDebugOption.h:

//
//  ASTextDebugOption.h
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for NSParagraphStyle+ASText.h:

//
//  NSParagraphStyle+ASText.h
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for ASTextDebugOption.m:

//
//  ASTextDebugOption.m
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for ASTextUtilities.h:

//
//  ASTextUtilities.h
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for ASTextInput.h:

//
//  ASTextInput.h
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for ASTextRunDelegate.h:

//
//  ASTextRunDelegate.h
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for ASTextInput.m:

//
//  ASTextInput.m
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for NSAttributedString+ASText.h:

//
//  NSAttributedString+ASText.h
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for ASTextLayout.h:

//
//  ASTextLayout.h
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for AppDelegate.m:

//
//  AppDelegate.m
//  Texture
//
//  Copyright (c) 2014-present, Facebook, Inc.  All rights reserved.
//  This source code is licensed under the BSD-style license found in the
//  LICENSE file in the /ASDK-Licenses directory of this source tree. An additional
//  grant of patent rights can be found in the PATENTS file in the same directory.
//
//  Modifications to this file made after 4/13/2017 are: Copyright (c) 2017-present,
//  Pinterest, Inc.  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for ASTextLayout.m:

//
//  ASTextLayout.m
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for ASTextRunDelegate.m:

//
//  ASTextRunDelegate.m
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for ASTextLine.h:

//
//  ASTextLine.h
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for ASTextUtilities.m:

//
//  ASTextUtilities.m
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for ASTextLine.m:

//
//  ASTextLine.m
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for NSAttributedString+ASText.m:

//
//  NSAttributedString+ASText.m
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for ASTextAttribute.h:

//
//  ASTextAttribute.h
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for NSParagraphStyle+ASText.m:

//
//  NSParagraphStyle+ASText.m
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for ASTextAttribute.m:

//
//  ASTextAttribute.m
//  Texture
//
//  Copyright (c) 2017-present, Pinterest, Inc.  All rights reserved.
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    
⚠️ Please ensure license is correct for KittenNode.mm:

//
//  KittenNode.mm
//  Texture
//
//  Copyright (c) 2014-present, Facebook, Inc.  All rights reserved.
//  This source code is licensed under the BSD-style license found in the
//  LICENSE file in the /ASDK-Licenses directory of this source tree. An additional
//  grant of patent rights can be found in the PATENTS file in the same directory.
//
//  Modifications to this file made after 4/13/2017 are: Copyright (c) 2017-present,
//  Pinterest, Inc.  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//

    

Generated by 🚫 Danger

@Adlai-Holler
Copy link
Member Author

In order to keep moving, I'm going to land this with the YYText-header warnings and the one from KittenNode.mm intact. @garrettmoon Let's run a pass updating the license headers in the sample code, or update or disable the license header rule altogether.

@Adlai-Holler Adlai-Holler merged commit d4725a5 into master May 14, 2017
@Adlai-Holler Adlai-Holler deleted the AHTextImprovements branch May 14, 2017 19:02
@ghost
Copy link

ghost commented May 14, 2017

🚫 CI failed with log

@ghost
Copy link

ghost commented May 14, 2017

🚫 CI failed with log

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants