diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
commit | 2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch) | |
tree | 988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/WebCore/rendering/RenderReplaced.cpp | |
parent | dd91e772430dc294e3bf478c119ef8d43c0a3358 (diff) | |
download | qtwebkit-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.cpp | 195 |
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()) |