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

CATiledLayer for large chunks of text #14

Open
rnystrom opened this issue May 29, 2018 · 3 comments
Open

CATiledLayer for large chunks of text #14

rnystrom opened this issue May 29, 2018 · 3 comments

Comments

@rnystrom
Copy link
Member

Idk how best to combine these, but would improve rendering huge chunks of text.

  • mmap bitmap from disk
  • All layers in memory defeats the purpose
  • LRUCache can store chunks?
@rnystrom
Copy link
Member Author

@ocrickard
Copy link
Contributor

Yeah, big fan of CATiledLayer for huge chunks of text. However, they are REALLY heavy weight on memory and bad for scroll perf if you have a bunch of them on the screen at once (I tested this awhile ago). In my other text impl I worked on in 2015 in my spare time I came up with the idea of a dual CALayer/CATiledLayer impl that basically uses the layers as stupid shells, and encapsulates logic in a layer render delegate. It's a kind of complicated dance that I'm sure could be simplified.

I pulled the impl from my old project:

https://gist.github.com/ocrickard/9892a28cfd733a84fed95b2a66f27615

Anyway, if you're looking for inspiration, that impl performs great both in tiny little labels, and in huuuge walls of text.

@rnystrom
Copy link
Member Author

TIL!!

I've never used it before, spared me a lot of time figuring this out lol. I bet the async drawing will be a good quick win. Then if we (or someone else) is hitting huge perf issues from drawing giant bitmaps, then we can find a way to make this work.

facebook-github-bot pushed a commit to facebook/react-native that referenced this issue Jun 24, 2019
Summary:
The current technique we use to draw text uses linear memory, which means that when text is too long the UIView layer is unable to draw it. This causes the issue described [here](#19453). On an iOS simulator the bug happens at around 500 lines which is quite annoying. It can also happen on a real device but requires a lot more text.

To be more specific the amount of text doesn't actually matter, it is the size of the UIView that we use to draw the text. When we use `[drawRect:]` the view creates a bitmap to send to the gpu to render, if that bitmap is too big it cannot render.

To fix this we can use `CATiledLayer` which will split drawing into smaller parts, that gets executed when the content is about to be visible. This drawing is also async which means the text can seem to appear during scroll. See https://developer.apple.com/documentation/quartzcore/calayer?language=objc.

`CATiledLayer` also adds some overhead that we don't want when rendering small amount of text. To fix this we can use either a regular `CALayer` or a `CATiledLayer` depending on the size of the view containing the text. I picked 1024 as the threshold which is about 1 screen and a half, and is still smaller than the height needed for the bug to occur when using a regular `CALayer` on a iOS simulator.

Also found this which addresses the problem in a similar manner and took some inspiration from the code linked there GitHawkApp/StyledTextKit#14 (comment)

Fixes #19453

## Changelog

[iOS] [Fixed] - Use CALayers to draw text, fixes rendering for long text
Pull Request resolved: #24387

Test Plan:
- Added the example I was using to verify the fix to RNTester.
- Made sure all other examples are still rendering properly.
- Tested text selection

Reviewed By: shergin

Differential Revision: D15918277

Pulled By: sammy-SC

fbshipit-source-id: c45409a8413e6e3ad272be39ba527a4e8d349e28
kelset pushed a commit to facebook/react-native that referenced this issue Jun 28, 2019
Summary:
The current technique we use to draw text uses linear memory, which means that when text is too long the UIView layer is unable to draw it. This causes the issue described [here](#19453). On an iOS simulator the bug happens at around 500 lines which is quite annoying. It can also happen on a real device but requires a lot more text.

To be more specific the amount of text doesn't actually matter, it is the size of the UIView that we use to draw the text. When we use `[drawRect:]` the view creates a bitmap to send to the gpu to render, if that bitmap is too big it cannot render.

To fix this we can use `CATiledLayer` which will split drawing into smaller parts, that gets executed when the content is about to be visible. This drawing is also async which means the text can seem to appear during scroll. See https://developer.apple.com/documentation/quartzcore/calayer?language=objc.

`CATiledLayer` also adds some overhead that we don't want when rendering small amount of text. To fix this we can use either a regular `CALayer` or a `CATiledLayer` depending on the size of the view containing the text. I picked 1024 as the threshold which is about 1 screen and a half, and is still smaller than the height needed for the bug to occur when using a regular `CALayer` on a iOS simulator.

Also found this which addresses the problem in a similar manner and took some inspiration from the code linked there GitHawkApp/StyledTextKit#14 (comment)

Fixes #19453

## Changelog

[iOS] [Fixed] - Use CALayers to draw text, fixes rendering for long text
Pull Request resolved: #24387

Test Plan:
- Added the example I was using to verify the fix to RNTester.
- Made sure all other examples are still rendering properly.
- Tested text selection

Reviewed By: shergin

Differential Revision: D15918277

Pulled By: sammy-SC

fbshipit-source-id: c45409a8413e6e3ad272be39ba527a4e8d349e28
M-i-k-e-l pushed a commit to M-i-k-e-l/react-native that referenced this issue Mar 10, 2020
Summary:
The current technique we use to draw text uses linear memory, which means that when text is too long the UIView layer is unable to draw it. This causes the issue described [here](facebook#19453). On an iOS simulator the bug happens at around 500 lines which is quite annoying. It can also happen on a real device but requires a lot more text.

To be more specific the amount of text doesn't actually matter, it is the size of the UIView that we use to draw the text. When we use `[drawRect:]` the view creates a bitmap to send to the gpu to render, if that bitmap is too big it cannot render.

To fix this we can use `CATiledLayer` which will split drawing into smaller parts, that gets executed when the content is about to be visible. This drawing is also async which means the text can seem to appear during scroll. See https://developer.apple.com/documentation/quartzcore/calayer?language=objc.

`CATiledLayer` also adds some overhead that we don't want when rendering small amount of text. To fix this we can use either a regular `CALayer` or a `CATiledLayer` depending on the size of the view containing the text. I picked 1024 as the threshold which is about 1 screen and a half, and is still smaller than the height needed for the bug to occur when using a regular `CALayer` on a iOS simulator.

Also found this which addresses the problem in a similar manner and took some inspiration from the code linked there GitHawkApp/StyledTextKit#14 (comment)

Fixes facebook#19453

## Changelog

[iOS] [Fixed] - Use CALayers to draw text, fixes rendering for long text
Pull Request resolved: facebook#24387

Test Plan:
- Added the example I was using to verify the fix to RNTester.
- Made sure all other examples are still rendering properly.
- Tested text selection

Reviewed By: shergin

Differential Revision: D15918277

Pulled By: sammy-SC

fbshipit-source-id: c45409a8413e6e3ad272be39ba527a4e8d349e28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants