Bug 189119 - Remove redundant inline text boxes for empty combined text
Summary: Remove redundant inline text boxes for empty combined text
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Text (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Daniel Bates
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2018-08-29 16:30 PDT by Daniel Bates
Modified: 2018-09-04 11:22 PDT (History)
6 users (show)

See Also:


Attachments
Patch (7.69 KB, patch)
2018-08-29 16:49 PDT, Daniel Bates
no flags Details | Formatted Diff | Diff
Patch (8.48 KB, patch)
2018-08-30 11:09 PDT, Daniel Bates
zalan: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Bates 2018-08-29 16:30:07 PDT
While investigating bug #184390 I discovered that we are creating empty inline text boxes for combined text. We should look to avoid doing this both to save memory and make it easier to reason about painting of text.
Comment 1 Daniel Bates 2018-08-29 16:33:42 PDT
An empty inline text box does not visually effect the rendering of the page.
Comment 2 Daniel Bates 2018-08-29 16:49:54 PDT
Created attachment 348448 [details]
Patch
Comment 3 Daniel Bates 2018-08-30 10:21:54 PDT
(In reply to Daniel Bates from comment #0)
> While investigating bug #184390 I discovered that we are creating empty
> inline text boxes for combined text. We should look to avoid doing this both
> to save memory and make it easier to reason about painting of text.

To be more precise: I discovered that our logic for removing "redundant" inline text boxes does not remove inline text boxes for empty combined texts. It does remove inline text boxes for non-combined text that are empty. We should consider inline text boxes with empty combined text to also be empty and remove such boxes because they have not visual appearance, take up memory, and make it harder to reason about painting of the inline text box tree (since we currently need to explicitly consider the case of an inline text box with a RenderCombineText renderer whose combined text string is the empty string as opposed to the higher level concept of whether the box is visually empty).
Comment 4 Daniel Bates 2018-08-30 10:41:13 PDT
For those not familiar with the concept of combined text. Combined text is defined to be "the combination of multiple typographic character units into the space of a single typographic character unit. The resulting composition is treated as a single upright glyph for the purposes of layout and decoration." (https://drafts.csswg.org/css-writing-modes-4/#propdef-text-combine-upright; Editor's Draft, 17 August 2018). We model this in the engine with an inline text box that has length 1 (InlineTextBox::len() == 1) and its associated renderer (RenderCombineText) stores the resulting composition to be rendered in the box (RenderCombineText::combinedStringForRendering()).

Additional remarks:

Notice that inline text boxes hang off of renderers and we only create a text renderer if the underlying DOM text node is non-empty by RenderTreeUpdater::textRendererIsNeeded().

DOM operations, including Range.surroundContents(), can mutate both the DOM text nodes and the text in the associated renderers such that the composed string stored in a RenderCombineText can become the empty string (RenderCombineText::combinedStringForRendering().isEmpty() evaluates to true).
Comment 5 Daniel Bates 2018-08-30 11:02:42 PDT
Comment on attachment 348448 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=348448&action=review

> Source/WebCore/ChangeLog:10
> +        An empty inline text box does not visually effect the rendering of the page. We should not
> +        create such text boxes both to reduce memory and to make it easier to reason about the line
> +        box tree.

Will update this before landing to read:

We should consider inline text boxes that have a combined text renderer (RenderCombineText) whose composed string is empty as "redundant" just as we do for inline text boxes that have a non-combined text renderer that have zero length so that we remove them. Such boxes are visibly empty and do not take up space visually. By removing them we reduce memory and make it easier to reason about the line box tree.

Currently RenderBlockFlow::computeBlockDirectionPositionsForLine() tests if an inline text box is empty by checking if it has a zero length (InlineTextBox::len()). However an inline text box associated with a RenderCombineText always has length 1 regardless of whether the composed string it represents is the empty string. Instead we should expose a way to check if an inline text box is visually empty and have RenderBlockFlow::computeBlockDirectionPositionsForLine() query the inline text box for this answer.
Comment 6 Daniel Bates 2018-08-30 11:09:12 PDT
Created attachment 348510 [details]
Patch

Updated ChangeLogs to reflect updated title and my remarks in comment 5.
Comment 7 Brent Fulgham 2018-08-30 11:11:24 PDT
Comment on attachment 348510 [details]
Patch

I think this change looks good, but I'd like Alan or Myles to give it a look, too.
Comment 8 zalan 2018-08-30 13:59:39 PDT
Comment on attachment 348510 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=348510&action=review

> Source/WebCore/rendering/InlineTextBox.cpp:79
> +bool InlineTextBox::isEmpty() const

In some cases we use "empty" in the context of something is _visually_ empty. I'd rather try the term hasTextContent() or something along those lines.
Comment 9 Daniel Bates 2018-09-04 09:37:54 PDT
(In reply to zalan from comment #8)
> Comment on attachment 348510 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=348510&action=review
> 
> > Source/WebCore/rendering/InlineTextBox.cpp:79
> > +bool InlineTextBox::isEmpty() const
> 
> In some cases we use "empty" in the context of something is _visually_
> empty. I'd rather try the term hasTextContent() or something along those
> lines.

Will rename isEmpty() to hasTextContent() before landing.
Comment 10 Daniel Bates 2018-09-04 10:02:00 PDT
(In reply to Daniel Bates from comment #9)
> (In reply to zalan from comment #8)
> > Comment on attachment 348510 [details]
> > Patch
> > 
> > View in context:
> > https://bugs.webkit.org/attachment.cgi?id=348510&action=review
> > 
> > > Source/WebCore/rendering/InlineTextBox.cpp:79
> > > +bool InlineTextBox::isEmpty() const
> > 
> > In some cases we use "empty" in the context of something is _visually_
> > empty. I'd rather try the term hasTextContent() or something along those
> > lines.
> 
> Will rename isEmpty() to hasTextContent() before landing.

Clearly, I will also need to invert the logic in InlineTextBox::isEmpty() such that it return true if the text box has content and false otherwise.
Comment 11 Daniel Bates 2018-09-04 10:02:51 PDT
Committed r235615: <https://trac.webkit.org/changeset/235615>
Comment 12 Radar WebKit Bug Importer 2018-09-04 10:03:20 PDT
<rdar://problem/44101162>
Comment 13 Daniel Bates 2018-09-04 11:22:01 PDT
Committed attempt to fix layout tests in <https://trac.webkit.org/changeset/235621>.