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. |