1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "platform/graphics/paint/DisplayItemPropertyTreeBuilder.h"
8 #include "platform/graphics/paint/DisplayItem.h"
9 #include "platform/graphics/paint/DisplayItemClipTree.h"
10 #include "platform/graphics/paint/DisplayItemTransformTree.h"
11 #include "platform/graphics/paint/ScrollDisplayItem.h"
12 #include "platform/graphics/paint/Transform3DDisplayItem.h"
13 #include "platform/graphics/paint/TransformDisplayItem.h"
17 DisplayItemPropertyTreeBuilder::DisplayItemPropertyTreeBuilder()
18 : m_transformTree(adoptPtr(new DisplayItemTransformTree
))
19 , m_clipTree(adoptPtr(new DisplayItemClipTree
))
20 , m_rangeBeginIndex(0)
23 m_stateStack
.append(BuilderState());
26 DisplayItemPropertyTreeBuilder::~DisplayItemPropertyTreeBuilder()
30 PassOwnPtr
<DisplayItemTransformTree
> DisplayItemPropertyTreeBuilder::releaseTransformTree()
32 ASSERT(m_stateStack
.size() == 1);
33 ASSERT(currentState().ignoredBeginCount
== 0);
35 return m_transformTree
.release();
38 PassOwnPtr
<DisplayItemClipTree
> DisplayItemPropertyTreeBuilder::releaseClipTree()
40 ASSERT(m_stateStack
.size() == 1);
41 ASSERT(currentState().ignoredBeginCount
== 0);
43 return m_clipTree
.release();
46 Vector
<DisplayItemPropertyTreeBuilder::RangeRecord
> DisplayItemPropertyTreeBuilder::releaseRangeRecords()
48 Vector
<RangeRecord
> output
;
49 output
.swap(m_rangeRecords
);
53 void DisplayItemPropertyTreeBuilder::processDisplayItem(const DisplayItem
& displayItem
)
55 if (displayItem
.isBegin())
56 processBeginItem(displayItem
);
57 else if (displayItem
.isEnd())
58 processEndItem(displayItem
);
64 enum TransformKind
{ NotATransform
= 0, Only2DTranslation
, RequiresTransformNode
};
65 enum ClipKind
{ NotAClip
= 0, RequiresClipNode
};
67 struct BeginDisplayItemClassification
{
68 // |transformOrigin| is irrelevant unless a non-translation matrix is
70 TransformKind transformKind
= NotATransform
;
71 TransformationMatrix matrix
;
72 FloatPoint3D transformOrigin
;
74 ClipKind clipKind
= NotAClip
;
78 // Classifies a begin display item based on how it affects the property trees.
79 static BeginDisplayItemClassification
classifyBeginItem(const DisplayItem
& beginDisplayItem
)
81 ASSERT(beginDisplayItem
.isBegin());
83 BeginDisplayItemClassification result
;
84 DisplayItem::Type type
= beginDisplayItem
.type();
85 if (DisplayItem::isTransform3DType(type
)) {
86 const auto& begin3D
= static_cast<const BeginTransform3DDisplayItem
&>(beginDisplayItem
);
87 result
.matrix
= begin3D
.transform();
88 result
.transformOrigin
= begin3D
.transformOrigin();
89 result
.transformKind
= result
.matrix
.isIdentityOr2DTranslation() ? Only2DTranslation
: RequiresTransformNode
;
90 } else if (type
== DisplayItem::BeginTransform
) {
91 const auto& begin2D
= static_cast<const BeginTransformDisplayItem
&>(beginDisplayItem
);
92 result
.matrix
= begin2D
.transform();
93 result
.transformKind
= begin2D
.transform().isIdentityOrTranslation() ? Only2DTranslation
: RequiresTransformNode
;
94 } else if (DisplayItem::isScrollType(type
)) {
95 const auto& beginScroll
= static_cast<const BeginScrollDisplayItem
&>(beginDisplayItem
);
96 const IntSize
& offset
= beginScroll
.currentOffset();
97 result
.matrix
.translate(-offset
.width(), -offset
.height());
98 result
.transformKind
= Only2DTranslation
;
105 void DisplayItemPropertyTreeBuilder::processBeginItem(const DisplayItem
& displayItem
)
107 BeginDisplayItemClassification classification
= classifyBeginItem(displayItem
);
109 if (!classification
.transformKind
&& !classification
.clipKind
) {
110 currentState().ignoredBeginCount
++;
115 BuilderState
newState(currentState());
116 newState
.ignoredBeginCount
= 0;
118 switch (classification
.transformKind
) {
121 case Only2DTranslation
:
122 // Adjust the offset associated with the current transform node.
123 newState
.offset
+= classification
.matrix
.to2DTranslation();
125 case RequiresTransformNode
:
126 // Emit a transform node.
127 newState
.transformNode
= m_transformTree
->createNewNode(
128 newState
.transformNode
, classification
.matrix
, classification
.transformOrigin
);
129 newState
.offset
= FloatSize();
133 switch (classification
.clipKind
) {
136 case RequiresClipNode
:
138 FloatRect adjustedClipRect
= classification
.clipRect
;
139 adjustedClipRect
.move(newState
.offset
);
140 newState
.clipNode
= m_clipTree
->createNewNode(
141 newState
.clipNode
, newState
.transformNode
, adjustedClipRect
);
145 m_stateStack
.append(newState
);
148 void DisplayItemPropertyTreeBuilder::processEndItem(const DisplayItem
& displayItem
)
150 if (currentState().ignoredBeginCount
) {
151 // Ignored this end display item.
152 currentState().ignoredBeginCount
--;
154 // We've closed the scope of some property.
156 m_stateStack
.removeLast();
157 ASSERT(!m_stateStack
.isEmpty());
161 void DisplayItemPropertyTreeBuilder::finishRange()
163 // Don't emit an empty range record.
164 if (m_rangeBeginIndex
< m_currentIndex
) {
165 const auto& current
= currentState();
166 RangeRecord rangeRecord
;
167 rangeRecord
.displayListBeginIndex
= m_rangeBeginIndex
;
168 rangeRecord
.displayListEndIndex
= m_currentIndex
;
169 rangeRecord
.transformNodeIndex
= current
.transformNode
;
170 rangeRecord
.offset
= current
.offset
;
171 rangeRecord
.clipNodeIndex
= current
.clipNode
;
172 m_rangeRecords
.append(rangeRecord
);
175 // The current display item is a boundary.
176 // The earliest the next range could begin is the next one.
177 m_rangeBeginIndex
= m_currentIndex
+ 1;