OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/paint/PaintPropertyTreeBuilder.h" | 5 #include "core/paint/PaintPropertyTreeBuilder.h" |
6 | 6 |
7 #include "core/frame/FrameView.h" | 7 #include "core/frame/FrameView.h" |
8 #include "core/layout/LayoutPart.h" | 8 #include "core/layout/LayoutPart.h" |
9 #include "core/layout/LayoutView.h" | 9 #include "core/layout/LayoutView.h" |
10 #include "core/paint/ObjectPaintProperties.h" | 10 #include "core/paint/ObjectPaintProperties.h" |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
207 static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutObje ct& object, PaintPropertyTreeBuilderContext& context) | 207 static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutObje ct& object, PaintPropertyTreeBuilderContext& context) |
208 { | 208 { |
209 const ComputedStyle& style = object.styleRef(); | 209 const ComputedStyle& style = object.styleRef(); |
210 if (!style.hasOpacity()) | 210 if (!style.hasOpacity()) |
211 return nullptr; | 211 return nullptr; |
212 RefPtr<EffectPaintPropertyNode> newEffectNode = EffectPaintPropertyNode::cre ate(style.opacity(), context.currentEffect); | 212 RefPtr<EffectPaintPropertyNode> newEffectNode = EffectPaintPropertyNode::cre ate(style.opacity(), context.currentEffect); |
213 context.currentEffect = newEffectNode.get(); | 213 context.currentEffect = newEffectNode.get(); |
214 return newEffectNode.release(); | 214 return newEffectNode.release(); |
215 } | 215 } |
216 | 216 |
217 static PassRefPtr<ClipPaintPropertyNode> createCSSClipIfNeeded(const LayoutObjec t& object, PaintPropertyTreeBuilderContext& context) | |
218 { | |
219 if (!object.hasClip()) | |
220 return nullptr; | |
221 ASSERT(object.canContainAbsolutePositionObjects()); | |
222 | |
223 // Create clip node for descendants that are not fixed position. | |
224 // We don't have to setup context.clipForAbsolutePosition here because this object must be | |
225 // a container for absolute position descendants, and will copy from in-flow context later | |
226 // at updateOutOfFlowContext() step. | |
227 LayoutRect clipRect = toLayoutBox(object).clipRect(context.paintOffset); | |
228 RefPtr<ClipPaintPropertyNode> newClipNodeForCSSClip = ClipPaintPropertyNode: :create( | |
229 context.currentTransform, | |
230 FloatRoundedRect(FloatRect(clipRect)), | |
231 context.currentClip); | |
232 context.currentClip = newClipNodeForCSSClip.get(); | |
233 | |
234 return newClipNodeForCSSClip.release(); | |
235 } | |
236 | |
217 // TODO(trchen): Remove this once we bake the paint offset into frameRect. | 237 // TODO(trchen): Remove this once we bake the paint offset into frameRect. |
218 static PassRefPtr<TransformPaintPropertyNode> createScrollbarPaintOffsetIfNeeded (const LayoutObject& object, PaintPropertyTreeBuilderContext& context) | 238 static PassRefPtr<TransformPaintPropertyNode> createScrollbarPaintOffsetIfNeeded (const LayoutObject& object, PaintPropertyTreeBuilderContext& context) |
219 { | 239 { |
220 IntPoint roundedPaintOffset = roundedIntPoint(context.paintOffset); | 240 IntPoint roundedPaintOffset = roundedIntPoint(context.paintOffset); |
221 if (roundedPaintOffset == IntPoint()) | 241 if (roundedPaintOffset == IntPoint()) |
222 return nullptr; | 242 return nullptr; |
223 | 243 |
224 if (!object.isBoxModelObject()) | 244 if (!object.isBoxModelObject()) |
225 return nullptr; | 245 return nullptr; |
226 PaintLayerScrollableArea* scrollableArea = toLayoutBoxModelObject(object).ge tScrollableArea(); | 246 PaintLayerScrollableArea* scrollableArea = toLayoutBoxModelObject(object).ge tScrollableArea(); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
302 if (scrollOffset.isZero() && !layer->scrollsOverflow()) | 322 if (scrollOffset.isZero() && !layer->scrollsOverflow()) |
303 return nullptr; | 323 return nullptr; |
304 | 324 |
305 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create( | 325 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = Tr ansformPaintPropertyNode::create( |
306 TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.he ight()), | 326 TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.he ight()), |
307 FloatPoint3D(), context.currentTransform); | 327 FloatPoint3D(), context.currentTransform); |
308 context.currentTransform = newTransformNodeForScrollTranslation.get(); | 328 context.currentTransform = newTransformNodeForScrollTranslation.get(); |
309 return newTransformNodeForScrollTranslation.release(); | 329 return newTransformNodeForScrollTranslation.release(); |
310 } | 330 } |
311 | 331 |
312 static void updateOutOfFlowContext(const LayoutObject& object, PaintPropertyTree BuilderContext& context) | 332 static void updateOutOfFlowContext(RefPtr<ClipPaintPropertyNode>& newClipNodeFor CSSClipFixedPosition, const LayoutObject& object, PaintPropertyTreeBuilderContex t& context, ClipPaintPropertyNode* newClipNodeForCSSClip) |
jbroman
2016/03/23 17:16:51
This argument order is very surprising to me. Norm
trchen
2016/03/24 00:53:58
Done.
I learned Intel syntax when I was young and
| |
313 { | 333 { |
314 // At the html->svg boundary (see: createPaintOffsetTranslationIfNeeded) the currentTransform is | 334 // At the html->svg boundary (see: createPaintOffsetTranslationIfNeeded) the currentTransform is |
315 // up-to-date for all children of the svg root element. Additionally, inside SVG, all positioning | 335 // up-to-date for all children of the svg root element. Additionally, inside SVG, all positioning |
316 // uses transforms. Therefore, we only need to check createdNewTransform and isSVGRoot() to | 336 // uses transforms. Therefore, we only need to check createdNewTransform and isSVGRoot() to |
317 // ensure out-of-flow and fixed positioning is correct at the svg->html boun dary. | 337 // ensure out-of-flow and fixed positioning is correct at the svg->html boun dary. |
318 | 338 |
319 if (object.canContainAbsolutePositionObjects()) { | 339 if (object.canContainAbsolutePositionObjects()) { |
320 context.transformForAbsolutePosition = context.currentTransform; | 340 context.transformForAbsolutePosition = context.currentTransform; |
321 context.paintOffsetForAbsolutePosition = context.paintOffset; | 341 context.paintOffsetForAbsolutePosition = context.paintOffset; |
322 context.clipForAbsolutePosition = context.currentClip; | 342 context.clipForAbsolutePosition = context.currentClip; |
323 } | 343 } |
324 | 344 |
325 // TODO(pdr): Remove the !object.isLayoutView() condition when removing Fram eView | 345 // TODO(pdr): Remove the !object.isLayoutView() condition when removing Fram eView |
326 // paint properties for rootLayerScrolls. | 346 // paint properties for rootLayerScrolls. |
327 if (!object.isLayoutView() && object.canContainFixedPositionObjects()) { | 347 if (!object.isLayoutView() && object.canContainFixedPositionObjects()) { |
328 context.transformForFixedPosition = context.currentTransform; | 348 context.transformForFixedPosition = context.currentTransform; |
329 context.paintOffsetForFixedPosition = context.paintOffset; | 349 context.paintOffsetForFixedPosition = context.paintOffset; |
330 context.clipForFixedPosition = context.currentClip; | 350 context.clipForFixedPosition = context.currentClip; |
351 } else if (newClipNodeForCSSClip) { | |
352 // CSS clip applies to all descendants, even if this object is not a con taining block | |
353 // ancestor of the descendant. It is okay for absolute-position descenda nts because | |
354 // having CSS clip implies being absolute position container. However fo r fixed-position | |
355 // descendants we need to insert the clip here if we are not a containin g block ancestor | |
356 // of them. | |
357 | |
358 // Before we actually create anything, check whether in-flow context and fixed-position | |
359 // context has exactly the same clip. Reuse if possible. | |
360 if (context.clipForFixedPosition == newClipNodeForCSSClip->parent()) { | |
361 context.clipForFixedPosition = newClipNodeForCSSClip; | |
362 return; | |
363 } | |
364 | |
365 newClipNodeForCSSClipFixedPosition = ClipPaintPropertyNode::create( | |
366 const_cast<TransformPaintPropertyNode*>(newClipNodeForCSSClip->local TransformSpace()), | |
jbroman
2016/03/23 17:16:51
const_cast makes me sad. I suspect one of these th
trchen
2016/03/24 00:53:58
I don't know... We need it non-const only for refe
jbroman
2016/03/24 01:03:39
Oh, weird. Both Chromium's and Skia's have it as m
| |
367 newClipNodeForCSSClip->clipRect(), | |
368 context.clipForFixedPosition); | |
369 context.clipForFixedPosition = newClipNodeForCSSClipFixedPosition.get(); | |
331 } | 370 } |
332 } | 371 } |
333 | 372 |
334 static PassOwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordTreeCon textIfNeeded(LayoutObject& object, const PaintPropertyTreeBuilderContext& contex t) | 373 static PassOwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordTreeCon textIfNeeded(LayoutObject& object, const PaintPropertyTreeBuilderContext& contex t) |
335 { | 374 { |
336 // Note: Currently only layer painter makes use of the pre-computed context. | 375 // Note: Currently only layer painter makes use of the pre-computed context. |
337 // This condition may be loosened with no adverse effects beside memory use. | 376 // This condition may be loosened with no adverse effects beside memory use. |
338 if (!object.hasLayer()) | 377 if (!object.hasLayer()) |
339 return nullptr; | 378 return nullptr; |
340 | 379 |
341 OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordedContext = ad optPtr(new ObjectPaintProperties::LocalBorderBoxProperties); | 380 OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordedContext = ad optPtr(new ObjectPaintProperties::LocalBorderBoxProperties); |
342 recordedContext->paintOffset = context.paintOffset; | 381 recordedContext->paintOffset = context.paintOffset; |
343 recordedContext->transform = context.currentTransform; | 382 recordedContext->transform = context.currentTransform; |
344 recordedContext->clip = context.currentClip; | 383 recordedContext->clip = context.currentClip; |
345 recordedContext->effect = context.currentEffect; | 384 recordedContext->effect = context.currentEffect; |
346 return recordedContext.release(); | 385 return recordedContext.release(); |
347 } | 386 } |
348 | 387 |
349 void PaintPropertyTreeBuilder::walk(LayoutObject& object, const PaintPropertyTre eBuilderContext& context) | 388 void PaintPropertyTreeBuilder::walk(LayoutObject& object, const PaintPropertyTre eBuilderContext& context) |
350 { | 389 { |
351 PaintPropertyTreeBuilderContext localContext(context); | 390 PaintPropertyTreeBuilderContext localContext(context); |
352 | 391 |
353 deriveBorderBoxFromContainerContext(object, localContext); | 392 deriveBorderBoxFromContainerContext(object, localContext); |
354 RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = createPaintOffsetTranslationIfNeeded(object, localContext); | 393 RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = createPaintOffsetTranslationIfNeeded(object, localContext); |
355 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = createTran sformIfNeeded(object, localContext); | 394 RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = createTran sformIfNeeded(object, localContext); |
356 RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext); | 395 RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext); |
396 RefPtr<ClipPaintPropertyNode> newClipNodeForCSSClip = createCSSClipIfNeeded( object, localContext); | |
357 OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> newRecordedContext = recordTreeContextIfNeeded(object, localContext); | 397 OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> newRecordedContext = recordTreeContextIfNeeded(object, localContext); |
358 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollbarPaintOffset = createScrollbarPaintOffsetIfNeeded(object, localContext); | 398 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollbarPaintOffset = createScrollbarPaintOffsetIfNeeded(object, localContext); |
359 RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = createOverflowCli pIfNeeded(object, localContext); | 399 RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = createOverflowCli pIfNeeded(object, localContext); |
360 // TODO(trchen): Insert flattening transform here, as specified by | 400 // TODO(trchen): Insert flattening transform here, as specified by |
361 // http://www.w3.org/TR/css3-transforms/#transform-style-property | 401 // http://www.w3.org/TR/css3-transforms/#transform-style-property |
362 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPe rspectiveIfNeeded(object, localContext); | 402 RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPe rspectiveIfNeeded(object, localContext); |
363 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = cr eateScrollTranslationIfNeeded(object, localContext); | 403 RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = cr eateScrollTranslationIfNeeded(object, localContext); |
364 updateOutOfFlowContext(object, localContext); | 404 RefPtr<ClipPaintPropertyNode> newClipNodeForCSSClipFixedPosition; |
405 updateOutOfFlowContext(newClipNodeForCSSClipFixedPosition, object, localCont ext, newClipNodeForCSSClip.get()); | |
365 | 406 |
366 if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransfor m || newEffectNode || newClipNodeForOverflowClip || newTransformNodeForPerspecti ve || newTransformNodeForScrollTranslation || newTransformNodeForScrollbarPaintO ffset || newRecordedContext) { | 407 if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransfor m || newEffectNode || newClipNodeForCSSClip || newClipNodeForCSSClipFixedPositio n || newClipNodeForOverflowClip || newTransformNodeForPerspective || newTransfor mNodeForScrollTranslation || newTransformNodeForScrollbarPaintOffset || newRecor dedContext) { |
367 OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProper ties::create( | 408 OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProper ties::create( |
368 newTransformNodeForPaintOffsetTranslation.release(), | 409 newTransformNodeForPaintOffsetTranslation.release(), |
369 newTransformNodeForTransform.release(), | 410 newTransformNodeForTransform.release(), |
370 newEffectNode.release(), | 411 newEffectNode.release(), |
412 newClipNodeForCSSClip.release(), | |
413 newClipNodeForCSSClipFixedPosition.release(), | |
371 newClipNodeForOverflowClip.release(), | 414 newClipNodeForOverflowClip.release(), |
372 newTransformNodeForPerspective.release(), | 415 newTransformNodeForPerspective.release(), |
373 newTransformNodeForScrollTranslation.release(), | 416 newTransformNodeForScrollTranslation.release(), |
374 newTransformNodeForScrollbarPaintOffset.release(), | 417 newTransformNodeForScrollbarPaintOffset.release(), |
375 newRecordedContext.release()); | 418 newRecordedContext.release()); |
376 object.setObjectPaintProperties(updatedPaintProperties.release()); | 419 object.setObjectPaintProperties(updatedPaintProperties.release()); |
377 } else { | 420 } else { |
378 object.clearObjectPaintProperties(); | 421 object.clearObjectPaintProperties(); |
379 } | 422 } |
380 | 423 |
381 for (LayoutObject* child = object.slowFirstChild(); child; child = child->ne xtSibling()) { | 424 for (LayoutObject* child = object.slowFirstChild(); child; child = child->ne xtSibling()) { |
382 if (child->isBoxModelObject() || child->isSVG()) | 425 if (child->isBoxModelObject() || child->isSVG()) |
383 walk(*child, localContext); | 426 walk(*child, localContext); |
384 } | 427 } |
385 | 428 |
386 if (object.isLayoutPart()) { | 429 if (object.isLayoutPart()) { |
387 Widget* widget = toLayoutPart(object).widget(); | 430 Widget* widget = toLayoutPart(object).widget(); |
388 if (widget && widget->isFrameView()) | 431 if (widget && widget->isFrameView()) |
389 walk(*toFrameView(widget), localContext); | 432 walk(*toFrameView(widget), localContext); |
390 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). | 433 // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). |
391 } | 434 } |
392 } | 435 } |
393 | 436 |
394 } // namespace blink | 437 } // namespace blink |
OLD | NEW |