Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(323)

Unified Diff: third_party/WebKit/Source/core/paint/README.md

Issue 2844803007: Introduce FragmentData, and put ObjectPaintProperties into it. (Closed)
Patch Set: none Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/paint/README.md
diff --git a/third_party/WebKit/Source/core/paint/README.md b/third_party/WebKit/Source/core/paint/README.md
index 34d5d5712b14700197c4c57d573e17c72ec4c171..b30e782ca4b7f8772541a6a5116774607dbd28cc 100644
--- a/third_party/WebKit/Source/core/paint/README.md
+++ b/third_party/WebKit/Source/core/paint/README.md
@@ -11,14 +11,14 @@ the following document lifecycle states:
### Stacked elements and stacking contexts
-This chapter is basically a clarification of [CSS 2.1 appendix E. Elaborate description
-of Stacking Contexts](http://www.w3.org/TR/CSS21/zindex.html).
+This chapter is basically a clarification of [CSS 2.1 appendix E. Elaborate
+description of Stacking Contexts](http://www.w3.org/TR/CSS21/zindex.html).
-Note: we use 'element' instead of 'object' in this chapter to keep consistency with
-the spec. We use 'object' in other places in this document.
+Note: we use 'element' instead of 'object' in this chapter to keep consistency
+with the spec. We use 'object' in other places in this document.
-According to the documentation, we can have the following types of elements that are
-treated in different ways during painting:
+According to the documentation, we can have the following types of elements that
+are treated in different ways during painting:
* Stacked objects: objects that are z-ordered in stacking contexts, including:
@@ -30,27 +30,30 @@ treated in different ways during painting:
managed by real stacking contexts. They are positioned elements with
`z-index: auto` (E.2.8 in the documentation).
- They must be managed by the enclosing stacking context as stacked elements
- because `z-index:auto` and `z-index:0` are considered equal for stacking
- context sorting and they may interleave by DOM order.
+ They must be managed by the enclosing stacking context as stacked
+ elements because `z-index:auto` and `z-index:0` are considered equal for
+ stacking context sorting and they may interleave by DOM order.
- The difference of a stacked element of this type from a real stacking context
- is that it doesn't manage z-ordering of stacked descendants. These descendants
- are managed by the parent stacking context of this stacked element.
+ The difference of a stacked element of this type from a real stacking
+ context is that it doesn't manage z-ordering of stacked descendants.
+ These descendants are managed by the parent stacking context of this
+ stacked element.
- "Stacked element" is not defined as a formal term in the documentation, but we found
- it convenient to use this term to refer to any elements participating z-index ordering
- in stacking contexts.
+ "Stacked element" is not defined as a formal term in the documentation, but
+ we found it convenient to use this term to refer to any elements
+ participating z-index ordering in stacking contexts.
- A stacked element is represented by a `PaintLayerStackingNode` associated with a
- `PaintLayer`. It's painted as self-painting `PaintLayer`s by `PaintLayerPainter`
- by executing all of the steps of the painting algorithm explained in the documentation
- for the element. When painting a stacked element of the second type, we don't
- paint its stacked descendants which are managed by the parent stacking context.
+ A stacked element is represented by a `PaintLayerStackingNode` associated
+ with a `PaintLayer`. It's painted as self-painting `PaintLayer`s by
+ `PaintLayerPainter`
+ by executing all of the steps of the painting algorithm explained in the
+ documentation for the element. When painting a stacked element of the second
+ type, we don't paint its stacked descendants which are managed by the parent
+ stacking context.
-* Non-stacked pseudo stacking contexts: elements that are not stacked, but paint
- their descendants (excluding any stacked contents) as if they created stacking
- contexts. This includes
+* Non-stacked pseudo stacking contexts: elements that are not stacked, but
+ paint their descendants (excluding any stacked contents) as if they created
+ stacking contexts. This includes
* inline blocks, inline tables, inline-level replaced elements
(E.2.7.2.1.4 in the documentation)
@@ -59,52 +62,52 @@ treated in different ways during painting:
* [grid items](http://www.w3.org/TR/css-grid-1/#z-order)
* custom scrollbar parts
- They are painted by `ObjectPainter::paintAllPhasesAtomically()` which executes
- all of the steps of the painting algorithm explained in the documentation, except
- ignores any descendants which are positioned or have non-auto z-index (which is
- achieved by skipping descendants with self-painting layers).
+ They are painted by `ObjectPainter::paintAllPhasesAtomically()` which
+ executes all of the steps of the painting algorithm explained in the
+ documentation, except ignores any descendants which are positioned or have
+ non-auto z-index (which is achieved by skipping descendants with
+ self-painting layers).
* Other normal elements.
### Other glossaries
-* Paint container: the parent of an object for painting, as defined by [CSS2.1 spec
- for painting]((http://www.w3.org/TR/CSS21/zindex.html)). For regular objects,
- this is the parent in the DOM. For stacked objects, it's the containing stacking
- context-inducing object.
+* Paint container: the parent of an object for painting, as defined by
+ [CSS2.1 spec for painting]((http://www.w3.org/TR/CSS21/zindex.html)). For
+ regular objects, this is the parent in the DOM. For stacked objects, it's
+ the containing stacking context-inducing object.
-* Paint container chain: the chain of paint ancestors between an element and the
- root of the page.
+* Paint container chain: the chain of paint ancestors between an element and
+ the root of the page.
* Compositing container: an implementation detail of Blink, which uses
- `PaintLayer`s to represent some layout objects. It is the ancestor along the paint
- ancestor chain which has a PaintLayer. Implemented in
- `PaintLayer::compositingContainer()`. Think of it as skipping intermediate normal
- objects and going directly to the containing stacked object.
+ `PaintLayer`s to represent some layout objects. It is the ancestor along the
+ paint ancestor chain which has a PaintLayer. Implemented in
+ `PaintLayer::compositingContainer()`. Think of it as skipping intermediate
+ normal objects and going directly to the containing stacked object.
-* Compositing container chain: same as paint chain, but for compositing container.
+* Compositing container chain: same as paint chain, but for compositing
+ container.
-* Paint invalidation container: the nearest object on the compositing container
- chain which is composited.
+* Paint invalidation container: the nearest object on the compositing
+ container chain which is composited.
* Visual rect: the bounding box of all pixels that will be painted by a
display item client.
## Paint invalidation
-Paint invalidation marks anything that need to be painted differently from the original
-cached painting.
+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 in pre-order, crossing frame boundaries, for marked subtrees
-and objects and send the following information to `GraphicsLayer`s and `PaintController`s:
+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 in
+pre-order, crossing frame boundaries, for marked subtrees and objects and send
+the following information to `GraphicsLayer`s and `PaintController`s:
* invalidated display item clients: must invalidate all display item clients
that will generate different display items.
@@ -115,163 +118,214 @@ and objects and send the following information to `GraphicsLayer`s and `PaintCon
#### `PaintInvalidationState`
-`PaintInvalidationState` is an optimization used during the paint invalidation phase. Before
-the paint invalidation tree walk, a root `PaintInvalidationState` is created for the root
-`LayoutView`. During the tree walk, one `PaintInvalidationState` is created for each visited
-object based on the `PaintInvalidationState` passed from the parent object.
-It tracks the following information to provide O(1) complexity access to them if possible:
+`PaintInvalidationState` is an optimization used during the paint invalidation
+phase. Before the paint invalidation tree walk, a root `PaintInvalidationState`
+is created for the root `LayoutView`. During the tree walk, one
+`PaintInvalidationState` is created for each visited object based on the
+`PaintInvalidationState` passed from the parent object. It tracks the following
+information to provide O(1) complexity access to them if possible:
-* Paint invalidation container: Since as indicated by the definitions in [Glossaries](#Other glossaries),
- the paint invalidation container for stacked objects can differ from normal objects, we
- have to track both separately. Here is an example:
+* Paint invalidation container: Since as indicated by the definitions in
+ [Glossaries](#Other glossaries), the paint invalidation container for
+ stacked objects can differ from normal objects, we have to track both
+ separately. Here is an example:
<div style="overflow: scroll">
<div id=A style="position: absolute"></div>
<div id=B></div>
</div>
- If the scroller is composited (for high-DPI screens for example), it is the paint invalidation
- container for div B, but not A.
+ If the scroller is composited (for high-DPI screens for example), it is the
+ paint invalidation container for div B, but not A.
-* Paint offset and clip rect: if possible, `PaintInvalidationState` accumulates paint offsets
- and overflow clipping rects from the paint invalidation container to provide O(1) complexity to
- map a point or a rect in current object's local space to paint invalidation container's space.
- Because locations of objects are determined by their containing blocks, and the containing block
- for absolute-position objects differs from non-absolute, we track paint offsets and overflow
- clipping rects for absolute-position objects separately.
+* Paint offset and clip rect: if possible, `PaintInvalidationState`
+ accumulates paint offsets and overflow clipping rects from the paint
+ invalidation container to provide O(1) complexity to map a point or a rect
+ in current object's local space to paint invalidation container's space.
+ Because locations of objects are determined by their containing blocks, and
+ the containing block for absolute-position objects differs from
+ non-absolute, we track paint offsets and overflow clipping rects for
+ absolute-position objects separately.
-In cases that accurate accumulation of paint offsets and clipping rects is impossible,
-we will fall back to slow-path using `LayoutObject::localToAncestorPoint()` or
-`LayoutObject::mapToVisualRectInAncestorSpace()`. This includes the following cases:
+In cases that accurate accumulation of paint offsets and clipping rects is
+impossible, we will fall back to slow-path using
+`LayoutObject::localToAncestorPoint()` or
+`LayoutObject::mapToVisualRectInAncestorSpace()`. This includes the following
+cases:
-* An object has transform related property, is multi-column or has flipped blocks writing-mode,
- causing we can't simply accumulate paint offset for mapping a local rect to paint invalidation
- container;
+* An object has transform related property, is multi-column or has flipped
+ blocks writing-mode, causing we can't simply accumulate paint offset for
+ mapping a local rect to paint invalidation container;
* An object has has filter (including filter induced by reflection), which
needs to expand visual rect for descendants, because currently we don't
include and filter extents into visual overflow;
-* For a fixed-position object we calculate its offset using `LayoutObject::localToAncestorPoint()`,
- but map for its descendants in fast-path if no other things prevent us from doing this;
+* For a fixed-position object we calculate its offset using
+ `LayoutObject::localToAncestorPoint()`, but map for its descendants in
+ fast-path if no other things prevent us from doing this;
-* Because we track paint offset from the normal paint invalidation container only, if we are going
- to use `m_paintInvalidationContainerForStackedContents` and it's different from the normal paint
- invalidation container, we have to force slow-path because the accumulated paint offset is not
- usable;
+* Because we track paint offset from the normal paint invalidation container
+ only, if we are going to use
+ `m_paintInvalidationContainerForStackedContents` and it's different from the
+ normal paint invalidation container, we have to force slow-path because the
+ accumulated paint offset is not usable;
-* We also stop to track paint offset and clipping rect for absolute-position objects when
- `m_paintInvalidationContainerForStackedContents` becomes different from `m_paintInvalidationContainer`.
+* We also stop to track paint offset and clipping rect for absolute-position
+ objects when `m_paintInvalidationContainerForStackedContents` becomes
+ different from `m_paintInvalidationContainer`.
### 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.
-
-`LayoutInline`s and `LayoutText`s are marked for full paint invalidation if needed when
-new style is set on them. During paint invalidation, we invalidate the `InlineFlowBox`s
-directly contained by the `LayoutInline` in `LayoutInline::invalidateDisplayItemClients()` and
-`InlineTextBox`s contained by the `LayoutText` in `LayoutText::invalidateDisplayItemClients()`.
-We don't need to traverse into the subtree of `InlineFlowBox`s in `LayoutInline::invalidateDisplayItemClients()`
-because the descendant `InlineFlowBox`s and `InlineTextBox`s will be handled by their
-owning `LayoutInline`s and `LayoutText`s, respectively, when changed style is propagated.
+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.
+
+`LayoutInline`s and `LayoutText`s are marked for full paint invalidation if
+needed when new style is set on them. During paint invalidation, we invalidate
+the `InlineFlowBox`s directly contained by the `LayoutInline` in
+`LayoutInline::invalidateDisplayItemClients()` and `InlineTextBox`s contained by
+the `LayoutText` in `LayoutText::invalidateDisplayItemClients()`. We don't need
+to traverse into the subtree of `InlineFlowBox`s in
+`LayoutInline::invalidateDisplayItemClients()` because the descendant
+`InlineFlowBox`s and `InlineTextBox`s will be handled by their owning
+`LayoutInline`s and `LayoutText`s, 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.
+`::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.
+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.
+* `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 `InlineBox`es in 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
+`InlineBox`es in the first line.
### Slimming paint v2
TODO(wangxianzhu): add details
-## [`PrePaintTreeWalk`](PrePaintTreeWalk.h) (Slimming paint v2 only)
+## [`PrePaintTreeWalk`](PrePaintTreeWalk.h) (Slimming Paint invalidation/v2 only)
+
+During `InPrePaint` document lifecycle state, this class is called to walk the
+whole layout tree, beginning from the root FrameView, across frame boundaries.
+We do the following during the tree walk:
+
+### Building paint property trees
+[`PaintPropertyTreeBuilder`](PaintPropertyTreeBuilder.h)
+
+This class is responsible for building property trees
+(see [the platform paint README file](../../platform/graphics/paint/README.md)).
+
+Each `PaintLayer`'s `LayoutObject` has one or more `FragmentData` objects (see
+below for more on fragments). Every `FragmentData` has an
+`ObjectPaintProperties` object if any property nodes are induced by it. For
+example, if the object has a transform, its `ObjectPaintProperties::Transform()`
+field points at the `TransformPaintPropertyNode` representing that transform.
+
+The `NeedsPaintPropertyUpdate`, `SubtreeNeedsPaintPropertyUpdate` and
+`DescendantNeedsPaintPropertyUpdate` dirty bits on `LayoutObject` control how
+much of the layout tree is traversed during each `PrePaintTreeWalk`.
-During `InPrePaint` document lifecycle state, this class is called to walk the whole
-layout tree, beginning from the root FrameView, across frame boundaries. We do the
-following during the tree walk:
+### Fragments
-* Building paint property tree: creates paint property tree nodes for special
- things in the layout tree, including but not limit to: overflow clip, transform,
- fixed-pos, animation, mask, filter, etc. Also sets direct compositing reasons to be
- used later for compositing.
+In the absence of multicolumn/pagination, there is a 1:1 correspondence between
+self-painting `PaintLayer`s and `FragmentData`. If there is
+multicolumn/pagination, there may be more `FragmentData`s.. If a `PaintLayer`
+has a property node, each of its fragments will have one. The parent of a
+fragment's property node is the property node that belongs to the ancestor
+`PaintLayer` which is part of the same column. For example, if there are 3
+columns and both a parent and child `PaintLayer` have a transform, there will be
+3 `FragmentData` objects for the parent, 3 for the child, each `FragmentData`
+will have its own `TransformPaintPropertyNode`, and the child's ith fragment's
+transform will point to the ith parent's transform.
-* Paint invalidation: Not implemented yet. TODO(wangxianzhu): add details after
- it's implemented.
+See [`LayoutMultiColumnFlowThread.h`](../layout/LayoutMultiColumnFlowThread.h)
+for a much more detail about multicolumn/pagination.
+
+### Paint invalidation: `PaintInvalidator` implements a tree walk that
+performs paint invalidation. TODO(wangxianzhu): expand on this.
+
+### [`PaintPropertyTreeBuilder`](PaintPropertyTreeBuilder.h) (Slimming Paint invalidation only)
## 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.
+`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
-When a painter would create a `DrawingDisplayItem` exactly the same as the display item
-created in the previous painting, we'll reuse the previous one instead of repainting it.
+When a painter would create a `DrawingDisplayItem` exactly the same as the
+display item created in the previous painting, we'll reuse the previous one
+instead of repainting it.
### 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.
+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 get
-the whole subsequence from the cache instead of repainting them.
+In a subsequence paint, if the layer would generate exactly the same display
+items, we'll get the whole subsequence from the cache instead of repainting
+them.
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.
+See `shouldCreateSubsequence()` and `shouldRepaintSubsequence()` in
+`PaintLayerPainter.cpp` for the conditions.
## Empty paint phase optimization
-During painting, we walk the layout tree multiple times for multiple paint phases. Sometimes
-a layer contain nothing needing a certain paint phase and we can skip tree walk for such
-empty phases. Now we have optimized `PaintPhaseDescendantBlockBackgroundsOnly`,
-`PaintPhaseDescendantOutlinesOnly` and `PaintPhaseFloat` for empty paint phases.
-
-During paint invalidation, we set the containing self-painting layer's `needsPaintPhaseXXX`
-flag if the object has something needing to be painted in the paint phase.
-
-During painting, we check the flag before painting a paint phase and skip the tree walk if
-the flag is not set.
-
-It's hard to clear a `needsPaintPhaseXXX` flag when a layer no longer needs the paint phase,
-so we never clear the flags. Instead, we use another set of flags (`previousPaintPhaseXXXWasEmpty`)
-to record if a painting of a phase actually produced nothing. We'll skip the next
-painting of the phase if the flag is set, regardless of the corresponding
-`needsPaintPhaseXXX` flag. We will clear the `previousPaintPhaseXXXWasEmpty` flags when
-we paint with different clipping, scroll offset or interest rect from the previous paint.
-
-We don't clear the `previousPaintPhaseXXXWasEmpty` flags when the layer is marked `needsRepaint`.
-Instead we clear the flag when the corresponding `needsPaintPhaseXXX` is set. This ensures that
-we won't clear `previousPaintPhaseXXXWasEmpty` flags when unrelated things changed which won't
+During painting, we walk the layout tree multiple times for multiple paint
+phases. Sometimes a layer contain nothing needing a certain paint phase and we
+can skip tree walk for such empty phases. Now we have optimized
+`PaintPhaseDescendantBlockBackgroundsOnly`, `PaintPhaseDescendantOutlinesOnly`
+and `PaintPhaseFloat` for empty paint phases.
+
+During paint invalidation, we set the containing self-painting layer's
+`needsPaintPhaseXXX` flag if the object has something needing to be painted in
+the paint phase.
+
+During painting, we check the flag before painting a paint phase and skip the
+tree walk if the flag is not set.
+
+It's hard to clear a `needsPaintPhaseXXX` flag when a layer no longer needs the
+paint phase, so we never clear the flags. Instead, we use another set of flags
+(`previousPaintPhaseXXXWasEmpty`) to record if a painting of a phase actually
+produced nothing. We'll skip the next painting of the phase if the flag is set,
+regardless of the corresponding `needsPaintPhaseXXX` flag. We will clear the
+`previousPaintPhaseXXXWasEmpty` flags when we paint with different clipping,
+scroll offset or interest rect from the previous paint.
+
+We don't clear the `previousPaintPhaseXXXWasEmpty` flags when the layer is
+marked `needsRepaint`. Instead we clear the flag when the corresponding
+`needsPaintPhaseXXX` is set. This ensures that we won't clear
+`previousPaintPhaseXXXWasEmpty` flags when unrelated things changed which won't
cause the paint phases to become non-empty.
-When layer structure changes, and we are not invalidate paint of the changed subtree,
-we need to manually update the `needsPaintPhaseXXX` flags. For example, if an object changes
-style and creates a self-painting-layer, we copy the flags from its containing self-painting
-layer to this layer, assuming that this layer needs all paint phases that its container
-self-painting layer needs.
+When layer structure changes, and we are not invalidate paint of the changed
+subtree, we need to manually update the `needsPaintPhaseXXX` flags. For example,
+if an object changes style and creates a self-painting-layer, we copy the flags
+from its containing self-painting layer to this layer, assuming that this layer
+needs all paint phases that its container self-painting layer needs.
-We could update the `needsPaintPhaseXXX` flags in a separate tree walk, but that would regress
-performance of the first paint. For slimming paint v2, we can update the flags during the
-pre-painting tree walk to simplify the logics.
+We could update the `needsPaintPhaseXXX` flags in a separate tree walk, but that
+would regress performance of the first paint. For slimming paint v2, we can
+update the flags during the pre-painting tree walk to simplify the logics.
« no previous file with comments | « third_party/WebKit/Source/core/paint/FragmentData.cpp ('k') | third_party/WebKit/Source/core/paint/RarePaintData.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698