| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) | 4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) |
| 5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) | 5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) |
| 6 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserv
ed. | 6 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserv
ed. |
| 7 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. | 7 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. |
| 8 * | 8 * |
| 9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
| 10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 #include "sky/engine/platform/LengthFunctions.h" | 48 #include "sky/engine/platform/LengthFunctions.h" |
| 49 #include "sky/engine/platform/geometry/FloatQuad.h" | 49 #include "sky/engine/platform/geometry/FloatQuad.h" |
| 50 #include "sky/engine/platform/geometry/TransformState.h" | 50 #include "sky/engine/platform/geometry/TransformState.h" |
| 51 #include "sky/engine/platform/graphics/GraphicsContextStateSaver.h" | 51 #include "sky/engine/platform/graphics/GraphicsContextStateSaver.h" |
| 52 | 52 |
| 53 namespace blink { | 53 namespace blink { |
| 54 | 54 |
| 55 // Size of border belt for autoscroll. When mouse pointer in border belt, | 55 // Size of border belt for autoscroll. When mouse pointer in border belt, |
| 56 // autoscroll is started. | 56 // autoscroll is started. |
| 57 static const int autoscrollBeltSize = 20; | 57 static const int autoscrollBeltSize = 20; |
| 58 static const unsigned backgroundObscurationTestMaxDepth = 4; | |
| 59 | 58 |
| 60 RenderBox::RenderBox(ContainerNode* node) | 59 RenderBox::RenderBox(ContainerNode* node) |
| 61 : RenderBoxModelObject(node) | 60 : RenderBoxModelObject(node) |
| 62 , m_intrinsicContentLogicalHeight(-1) | 61 , m_intrinsicContentLogicalHeight(-1) |
| 63 , m_minPreferredLogicalWidth(-1) | 62 , m_minPreferredLogicalWidth(-1) |
| 64 , m_maxPreferredLogicalWidth(-1) | 63 , m_maxPreferredLogicalWidth(-1) |
| 65 { | 64 { |
| 66 setIsBox(); | 65 setIsBox(); |
| 67 } | 66 } |
| 68 | 67 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 if (needsLayout() && oldStyle) { | 107 if (needsLayout() && oldStyle) { |
| 109 RenderBlock::removePercentHeightDescendantIfNeeded(this); | 108 RenderBlock::removePercentHeightDescendantIfNeeded(this); |
| 110 | 109 |
| 111 // Normally we can do optimized positioning layout for absolute/fixed po
sitioned objects. There is one special case, however, which is | 110 // Normally we can do optimized positioning layout for absolute/fixed po
sitioned objects. There is one special case, however, which is |
| 112 // when the positioned object's margin-before is changed. In this case t
he parent has to get a layout in order to run margin collapsing | 111 // when the positioned object's margin-before is changed. In this case t
he parent has to get a layout in order to run margin collapsing |
| 113 // to determine the new static position. | 112 // to determine the new static position. |
| 114 if (isOutOfFlowPositioned() && newStyle->hasStaticBlockPosition() && old
Style->marginBefore() != newStyle->marginBefore() | 113 if (isOutOfFlowPositioned() && newStyle->hasStaticBlockPosition() && old
Style->marginBefore() != newStyle->marginBefore() |
| 115 && parent() && !parent()->normalChildNeedsLayout()) | 114 && parent() && !parent()->normalChildNeedsLayout()) |
| 116 parent()->setChildNeedsLayout(); | 115 parent()->setChildNeedsLayout(); |
| 117 } | 116 } |
| 118 | |
| 119 // Our opaqueness might have changed without triggering layout. | |
| 120 if (diff.needsPaintInvalidation()) { | |
| 121 RenderObject* parentToInvalidate = parent(); | |
| 122 for (unsigned i = 0; i < backgroundObscurationTestMaxDepth && parentToIn
validate; ++i) { | |
| 123 parentToInvalidate->invalidateBackgroundObscurationStatus(); | |
| 124 parentToInvalidate = parentToInvalidate->parent(); | |
| 125 } | |
| 126 } | |
| 127 } | 117 } |
| 128 | 118 |
| 129 void RenderBox::updateFromStyle() | 119 void RenderBox::updateFromStyle() |
| 130 { | 120 { |
| 131 RenderBoxModelObject::updateFromStyle(); | 121 RenderBoxModelObject::updateFromStyle(); |
| 132 | 122 |
| 133 RenderStyle* styleToUse = style(); | 123 RenderStyle* styleToUse = style(); |
| 134 bool isRootObject = isDocumentElement(); | 124 bool isRootObject = isDocumentElement(); |
| 135 bool isViewObject = isRenderView(); | 125 bool isViewObject = isRenderView(); |
| 136 | 126 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 158 clearNeedsLayout(); | 148 clearNeedsLayout(); |
| 159 return; | 149 return; |
| 160 } | 150 } |
| 161 | 151 |
| 162 LayoutState state(*this, locationOffset()); | 152 LayoutState state(*this, locationOffset()); |
| 163 while (child) { | 153 while (child) { |
| 164 child->layoutIfNeeded(); | 154 child->layoutIfNeeded(); |
| 165 ASSERT(!child->needsLayout()); | 155 ASSERT(!child->needsLayout()); |
| 166 child = child->nextSibling(); | 156 child = child->nextSibling(); |
| 167 } | 157 } |
| 168 invalidateBackgroundObscurationStatus(); | |
| 169 clearNeedsLayout(); | 158 clearNeedsLayout(); |
| 170 } | 159 } |
| 171 | 160 |
| 172 // More IE extensions. clientWidth and clientHeight represent the interior of a
n object | 161 // More IE extensions. clientWidth and clientHeight represent the interior of a
n object |
| 173 // excluding border and scrollbar. | 162 // excluding border and scrollbar. |
| 174 LayoutUnit RenderBox::clientWidth() const | 163 LayoutUnit RenderBox::clientWidth() const |
| 175 { | 164 { |
| 176 return width() - borderLeft() - borderRight(); | 165 return width() - borderLeft() - borderRight(); |
| 177 } | 166 } |
| 178 | 167 |
| (...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 705 if (boxDecorationData.hasBorder && bleedAvoidance != BackgroundBleedBackgrou
ndOverBorder) | 694 if (boxDecorationData.hasBorder && bleedAvoidance != BackgroundBleedBackgrou
ndOverBorder) |
| 706 paintBorder(paintInfo, paintRect, style, bleedAvoidance); | 695 paintBorder(paintInfo, paintRect, style, bleedAvoidance); |
| 707 } | 696 } |
| 708 | 697 |
| 709 void RenderBox::paintBackground(const PaintInfo& paintInfo, const LayoutRect& pa
intRect, const Color& backgroundColor, BackgroundBleedAvoidance bleedAvoidance) | 698 void RenderBox::paintBackground(const PaintInfo& paintInfo, const LayoutRect& pa
intRect, const Color& backgroundColor, BackgroundBleedAvoidance bleedAvoidance) |
| 710 { | 699 { |
| 711 if (isDocumentElement()) { | 700 if (isDocumentElement()) { |
| 712 paintRootBoxFillLayers(paintInfo); | 701 paintRootBoxFillLayers(paintInfo); |
| 713 return; | 702 return; |
| 714 } | 703 } |
| 715 if (boxDecorationBackgroundIsKnownToBeObscured()) | |
| 716 return; | |
| 717 paintFillLayers(paintInfo, backgroundColor, style()->backgroundLayers(), pai
ntRect, bleedAvoidance); | 704 paintFillLayers(paintInfo, backgroundColor, style()->backgroundLayers(), pai
ntRect, bleedAvoidance); |
| 718 } | 705 } |
| 719 | 706 |
| 720 bool RenderBox::getBackgroundPaintedExtent(LayoutRect& paintedExtent) const | |
| 721 { | |
| 722 ASSERT(hasBackground()); | |
| 723 LayoutRect backgroundRect = pixelSnappedIntRect(borderBoxRect()); | |
| 724 | |
| 725 Color backgroundColor = resolveColor(CSSPropertyBackgroundColor); | |
| 726 if (backgroundColor.alpha()) { | |
| 727 paintedExtent = backgroundRect; | |
| 728 return true; | |
| 729 } | |
| 730 | |
| 731 if (!style()->backgroundLayers().image() || style()->backgroundLayers().next
()) { | |
| 732 paintedExtent = backgroundRect; | |
| 733 return true; | |
| 734 } | |
| 735 | |
| 736 BackgroundImageGeometry geometry; | |
| 737 calculateBackgroundImageGeometry(0, style()->backgroundLayers(), backgroundR
ect, geometry); | |
| 738 if (geometry.hasNonLocalGeometry()) | |
| 739 return false; | |
| 740 paintedExtent = geometry.destRect(); | |
| 741 return true; | |
| 742 } | |
| 743 | |
| 744 bool RenderBox::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) c
onst | |
| 745 { | |
| 746 Color backgroundColor = resolveColor(CSSPropertyBackgroundColor); | |
| 747 if (backgroundColor.hasAlpha()) | |
| 748 return false; | |
| 749 | |
| 750 // FIXME: Check the opaqueness of background images. | |
| 751 | |
| 752 // FIXME: Use rounded rect if border radius is present. | |
| 753 if (style()->hasBorderRadius()) | |
| 754 return false; | |
| 755 // FIXME: The background color clip is defined by the last layer. | |
| 756 if (style()->backgroundLayers().next()) | |
| 757 return false; | |
| 758 LayoutRect backgroundRect; | |
| 759 switch (style()->backgroundClip()) { | |
| 760 case BorderFillBox: | |
| 761 backgroundRect = borderBoxRect(); | |
| 762 break; | |
| 763 case PaddingFillBox: | |
| 764 backgroundRect = paddingBoxRect(); | |
| 765 break; | |
| 766 case ContentFillBox: | |
| 767 backgroundRect = contentBoxRect(); | |
| 768 break; | |
| 769 default: | |
| 770 break; | |
| 771 } | |
| 772 return backgroundRect.contains(localRect); | |
| 773 } | |
| 774 | |
| 775 static bool isCandidateForOpaquenessTest(RenderBox* childBox) | |
| 776 { | |
| 777 RenderStyle* childStyle = childBox->style(); | |
| 778 if (childStyle->position() != StaticPosition && childBox->containingBlock()
!= childBox->parent()) | |
| 779 return false; | |
| 780 if (!childBox->width() || !childBox->height()) | |
| 781 return false; | |
| 782 if (RenderLayer* childLayer = childBox->layer()) { | |
| 783 // FIXME: Deal with z-index. | |
| 784 if (!childStyle->hasAutoZIndex()) | |
| 785 return false; | |
| 786 if (childLayer->hasTransform() || childLayer->isTransparent() || childLa
yer->hasFilter()) | |
| 787 return false; | |
| 788 if (childBox->hasOverflowClip() && childStyle->hasBorderRadius()) | |
| 789 return false; | |
| 790 } | |
| 791 return true; | |
| 792 } | |
| 793 | |
| 794 bool RenderBox::foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, u
nsigned maxDepthToTest) const | |
| 795 { | |
| 796 if (!maxDepthToTest) | |
| 797 return false; | |
| 798 for (RenderObject* child = slowFirstChild(); child; child = child->nextSibli
ng()) { | |
| 799 if (!child->isBox()) | |
| 800 continue; | |
| 801 RenderBox* childBox = toRenderBox(child); | |
| 802 if (!isCandidateForOpaquenessTest(childBox)) | |
| 803 continue; | |
| 804 LayoutPoint childLocation = childBox->location(); | |
| 805 if (childBox->isRelPositioned()) | |
| 806 childLocation.move(childBox->relativePositionOffset()); | |
| 807 LayoutRect childLocalRect = localRect; | |
| 808 childLocalRect.moveBy(-childLocation); | |
| 809 if (childLocalRect.y() < 0 || childLocalRect.x() < 0) { | |
| 810 // If there is unobscured area above/left of a static positioned box
then the rect is probably not covered. | |
| 811 if (childBox->style()->position() == StaticPosition) | |
| 812 return false; | |
| 813 continue; | |
| 814 } | |
| 815 if (childLocalRect.maxY() > childBox->height() || childLocalRect.maxX()
> childBox->width()) | |
| 816 continue; | |
| 817 if (childBox->backgroundIsKnownToBeOpaqueInRect(childLocalRect)) | |
| 818 return true; | |
| 819 if (childBox->foregroundIsKnownToBeOpaqueInRect(childLocalRect, maxDepth
ToTest - 1)) | |
| 820 return true; | |
| 821 } | |
| 822 return false; | |
| 823 } | |
| 824 | |
| 825 bool RenderBox::computeBackgroundIsKnownToBeObscured() | |
| 826 { | |
| 827 // Test to see if the children trivially obscure the background. | |
| 828 // FIXME: This test can be much more comprehensive. | |
| 829 if (!hasBackground()) | |
| 830 return false; | |
| 831 // Table and root background painting is special. | |
| 832 if (isDocumentElement()) | |
| 833 return false; | |
| 834 // FIXME: box-shadow is painted while background painting. | |
| 835 if (style()->boxShadow()) | |
| 836 return false; | |
| 837 LayoutRect backgroundRect; | |
| 838 if (!getBackgroundPaintedExtent(backgroundRect)) | |
| 839 return false; | |
| 840 return foregroundIsKnownToBeOpaqueInRect(backgroundRect, backgroundObscurati
onTestMaxDepth); | |
| 841 } | |
| 842 | |
| 843 bool RenderBox::backgroundHasOpaqueTopLayer() const | 707 bool RenderBox::backgroundHasOpaqueTopLayer() const |
| 844 { | 708 { |
| 845 const FillLayer& fillLayer = style()->backgroundLayers(); | 709 const FillLayer& fillLayer = style()->backgroundLayers(); |
| 846 if (fillLayer.clip() != BorderFillBox) | 710 if (fillLayer.clip() != BorderFillBox) |
| 847 return false; | 711 return false; |
| 848 | 712 |
| 849 // Clipped with local scrolling | 713 // Clipped with local scrolling |
| 850 if (hasOverflowClip() && fillLayer.attachment() == LocalBackgroundAttachment
) | 714 if (hasOverflowClip() && fillLayer.attachment() == LocalBackgroundAttachment
) |
| 851 return false; | 715 return false; |
| 852 | 716 |
| (...skipping 2238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3091 | 2955 |
| 3092 RenderBox::BoxDecorationData::BoxDecorationData(const RenderStyle& style) | 2956 RenderBox::BoxDecorationData::BoxDecorationData(const RenderStyle& style) |
| 3093 { | 2957 { |
| 3094 backgroundColor = style.colorIncludingFallback(CSSPropertyBackgroundColor); | 2958 backgroundColor = style.colorIncludingFallback(CSSPropertyBackgroundColor); |
| 3095 hasBackground = backgroundColor.alpha() || style.hasBackgroundImage(); | 2959 hasBackground = backgroundColor.alpha() || style.hasBackgroundImage(); |
| 3096 ASSERT(hasBackground == style.hasBackground()); | 2960 ASSERT(hasBackground == style.hasBackground()); |
| 3097 hasBorder = style.hasBorder(); | 2961 hasBorder = style.hasBorder(); |
| 3098 } | 2962 } |
| 3099 | 2963 |
| 3100 } // namespace blink | 2964 } // namespace blink |
| OLD | NEW |