Beispiel #1
0
void RenderReplaced::computeAspectRatioInformationForRenderBox(RenderBox* contentRenderer, FloatSize& constrainedSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
{
    FloatSize intrinsicSize;
    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 (isRenderImage())
                intrinsicSize.scale(toRenderImage(this)->imageDevicePixelRatio());
        }

        if (hasAspectRatio() && isPercentageIntrinsicSize)
            intrinsicRatio = 1;
            
        // Update our intrinsic size to match what the content renderer has computed, so that when we
        // constrain the size below, the correct intrinsic size will be obtained for comparison against
        // min and max widths.
        if (intrinsicRatio && !isPercentageIntrinsicSize && !intrinsicSize.isEmpty())
            m_intrinsicSize = LayoutSize(intrinsicSize);

        if (!isHorizontalWritingMode()) {
            if (intrinsicRatio)
                intrinsicRatio = 1 / intrinsicRatio;
            intrinsicSize = intrinsicSize.transposedSize();
        }
    } else {
        computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
        if (intrinsicRatio) {
            ASSERT(!isPercentageIntrinsicSize);
            if (!intrinsicSize.isEmpty())
                m_intrinsicSize = LayoutSize(isHorizontalWritingMode() ? intrinsicSize : intrinsicSize.transposedSize());
        }
    }

    // Now constrain the intrinsic size along each axis according to minimum and maximum width/heights along the
    // opposite axis. So for example a maximum width that shrinks our width will result in the height we compute here
    // having to shrink in order to preserve the aspect ratio. Because we compute these values independently along
    // each axis, the final returned size may in fact not preserve the aspect ratio.
    // FIXME: In the long term, it might be better to just return this code more to the way it used to be before this
    // function was added, since all it has done is make the code more unclear.
    constrainedSize = intrinsicSize;
    if (intrinsicRatio && !isPercentageIntrinsicSize && !intrinsicSize.isEmpty() && 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!
        constrainedSize.setWidth(RenderBox::computeReplacedLogicalHeight() * intrinsicSize.width() / intrinsicSize.height());
        constrainedSize.setHeight(RenderBox::computeReplacedLogicalWidth() * intrinsicSize.height() / intrinsicSize.width());
    }
}
Beispiel #2
0
LayoutUnit RenderReplaced::computeReplacedLogicalHeight() const
{
    // 10.5 Content height: the 'height' property: http://www.w3.org/TR/CSS21/visudet.html#propdef-height
    if (hasReplacedLogicalHeight())
        return computeReplacedLogicalHeightRespectingMinMaxHeight(computeReplacedLogicalHeightUsing(style()->logicalHeight()));

    RenderBox* contentRenderer = embeddedContentBox();

    // 10.6.2 Inline, replaced elements: http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-height
    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;

    bool widthIsAuto = style()->logicalWidth().isAuto();
    bool hasIntrinsicHeight = m_hasIntrinsicSize || (!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());
    }

    // 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));
    }

    // 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());
    }

    // 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);
}
Beispiel #3
0
void RenderReplaced::computeAspectRatioInformationForRenderBox(FloatSize& constrainedSize, double& intrinsicRatio) const
{
    FloatSize intrinsicSize;
    computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio);
    if (intrinsicRatio && !intrinsicSize.isEmpty())
        m_intrinsicSize = LayoutSize(intrinsicSize);

    // Now constrain the intrinsic size along each axis according to minimum and maximum width/heights along the
    // opposite axis. So for example a maximum width that shrinks our width will result in the height we compute here
    // having to shrink in order to preserve the aspect ratio. Because we compute these values independently along
    // each axis, the final returned size may in fact not preserve the aspect ratio.
    // FIXME: In the long term, it might be better to just return this code more to the way it used to be before this
    // function was added, since all it has done is make the code more unclear.
    constrainedSize = intrinsicSize;
    if (intrinsicRatio && !intrinsicSize.isEmpty() && 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.
        constrainedSize.setWidth(RenderBox::computeReplacedLogicalHeight() * intrinsicSize.width() / intrinsicSize.height());
        constrainedSize.setHeight(RenderBox::computeReplacedLogicalWidth() * intrinsicSize.height() / intrinsicSize.width());
    }
}
Beispiel #4
0
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);
}
Beispiel #5
0
LayoutUnit RenderReplaced::computeReplacedLogicalWidth(bool includeMaxWidth) const
{
    if (style()->logicalWidth().isSpecified())
        return computeReplacedLogicalWidthRespectingMinMaxWidth(computeReplacedLogicalWidthUsing(style()->logicalWidth()), includeMaxWidth);

    RenderBox* contentRenderer = embeddedContentBox();

    // 10.3.2 Inline, replaced elements: http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-width
    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;

    if (style()->logicalWidth().isAuto()) {
        bool heightIsAuto = style()->logicalHeight().isAuto();
        bool hasIntrinsicWidth = m_hasIntrinsicSize || (!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());
        }

        bool hasIntrinsicHeight = m_hasIntrinsicSize || (!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)));
            }

            // 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
            // 'width' is undefined in CSS 2.1. However, it is suggested that, if the containing block's width does not itself depend on the replaced element's width, then
            // the used value of 'width' is calculated from the constraint equation used for block-level, non-replaced elements in normal flow.
            if (heightIsAuto && !hasIntrinsicWidth && !hasIntrinsicHeight && contentRenderer) {
                // The aforementioned 'constraint equation' used for block-level, non-replaced elements in normal flow:
                // 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block
                LayoutUnit logicalWidth;
                if (RenderBlock* blockWithWidth = firstContainingBlockWithLogicalWidth(this))
                    logicalWidth = blockWithWidth->computeReplacedLogicalWidthRespectingMinMaxWidth(blockWithWidth->computeReplacedLogicalWidthUsing(blockWithWidth->style()->logicalWidth()), false);
                else
                    logicalWidth = containingBlock()->availableLogicalWidth();

                // This solves above equation for 'width' (== logicalWidth).
                LayoutUnit marginStart = miminumValueForLength(style()->marginStart(), logicalWidth);
                LayoutUnit marginEnd = miminumValueForLength(style()->marginEnd(), logicalWidth);
                logicalWidth = max(0, 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);
            }
        }

        // 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());
        }

        // 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);
    }

    return computeReplacedLogicalWidthRespectingMinMaxWidth(intrinsicLogicalWidth(), includeMaxWidth);
}