OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "config.h" | |
6 #include "core/paint/PaintPropertyTreeBuilder.h" | |
7 | |
8 #include "core/frame/FrameView.h" | |
9 #include "core/layout/LayoutView.h" | |
10 #include "core/paint/ObjectPaintProperties.h" | |
11 #include "core/paint/PaintLayer.h" | |
12 #include "platform/graphics/paint/TransformPaintPropertyNode.h" | |
13 #include "platform/transforms/TransformationMatrix.h" | |
14 | |
15 namespace blink { | |
16 | |
17 // The context for layout tree walk. | |
18 // The walk will be done in the primary tree order (= DOM order), thus the conte xt will also be | |
19 // responsible for bookkeeping tree state in other order, for example, the most recent position | |
20 // container seen. | |
21 struct PaintPropertyTreeBuilder::Context { | |
22 Context() : currentTransform(nullptr), transformForOutOfFlowPositioned(nullp tr), transformForFixedPositioned(nullptr) { } | |
23 | |
24 // The combination of a transform and paint offset describes a linear space. | |
25 // When a layout object recur to its children, the main context is expected to refer | |
26 // the object's border box, then the callee will derive its own border box b y translating | |
27 // the space with its own layout location. | |
28 TransformPaintPropertyNode* currentTransform; | |
29 LayoutPoint paintOffset; | |
30 | |
31 // Separate context for out-of-flow positioned and fixed positioned elements are needed | |
32 // because they don't use DOM parent as their positioning parent (i.e. conta ining block). | |
33 // These additional contexts normally pass through untouched, and are only c opied from | |
34 // the main context when the current element serves as the positioning paren t of corresponding | |
35 // positioned descendants. | |
36 TransformPaintPropertyNode* transformForOutOfFlowPositioned; | |
37 LayoutPoint paintOffsetForOutOfFlowPositioned; | |
38 | |
39 TransformPaintPropertyNode* transformForFixedPositioned; | |
40 LayoutPoint paintOffsetForFixedPositioned; | |
41 }; | |
42 | |
43 void PaintPropertyTreeBuilder::buildPropertyTrees(FrameView& rootFrame) | |
44 { | |
45 walk(rootFrame, Context()); | |
46 } | |
47 | |
48 void PaintPropertyTreeBuilder::walk(FrameView& frameView, const Context& context ) | |
49 { | |
50 Context localContext(context); | |
51 | |
52 TransformationMatrix frameTranslate; | |
53 frameTranslate.translate(frameView.x(), frameView.y()); | |
54 // The frame owner applies paint offset already. | |
55 // This assumption may change in the future. | |
56 ASSERT(context.paintOffset == LayoutPoint()); | |
57 RefPtr<TransformPaintPropertyNode> newTransformNodeForPreTranslation = Trans formPaintPropertyNode::create(frameTranslate, FloatPoint3D(), context.currentTra nsform); | |
58 localContext.transformForFixedPositioned = newTransformNodeForPreTranslation .get(); | |
59 localContext.paintOffsetForFixedPositioned = LayoutPoint(); | |
60 | |
61 // This is going away in favor of Settings::rootLayerScrolls. | |
62 DoubleSize scrollOffset = frameView.scrollOffsetDouble(); | |
63 TransformationMatrix frameScroll; | |
64 frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); | |
65 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create(frameScroll, FloatPoint3D(), newTransformNodeFo rPreTranslation); | |
66 localContext.currentTransform = localContext.transformForOutOfFlowPositioned = newTransformNodeForScrollTranslation.get(); | |
67 localContext.paintOffset = localContext.paintOffsetForOutOfFlowPositioned = LayoutPoint(); | |
68 | |
69 frameView.setPreTranslation(newTransformNodeForPreTranslation.release()); | |
70 frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release( )); | |
71 | |
72 if (LayoutView* layoutView = frameView.layoutView()) | |
73 walk(*layoutView, localContext); | |
74 } | |
75 | |
76 static bool shouldCreatePaintOffsetTranslationNode(LayoutBoxModelObject& object) | |
77 { | |
78 // TODO(trchen): Eliminate PaintLayer dependency. | |
79 PaintLayer* layer = object.layer(); | |
80 if (!layer) | |
81 return false; | |
82 | |
83 return layer->paintsWithTransform(GlobalPaintNormalPhase); | |
84 } | |
85 | |
86 static FloatPoint3D transformOrigin(const LayoutBox& box) | |
87 { | |
88 const ComputedStyle& style = box.styleRef(); | |
89 FloatSize borderBoxSize(box.size()); | |
90 return FloatPoint3D( | |
91 floatValueForLength(style.transformOriginX(), borderBoxSize.width()), | |
92 floatValueForLength(style.transformOriginY(), borderBoxSize.height()), | |
93 style.transformOriginZ()); | |
94 } | |
95 | |
96 static FloatPoint perspectiveOrigin(const LayoutBox& box) | |
97 { | |
98 const ComputedStyle& style = box.styleRef(); | |
99 FloatSize borderBoxSize(box.size()); | |
100 return FloatPoint( | |
101 floatValueForLength(style.perspectiveOriginX(), borderBoxSize.width()), | |
102 floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())) ; | |
103 } | |
104 | |
105 void PaintPropertyTreeBuilder::walk(LayoutBoxModelObject& object, const Context& context) | |
chrishtr
2015/10/21 17:15:19
This function is too long.
pdr.
2015/10/21 17:18:02
@trchen, what do you think about breaking each ste
trchen
2015/10/21 22:21:14
Sure! I was thinking about it so we can use the fu
| |
106 { | |
107 ASSERT(object.isBox() != object.isLayoutInline()); // Either or. | |
108 | |
109 Context localContext(context); | |
110 RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation ; | |
111 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform; | |
112 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective; | |
113 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation; | |
114 | |
115 // * Figure out the layout space of the current object. | |
116 const ComputedStyle& style = object.styleRef(); | |
117 // TODO(trchen): There is some insanity going on with tables. Double check r esults. | |
118 switch (style.position()) { | |
119 case StaticPosition: | |
120 break; | |
121 case RelativePosition: | |
122 localContext.paintOffset += object.offsetForInFlowPosition(); | |
123 break; | |
124 case AbsolutePosition: | |
125 localContext.currentTransform = context.transformForOutOfFlowPositioned; | |
126 localContext.paintOffset = context.paintOffsetForOutOfFlowPositioned; | |
127 break; | |
128 case StickyPosition: | |
129 localContext.paintOffset += object.offsetForInFlowPosition(); | |
130 break; | |
131 case FixedPosition: | |
132 localContext.currentTransform = context.transformForFixedPositioned; | |
133 localContext.paintOffset = context.paintOffsetForFixedPositioned; | |
134 break; | |
135 default: | |
136 ASSERT_NOT_REACHED(); | |
137 } | |
138 if (object.isBox()) | |
139 localContext.paintOffset += toLayoutBox(object).locationOffset(); | |
140 | |
141 // * Create a transform node to consolidate paint offset (if needed). | |
142 if (shouldCreatePaintOffsetTranslationNode(object) && localContext.paintOffs et != LayoutPoint()) { | |
143 TransformationMatrix matrix; | |
144 matrix.translate(localContext.paintOffset.x(), localContext.paintOffset. y()); | |
145 newTransformNodeForPaintOffsetTranslation = TransformPaintPropertyNode:: create( | |
146 matrix, FloatPoint3D(), localContext.currentTransform); | |
147 localContext.currentTransform = newTransformNodeForPaintOffsetTranslatio n.get(); | |
148 localContext.paintOffset = LayoutPoint(); | |
149 } | |
150 | |
151 // * Create a transform node for CSS transform (if present). | |
152 bool hasTransform = object.isBox() && style.hasTransform(); | |
153 if (hasTransform) { | |
154 TransformationMatrix matrix; | |
155 style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle:: ExcludeTransformOrigin, | |
156 ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentT ransformProperties); | |
157 newTransformNodeForTransform = TransformPaintPropertyNode::create( | |
158 matrix, transformOrigin(toLayoutBox(object)), localContext.currentTr ansform); | |
159 localContext.currentTransform = newTransformNodeForTransform.get(); | |
160 ASSERT(localContext.paintOffset == LayoutPoint()); | |
161 } | |
162 // At this point, the current space is the space we paint the element itself . | |
163 | |
164 // * Create a transform node for CSS perspective (if present). | |
165 if (object.isBox() && style.hasPerspective()) { | |
166 TransformationMatrix matrix; | |
167 matrix.applyPerspective(style.perspective()); | |
168 newTransformNodeForPerspective = TransformPaintPropertyNode::create( | |
169 matrix, perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(localC ontext.paintOffset), localContext.currentTransform); | |
170 localContext.currentTransform = newTransformNodeForPerspective.get(); | |
171 } | |
172 | |
173 // * Create a transform node for overflow clip (if present). | |
174 if (object.hasOverflowClip()) { | |
175 PaintLayer* layer = object.layer(); | |
176 ASSERT(layer); | |
177 DoubleSize scrollOffset = layer->scrollableArea()->scrollOffset(); | |
178 if (!scrollOffset.isZero() || layer->scrollsOverflow()) { | |
179 TransformationMatrix matrix; | |
180 matrix.translate(-scrollOffset.width(), -scrollOffset.height()); | |
181 newTransformNodeForScrollTranslation = TransformPaintPropertyNode::c reate(matrix, FloatPoint3D(), localContext.currentTransform); | |
182 localContext.currentTransform = newTransformNodeForScrollTranslation .get(); | |
183 } | |
184 } | |
185 // At this point, the current space is the space we paint in-flow children. | |
186 | |
187 // * Update the context for out-of-flow descendants (if position container i s established). | |
188 if (style.position() != StaticPosition || hasTransform) { | |
189 localContext.transformForOutOfFlowPositioned = localContext.currentTrans form; | |
190 localContext.paintOffsetForOutOfFlowPositioned = localContext.paintOffse t; | |
191 } | |
192 if (hasTransform) { | |
193 localContext.transformForFixedPositioned = localContext.currentTransform ; | |
194 localContext.paintOffsetForFixedPositioned = localContext.paintOffset; | |
195 } | |
196 | |
197 // * Memorize the nodes we created for future reference during paint. | |
198 if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransfor m || newTransformNodeForPerspective || newTransformNodeForScrollTranslation) { | |
199 ObjectPaintProperties& properties = object.ensureObjectPaintProperties() ; | |
200 properties.setPaintOffsetTranslation(newTransformNodeForPaintOffsetTrans lation.release()); | |
201 properties.setTransform(newTransformNodeForTransform.release()); | |
202 properties.setPerspective(newTransformNodeForPerspective.release()); | |
203 properties.setScrollTranslation(newTransformNodeForScrollTranslation.rel ease()); | |
204 } else { | |
205 object.clearObjectPaintProperties(); | |
206 } | |
207 | |
208 // * Recur. | |
209 | |
210 // TODO(trchen): Walk subframes for LayoutFrame. | |
211 | |
212 // TODO(trchen): Implement SVG walk. | |
213 if (object.isSVGRoot()) { | |
214 return; | |
215 } | |
216 | |
217 for (LayoutObject* child = object.slowFirstChild(); child; child = child->ne xtSibling()) { | |
218 if (child->isText()) | |
219 continue; | |
220 walk(toLayoutBoxModelObject(*child), localContext); | |
221 } | |
222 } | |
223 | |
224 } // namespace blink | |
OLD | NEW |