# Clip Computation
PropertyTrees contain [ClipTree](https://source.chromium.org/chromium/chromium/src/+/main:cc/trees/property_tree.h;l=341;drc=445f8cfdbb63b29ce44f728f6b5015cf18df5534) which stores the viewport clip as a tree structure.
This ClipTree is used to calculate the clip rect for the target node.
Let's take a deeper look on its logic.
## Node ID
In each property tree node, the unique id is specified.
Id `0` and `1` is a special id.
[kRootPropertyNodeId](https://source.chromium.org/chromium/chromium/src/+/main:cc/trees/property_tree.h;l=68;drc=445f8cfdbb63b29ce44f728f6b5015cf18df5534) is `0` which represents the root of the property tree. Property tree node start from index 0.
[kViewportPropertyNodeId](https://source.chromium.org/chromium/chromium/src/+/main:cc/trees/property_tree.h;l=71;drc=445f8cfdbb63b29ce44f728f6b5015cf18df5534) is `1` which represents a direct child of the root. In many cases, it is viewport, the area of the window.
For others, the number is assigned in order of the tree depth.
[PropertyTree](https://source.chromium.org/chromium/chromium/src/+/main:cc/trees/property_tree.h;l=75;drc=445f8cfdbb63b29ce44f728f6b5015cf18df5534) is a general implementation of ClipTree and other tree types.
On creating Node, it is added to the tree by [Insert](https://source.chromium.org/chromium/chromium/src/+/main:cc/trees/property_tree.cc;l=97;drc=445f8cfdbb63b29ce44f728f6b5015cf18df5534) and it assignes the id like this:
```cpp=
node.id = static_cast<int>(nodes_.size()) - 1;
```
On adding, it must set `parent_id` so it's guaranteed that the parent node is already added to the tree which means `nodes_.size()-1` is always larger than its parent id.
Noe that there seems to be no rule on the siblings, so the number only ensures the tree depth only from PropertyTree implementation.
The parent and child relationship is specified as a property of each node as [`parent_id`](https://source.chromium.org/chromium/chromium/src/+/main:cc/trees/clip_node.h;l=45;drc=445f8cfdbb63b29ce44f728f6b5015cf18df5534).
## Compute Clip
[ComputeClips](https://source.chromium.org/chromium/chromium/src/+/main:cc/trees/draw_property_utils.cc;l=871;drc=d28fd91f615e875c14ac7a80d5ae871e23e7cb2d) calculates the accumulated clip from the given [PropertyTrees](https://source.chromium.org/chromium/chromium/src/+/main:cc/trees/property_tree.h;l=707;drc=445f8cfdbb63b29ce44f728f6b5015cf18df5534).
Basically, the clip is just summed up for all ClipNode between root node and the target node.
The following is the essntial code to compute clips.
```cpp=
for (int i = kViewportPropertyNodeId; i < static_cast<int>(clip_tree->size()); ++i) {
if (clip_node->id == kViewportPropertyNodeId) {
clip_node->cached_accumulated_rect_in_screen_space = clip_node->clip;
continue;
}
accumulated_clip =
clip_tree->parent(clip_node)->cached_accumulated_rect_in_screen_space;
ApplyClipNodeToAccumulatedClip(..., &accumulated_clip..);
clip_node->cached_accumulated_rect_in_screen_space = accumulated_clip;
}
```
Starting from Viewport clip which is the direct child of the root of the tree, it accumulates `clip_node`'s parent clip rect and set it to the `clip_node`.
In short, CompueClip resolves clip rect for all nodes inside the property tree using cached value to avoid recalculation.
## Note
Here, you can see that all clip rect is accumulated from kViewportPropertyNode so that the clip rect must fit inside the viewport area.
Next question: why some subsurface such as border can survive this clip rect area?