Chromium Code Reviews| 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 |