summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/RenderReplaced.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-05-07 11:21:11 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-05-07 11:21:11 +0200
commit2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch)
tree988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/WebCore/rendering/RenderReplaced.cpp
parentdd91e772430dc294e3bf478c119ef8d43c0a3358 (diff)
downloadqtwebkit-2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47.tar.gz
Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286)
Diffstat (limited to 'Source/WebCore/rendering/RenderReplaced.cpp')
-rw-r--r--Source/WebCore/rendering/RenderReplaced.cpp195
1 files changed, 87 insertions, 108 deletions
diff --git a/Source/WebCore/rendering/RenderReplaced.cpp b/Source/WebCore/rendering/RenderReplaced.cpp
index 39bacfa7f..fd6b881b3 100644
--- a/Source/WebCore/rendering/RenderReplaced.cpp
+++ b/Source/WebCore/rendering/RenderReplaced.cpp
@@ -2,6 +2,7 @@
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -43,7 +44,6 @@ const int cDefaultHeight = 150;
RenderReplaced::RenderReplaced(Node* node)
: RenderBox(node)
, m_intrinsicSize(cDefaultWidth, cDefaultHeight)
- , m_hasIntrinsicSize(false)
{
setReplaced(true);
}
@@ -51,7 +51,6 @@ RenderReplaced::RenderReplaced(Node* node)
RenderReplaced::RenderReplaced(Node* node, const IntSize& intrinsicSize)
: RenderBox(node)
, m_intrinsicSize(intrinsicSize)
- , m_hasIntrinsicSize(true)
{
setReplaced(true);
}
@@ -146,7 +145,7 @@ void RenderReplaced::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
else {
// Push a clip if we have a border radius, since we want to round the foreground content that gets painted.
paintInfo.context->save();
- paintInfo.context->addRoundedRectClip(style()->getRoundedBorderFor(paintRect));
+ paintInfo.context->addRoundedRectClip(style()->getRoundedBorderFor(paintRect, view()));
}
}
@@ -162,7 +161,7 @@ void RenderReplaced::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
if (drawSelectionTint) {
LayoutRect selectionPaintingRect = localSelectionRect();
selectionPaintingRect.moveBy(adjustedPaintOffset);
- paintInfo.context->fillRect(selectionPaintingRect, selectionBackgroundColor(), style()->colorSpace());
+ paintInfo.context->fillRect(pixelSnappedIntRect(selectionPaintingRect), selectionBackgroundColor(), style()->colorSpace());
}
}
@@ -202,24 +201,6 @@ bool RenderReplaced::shouldPaint(PaintInfo& paintInfo, const LayoutPoint& paintO
return true;
}
-int RenderReplaced::computeIntrinsicLogicalWidth(RenderBox* contentRenderer, bool includeMaxWidth) const
-{
- if (m_hasIntrinsicSize)
- return computeReplacedLogicalWidthRespectingMinMaxWidth(calcAspectRatioLogicalWidth(), includeMaxWidth);
- ASSERT(contentRenderer);
- ASSERT(contentRenderer->style());
- return contentRenderer->computeReplacedLogicalWidthRespectingMinMaxWidth(contentRenderer->computeReplacedLogicalWidthUsing(contentRenderer->style()->logicalWidth()), includeMaxWidth);
-}
-
-int RenderReplaced::computeIntrinsicLogicalHeight(RenderBox* contentRenderer) const
-{
- if (m_hasIntrinsicSize)
- return computeReplacedLogicalHeightRespectingMinMaxHeight(calcAspectRatioLogicalHeight());
- ASSERT(contentRenderer);
- ASSERT(contentRenderer->style());
- return contentRenderer->computeReplacedLogicalHeightRespectingMinMaxHeight(contentRenderer->computeReplacedLogicalHeightUsing(contentRenderer->style()->logicalHeight()));
-}
-
static inline RenderBlock* firstContainingBlockWithLogicalWidth(const RenderReplaced* replaced)
{
// We have to lookup the containing block, which has an explicit width, which must not be equal to our direct containing block.
@@ -282,6 +263,56 @@ bool RenderReplaced::hasReplacedLogicalHeight() const
return false;
}
+static inline bool rendererHasAspectRatio(const RenderObject* renderer)
+{
+ ASSERT(renderer);
+ return renderer->isImage() || renderer->isCanvas() || renderer->isVideo();
+}
+
+void RenderReplaced::computeIntrinsicRatioInformationForRenderBox(RenderBox* contentRenderer, FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+{
+ if (contentRenderer) {
+ contentRenderer->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+ if (intrinsicRatio)
+ ASSERT(!isPercentageIntrinsicSize);
+
+ // Handle zoom & vertical writing modes here, as the embedded document doesn't know about them.
+ if (!isPercentageIntrinsicSize)
+ intrinsicSize.scale(style()->effectiveZoom());
+
+ if (intrinsicRatio && !isHorizontalWritingMode())
+ intrinsicRatio = 1 / intrinsicRatio;
+
+ if (rendererHasAspectRatio(this) && isPercentageIntrinsicSize)
+ intrinsicRatio = 1;
+ return;
+ }
+
+ // This code path can't yield percentage intrinsic sizes, assert that.
+ computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+ ASSERT(!isPercentageIntrinsicSize);
+}
+
+void RenderReplaced::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+{
+ // If there's an embeddedContentBox() of a remote, referenced document available, this code-path should never be used.
+ ASSERT(!embeddedContentBox());
+ isPercentageIntrinsicSize = false;
+ intrinsicSize = FloatSize(intrinsicLogicalWidth(), intrinsicLogicalHeight());
+
+ // Figure out if we need to compute an intrinsic ratio.
+ if (intrinsicSize.isEmpty() || !rendererHasAspectRatio(this))
+ return;
+
+ intrinsicRatio = intrinsicSize.width() / intrinsicSize.height();
+ if (style()->logicalWidth().isAuto() && style()->logicalHeight().isAuto()) {
+ // We can't multiply or divide by 'intrinsicRatio' here, it breaks tests, like fast/images/zoomed-img-size.html, which
+ // can only be fixed once subpixel precision is available for things like intrinsicWidth/Height - which include zoom!
+ intrinsicSize.setWidth(RenderBox::computeReplacedLogicalHeight() * intrinsicLogicalWidth() / intrinsicLogicalHeight());
+ intrinsicSize.setHeight(RenderBox::computeReplacedLogicalWidth() * intrinsicLogicalHeight() / intrinsicLogicalWidth());
+ }
+}
+
LayoutUnit RenderReplaced::computeReplacedLogicalWidth(bool includeMaxWidth) const
{
if (style()->logicalWidth().isSpecified())
@@ -293,33 +324,25 @@ LayoutUnit RenderReplaced::computeReplacedLogicalWidth(bool includeMaxWidth) con
bool isPercentageIntrinsicSize = false;
double intrinsicRatio = 0;
FloatSize intrinsicSize;
- if (contentRenderer)
- contentRenderer->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
- else
- computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
-
- if (intrinsicRatio && !isHorizontalWritingMode())
- intrinsicRatio = 1 / intrinsicRatio;
+ computeIntrinsicRatioInformationForRenderBox(contentRenderer, intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+ // FIXME: Remove unnecessary round/roundToInt calls from this method when layout is off ints: webkit.org/b/63656
if (style()->logicalWidth().isAuto()) {
bool heightIsAuto = style()->logicalHeight().isAuto();
- bool hasIntrinsicWidth = m_hasIntrinsicSize || (!isPercentageIntrinsicSize && intrinsicSize.width() > 0);
+ bool hasIntrinsicWidth = !isPercentageIntrinsicSize && intrinsicSize.width() > 0;
// If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic width, then that intrinsic width is the used value of 'width'.
- if (heightIsAuto && hasIntrinsicWidth) {
- if (m_hasIntrinsicSize)
- return computeReplacedLogicalWidthRespectingMinMaxWidth(calcAspectRatioLogicalWidth(), includeMaxWidth);
- return static_cast<LayoutUnit>(intrinsicSize.width() * style()->effectiveZoom());
- }
+ if (heightIsAuto && hasIntrinsicWidth)
+ return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(intrinsicSize.width()), includeMaxWidth);
- bool hasIntrinsicHeight = m_hasIntrinsicSize || (!isPercentageIntrinsicSize && intrinsicSize.height() > 0);
+ bool hasIntrinsicHeight = !isPercentageIntrinsicSize && intrinsicSize.height() > 0;
if (intrinsicRatio || isPercentageIntrinsicSize) {
// If 'height' and 'width' both have computed values of 'auto' and the element has no intrinsic width, but does have an intrinsic height and intrinsic ratio;
// or if 'width' has a computed value of 'auto', 'height' has some other computed value, and the element does have an intrinsic ratio; then the used value
// of 'width' is: (used height) * (intrinsic ratio)
if (intrinsicRatio && ((heightIsAuto && !hasIntrinsicWidth && hasIntrinsicHeight) || !heightIsAuto)) {
LayoutUnit logicalHeight = computeReplacedLogicalHeightUsing(style()->logicalHeight());
- return computeReplacedLogicalWidthRespectingMinMaxWidth(static_cast<LayoutUnit>(ceil(logicalHeight * intrinsicRatio)));
+ return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(round(logicalHeight * intrinsicRatio)));
}
// If 'height' and 'width' both have computed values of 'auto' and the element has an intrinsic ratio but no intrinsic height or width, then the used value of
@@ -335,26 +358,24 @@ LayoutUnit RenderReplaced::computeReplacedLogicalWidth(bool includeMaxWidth) con
logicalWidth = containingBlock()->availableLogicalWidth();
// This solves above equation for 'width' (== logicalWidth).
- LayoutUnit marginStart = style()->marginStart().calcMinValue(logicalWidth);
- LayoutUnit marginEnd = style()->marginEnd().calcMinValue(logicalWidth);
- logicalWidth = max(0, logicalWidth - (marginStart + marginEnd + (width() - clientWidth())));
+ LayoutUnit marginStart = minimumValueForLength(style()->marginStart(), logicalWidth);
+ LayoutUnit marginEnd = minimumValueForLength(style()->marginEnd(), logicalWidth);
+ logicalWidth = max(ZERO_LAYOUT_UNIT, logicalWidth - (marginStart + marginEnd + (width() - clientWidth())));
if (isPercentageIntrinsicSize)
- // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
- logicalWidth = static_cast<LayoutUnit>(round(logicalWidth * intrinsicSize.width() / 100));
- return computeReplacedLogicalWidthRespectingMinMaxWidth(logicalWidth);
+ logicalWidth = roundToInt(logicalWidth * intrinsicSize.width() / 100);
+ return computeReplacedLogicalWidthRespectingMinMaxWidth(logicalWidth, includeMaxWidth);
}
}
// Otherwise, if 'width' has a computed value of 'auto', and the element has an intrinsic width, then that intrinsic width is the used value of 'width'.
- if (hasIntrinsicWidth) {
- if (isPercentageIntrinsicSize || m_hasIntrinsicSize)
- return computeReplacedLogicalWidthRespectingMinMaxWidth(calcAspectRatioLogicalWidth(), includeMaxWidth);
- return static_cast<LayoutUnit>(intrinsicSize.width() * style()->effectiveZoom());
- }
+ if (hasIntrinsicWidth)
+ return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(intrinsicSize.width()), includeMaxWidth);
// Otherwise, if 'width' has a computed value of 'auto', but none of the conditions above are met, then the used value of 'width' becomes 300px. If 300px is too
// wide to fit the device, UAs should use the width of the largest rectangle that has a 2:1 ratio and fits the device instead.
- return computeReplacedLogicalWidthRespectingMinMaxWidth(cDefaultWidth, includeMaxWidth);
+ // Note: We fall through and instead return intrinsicLogicalWidth() here - to preserve existing WebKit behavior, which might or might not be correct, or desired.
+ // Changing this to return cDefaultWidth, will affect lots of test results. Eg. some tests assume that a blank <img> tag (which implies width/height=auto)
+ // has no intrinsic size, which is wrong per CSS 2.1, but matches our behavior since a long time.
}
return computeReplacedLogicalWidthRespectingMinMaxWidth(intrinsicLogicalWidth(), includeMaxWidth);
@@ -372,59 +393,28 @@ LayoutUnit RenderReplaced::computeReplacedLogicalHeight() const
bool isPercentageIntrinsicSize = false;
double intrinsicRatio = 0;
FloatSize intrinsicSize;
- if (contentRenderer)
- contentRenderer->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
- else
- computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
-
- if (intrinsicRatio && !isHorizontalWritingMode())
- intrinsicRatio = 1 / intrinsicRatio;
+ computeIntrinsicRatioInformationForRenderBox(contentRenderer, intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+ // FIXME: Remove unnecessary round/roundToInt calls from this method when layout is off ints: webkit.org/b/63656
bool widthIsAuto = style()->logicalWidth().isAuto();
- bool hasIntrinsicHeight = m_hasIntrinsicSize || (!isPercentageIntrinsicSize && intrinsicSize.height() > 0);
+ bool hasIntrinsicHeight = !isPercentageIntrinsicSize && intrinsicSize.height() > 0;
// If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic height, then that intrinsic height is the used value of 'height'.
- if (widthIsAuto && hasIntrinsicHeight) {
- if (m_hasIntrinsicSize)
- return computeReplacedLogicalHeightRespectingMinMaxHeight(calcAspectRatioLogicalHeight());
- return static_cast<LayoutUnit>(intrinsicSize.height() * style()->effectiveZoom());
- }
+ if (widthIsAuto && hasIntrinsicHeight)
+ return computeReplacedLogicalHeightRespectingMinMaxHeight(roundToInt(intrinsicSize.height()));
// Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic ratio then the used value of 'height' is:
// (used width) / (intrinsic ratio)
- if (intrinsicRatio && !isPercentageIntrinsicSize) {
- // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
- return computeReplacedLogicalHeightRespectingMinMaxHeight(round(availableLogicalWidth() / intrinsicRatio));
- }
+ if (intrinsicRatio)
+ return computeReplacedLogicalHeightRespectingMinMaxHeight(roundToInt(round(availableLogicalWidth() / intrinsicRatio)));
// Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic height, then that intrinsic height is the used value of 'height'.
- if (hasIntrinsicHeight) {
- if (m_hasIntrinsicSize)
- return computeReplacedLogicalHeightRespectingMinMaxHeight(calcAspectRatioLogicalHeight());
- return static_cast<LayoutUnit>(intrinsicSize.height() * style()->effectiveZoom());
- }
+ if (hasIntrinsicHeight)
+ return computeReplacedLogicalHeightRespectingMinMaxHeight(roundToInt(intrinsicSize.height()));
// Otherwise, if 'height' has a computed value of 'auto', but none of the conditions above are met, then the used value of 'height' must be set to the height
// of the largest rectangle that has a 2:1 ratio, has a height not greater than 150px, and has a width not greater than the device width.
- return computeReplacedLogicalHeightRespectingMinMaxHeight(cDefaultHeight);
-}
-
-int RenderReplaced::calcAspectRatioLogicalWidth() const
-{
- int intrinsicWidth = intrinsicLogicalWidth();
- int intrinsicHeight = intrinsicLogicalHeight();
- if (!intrinsicHeight)
- return 0;
- return RenderBox::computeReplacedLogicalHeight() * intrinsicWidth / intrinsicHeight;
-}
-
-int RenderReplaced::calcAspectRatioLogicalHeight() const
-{
- int intrinsicWidth = intrinsicLogicalWidth();
- int intrinsicHeight = intrinsicLogicalHeight();
- if (!intrinsicWidth)
- return 0;
- return RenderBox::computeReplacedLogicalWidth() * intrinsicHeight / intrinsicWidth;
+ return computeReplacedLogicalHeightRespectingMinMaxHeight(intrinsicLogicalHeight());
}
void RenderReplaced::computePreferredLogicalWidths()
@@ -435,7 +425,7 @@ void RenderReplaced::computePreferredLogicalWidths()
m_maxPreferredLogicalWidth = computeReplacedLogicalWidth(false) + borderAndPadding;
if (style()->maxWidth().isFixed())
- m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? borderAndPadding : zeroLayoutUnit));
+ m_maxPreferredLogicalWidth = min<LayoutUnit>(m_maxPreferredLogicalWidth, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? borderAndPadding : ZERO_LAYOUT_UNIT));
if (hasRelativeDimensions())
m_minPreferredLogicalWidth = 0;
@@ -488,20 +478,20 @@ LayoutRect RenderReplaced::selectionRectForRepaint(RenderBoxModelObject* repaint
return rect;
}
-IntRect RenderReplaced::localSelectionRect(bool checkWhetherSelected) const
+LayoutRect RenderReplaced::localSelectionRect(bool checkWhetherSelected) const
{
if (checkWhetherSelected && !isSelected())
- return IntRect();
+ return LayoutRect();
if (!m_inlineBoxWrapper)
// We're a block-level replaced element. Just return our own dimensions.
- return IntRect(IntPoint(), size());
+ return LayoutRect(LayoutPoint(), size());
RootInlineBox* root = m_inlineBoxWrapper->root();
- int newLogicalTop = root->block()->style()->isFlippedBlocksWritingMode() ? m_inlineBoxWrapper->logicalBottom() - root->selectionBottom() : root->selectionTop() - m_inlineBoxWrapper->logicalTop();
+ LayoutUnit newLogicalTop = root->block()->style()->isFlippedBlocksWritingMode() ? m_inlineBoxWrapper->logicalBottom() - root->selectionBottom() : root->selectionTop() - m_inlineBoxWrapper->logicalTop();
if (root->block()->style()->isHorizontalWritingMode())
- return IntRect(0, newLogicalTop, width(), root->selectionHeight());
- return IntRect(newLogicalTop, 0, root->selectionHeight(), height());
+ return LayoutRect(0, newLogicalTop, width(), root->selectionHeight());
+ return LayoutRect(newLogicalTop, 0, root->selectionHeight(), height());
}
void RenderReplaced::setSelectionState(SelectionState state)
@@ -537,17 +527,6 @@ bool RenderReplaced::isSelected() const
return false;
}
-IntSize RenderReplaced::intrinsicSize() const
-{
- return m_intrinsicSize;
-}
-
-void RenderReplaced::setIntrinsicSize(const IntSize& size)
-{
- ASSERT(m_hasIntrinsicSize);
- m_intrinsicSize = size;
-}
-
LayoutRect RenderReplaced::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const
{
if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())