Index: Source/core/css/CSSComputedStyleDeclaration.cpp |
diff --git a/Source/core/css/CSSComputedStyleDeclaration.cpp b/Source/core/css/CSSComputedStyleDeclaration.cpp |
index 4d09b550a6c6ebe5dc4fdd96a96c4d0531c439b0..766a2de1c47dd7d159f825ff0e7cabd9b7ffa12d 100644 |
--- a/Source/core/css/CSSComputedStyleDeclaration.cpp |
+++ b/Source/core/css/CSSComputedStyleDeclaration.cpp |
@@ -623,46 +623,107 @@ static PassRefPtr<CSSValueList> createPositionListForLayer(CSSPropertyID propert |
} |
positionList->append(zoomAdjustedPixelValueForLength(layer->yPosition(), style)); |
return positionList.release(); |
+ |
} |
-static PassRefPtr<CSSValue> getPositionOffsetValue(RenderStyle* style, CSSPropertyID propertyID, const RenderObject* renderer, RenderView* renderView) |
+static Length getOffsetComputedStyle(RenderStyle* style, CSSPropertyID propertyID) |
{ |
- if (!style) |
- return 0; |
+ // If specified as a length, the corresponding absolute length; if specified as |
+ // a percentage, the specified value; otherwise, 'auto'. Hence, we can just |
+ // return the value in the style. |
+ // |
+ // See http://www.w3.org/TR/CSS21/cascade.html#computed-value |
+ switch (propertyID) { |
+ case CSSPropertyLeft: |
+ return style->left(); |
+ case CSSPropertyRight: |
+ return style->right(); |
+ case CSSPropertyTop: |
+ return style->top(); |
+ case CSSPropertyBottom: |
+ return style->bottom(); |
+ default: |
+ ASSERT_NOT_REACHED(); |
+ } |
- Length l; |
+ return Length(0); |
+} |
+ |
+static LayoutUnit getOffsetUsedStyleRelative(RenderBox* box, RenderStyle* style, CSSPropertyID propertyID) |
+{ |
+ // For relatively positioned boxes, the offset is with respect to the top edges |
+ // of the box itself. This ties together top/bottom and left/right to be |
+ // opposites of each other. |
+ // |
+ // See http://www.w3.org/TR/CSS2/visuren.html#relative-positioning |
+ // |
+ // Specifically; |
+ // Since boxes are not split or stretched as a result of 'left' or |
+ // 'right', the used values are always: left = -right. |
+ // and |
+ // Since boxes are not split or stretched as a result of 'top' or |
+ // 'bottom', the used values are always: top = -bottom. |
switch (propertyID) { |
- case CSSPropertyLeft: |
- l = style->left(); |
- break; |
- case CSSPropertyRight: |
- l = style->right(); |
- break; |
- case CSSPropertyTop: |
- l = style->top(); |
- break; |
- case CSSPropertyBottom: |
- l = style->bottom(); |
- break; |
- default: |
- return 0; |
+ case CSSPropertyTop: |
+ return box->relativePositionOffset().height(); |
+ case CSSPropertyBottom: |
+ return -(box->relativePositionOffset().height()); |
+ case CSSPropertyLeft: |
+ return box->relativePositionOffset().width(); |
+ case CSSPropertyRight: |
+ return -(box->relativePositionOffset().width()); |
+ default: |
+ ASSERT_NOT_REACHED(); |
} |
- if (l.isPercent() && renderer && renderer->isBox()) { |
- LayoutUnit containingBlockSize = (propertyID == CSSPropertyLeft || propertyID == CSSPropertyRight) ? |
- toRenderBox(renderer)->containingBlockLogicalWidthForContent() : |
- toRenderBox(renderer)->containingBlockLogicalHeightForContent(ExcludeMarginBorderPadding); |
- return zoomAdjustedPixelValue(valueForLength(l, containingBlockSize, 0), style); |
- } if (l.isViewportPercentage()) |
- return zoomAdjustedPixelValue(valueForLength(l, 0, renderView), style); |
- if (l.isAuto()) { |
- // FIXME: It's not enough to simply return "auto" values for one offset if the other side is defined. |
- // In other words if left is auto and right is not auto, then left's computed value is negative right(). |
- // So we should get the opposite length unit and see if it is auto. |
- return cssValuePool().createValue(l); |
+ return 0; |
+} |
+ |
+static LayoutUnit getOffsetUsedStyleAbsolute(RenderBlock* container, RenderBox* box, RenderStyle* style, CSSPropertyID propertyID) |
+{ |
+ // For absoultely positioned boxes, the offset is how far an box's margin |
+ // edge is offset below the edge of the box's containing block. |
+ // See http://www.w3.org/TR/CSS2/visuren.html#position-props |
+ |
+ // Margins are included in Webkit's offsetTop/offsetLeft so we need to |
+ // remove them here. |
+ switch (propertyID) { |
+ case CSSPropertyTop: |
+ return box->offsetTop() - box->marginTop(); |
+ case CSSPropertyBottom: |
+ return container->clientHeight() - (box->offsetTop() + box->offsetHeight()) - box->marginBottom(); |
+ case CSSPropertyLeft: |
+ return box->offsetLeft() - box->marginLeft(); |
+ case CSSPropertyRight: |
+ return container->clientWidth() - (box->offsetLeft() + box->offsetWidth()) - box->marginRight(); |
+ default: |
+ ASSERT_NOT_REACHED(); |
} |
- return zoomAdjustedPixelValueForLength(l, style); |
+ return 0; |
+} |
+ |
+static PassRefPtr<CSSValue> getPositionOffsetValue(RenderStyle* style, CSSPropertyID propertyID, RenderObject* renderer, RenderView* renderView) |
+{ |
+ if (!style) |
+ return 0; |
+ |
+ // If the element is not displayed; return the "computed value". |
+ if (!renderView || !renderer || !renderer->isBox()) { |
+ return zoomAdjustedPixelValueForLength(getOffsetComputedStyle(style, propertyID), style); |
+ |
+ // We should return the "used value". |
+ } else { |
+ LayoutUnit length = 0; |
+ RenderBox* box = toRenderBox(renderer); |
+ RenderBlock* containingBlock = renderer->containingBlock(); |
+ if (box->isRelPositioned() || !containingBlock) { |
+ length = getOffsetUsedStyleRelative(box, style, propertyID); |
+ } else { |
+ length = getOffsetUsedStyleAbsolute(containingBlock, box, style, propertyID); |
+ } |
+ return zoomAdjustedPixelValue(length, style); |
+ } |
} |
PassRefPtr<CSSPrimitiveValue> CSSComputedStyleDeclaration::currentColorOrValidColor(RenderStyle* style, const Color& color) const |
@@ -1508,6 +1569,13 @@ Node* CSSComputedStyleDeclaration::styledNode() const |
return m_node.get(); |
} |
+// In CSS 2.1 the returned object should actually contain the "used values" |
+// rather then the "computed values" (despite the name saying otherwise). |
+// |
+// See; |
+// http://www.w3.org/TR/CSS21/cascade.html#used-value |
+// http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration |
+// https://developer.mozilla.org/en-US/docs/DOM/window.getComputedStyle |
PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropertyID propertyID, EUpdateLayout updateLayout) const |
{ |
Node* styledNode = this->styledNode(); |