Source/core/paint

This directory contains implementation of painters of layout objects.

Painters

Paint invalidation

Paint invalidation marks anything that need to be painted differently from the original cached painting.

Slimming paint v1

Though described in this document, most of the actual paint invalidation code is under Source/core/layout.

Paint invalidation is a document cycle stage after compositing update and before paint. During the previous stages, objects are marked for needing paint invalidation checking if needed by style change, layout change, compositing change, etc. In paint invalidation stage, we traverse the layout tree for marked subtrees and objects and send the following information to GraphicsLayers and PaintControllers:

  • paint invalidation rects: must cover all areas that will generete different pixels.
  • invalidated display item clients: must invalidate all display item clients that will generate different display items.

Paint invalidation of texts

Texts are painted by InlineTextBoxPainter using InlineTextBox as display item client. Text backgrounds and masks are painted by InlineTextFlowPainter using InlineFlowBox as display item client. We should invalidate these display item clients when their painting will change.

LayoutInlines and LayoutTexts are marked for full paint invalidation if needed when new style is set on them. During paint invalidation, we invalidate the InlineFlowBoxs directly contained by the LayoutInline in LayoutInline::invalidateDisplayItemClients() and InlineTextBoxs contained by the LayoutText in LayoutText::invalidateDisplayItemClients(). We don't need to traverse into the subtree of InlineFlowBoxs in LayoutInline::invalidateDisplayItemClients() because the descendant InlineFlowBoxs and InlineTextBoxs will be handled by their owning LayoutInlines and LayoutTexts, respectively, when changed style is propagated.

Specialty of ::first-line

::first-line pseudo style dynamically applies to all InlineBox's in the first line in the block having ::first-line style. The actual applied style is computed from the ::first-line style and other applicable styles.

If the first line contains any LayoutInline, we compute the style from the ::first-line style and the style of the LayoutInline and apply the computed style to the first line part of the LayoutInline. In blink's style implementation, the combined first line style of LayoutInline is identified with FIRST_LINE_INHERITED pseudo ID.

The normal paint invalidation of texts doesn't work for first line because

  • ComputedStyle::visualInvalidationDiff() can't detect first line style changes;
  • The normal paint invalidation is based on whole LayoutObject's, not aware of the first line.

We have a special path for first line style change: the style system informs the layout system when the computed first-line style changes through LayoutObject::firstLineStyleDidChange(). When this happens, we invalidate all InlineBoxes in the first line.

Slimming paint v2

TODO(wangxianzhu): add details

Paint result caching

PaintController holds the previous painting result as a cache of display items. If some painter would generate results same as those of the previous painting, we'll skip the painting and reuse the display items from cache.

Display item caching

We'll create a CachedDisplayItem when a painter would create a DrawingDisplayItem exactly the same as the display item created in the previous painting. After painting, PaintController will replace CachedDisplayItem with the corresponding display item from the cache.

Subsequence caching

When possible, we enclose the display items that PaintLayerPainter::paintContents() generates (including display items generated by sublayers) in a pair of BeginSubsequence/EndSubsequence display items.

In a subsequence paint, if the layer would generate exactly the same display items, we'll simply output a CachedSubsequence display item in place of the display items, and skip all paintings of the layer and its descendants in painting order. After painting, PaintController will replace CacheSubsequence with cached display items created in previous paintings.

There are many conditions affecting

  • whether we need to generate subsequence for a PaintLayer;
  • whether we can use cached subsequence for a PaintLayer. See shouldCreateSubsequence() and shouldRepaintSubsequence() in PaintLayerPainter.cpp for the conditions.