mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
508 lines
20 KiB
C++
508 lines
20 KiB
C++
/*
|
|
* 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
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "flutter/sky/engine/core/rendering/RenderReplaced.h"
|
|
|
|
#include "flutter/sky/engine/core/rendering/RenderBlock.h"
|
|
#include "flutter/sky/engine/core/rendering/RenderLayer.h"
|
|
#include "flutter/sky/engine/core/rendering/RenderView.h"
|
|
#include "flutter/sky/engine/platform/LengthFunctions.h"
|
|
#include "flutter/sky/engine/platform/graphics/GraphicsContext.h"
|
|
|
|
namespace blink {
|
|
|
|
const int RenderReplaced::defaultWidth = 300;
|
|
const int RenderReplaced::defaultHeight = 150;
|
|
|
|
RenderReplaced::RenderReplaced()
|
|
: m_intrinsicSize(defaultWidth, defaultHeight) {
|
|
setReplaced(true);
|
|
}
|
|
|
|
RenderReplaced::RenderReplaced(const LayoutSize& intrinsicSize)
|
|
: m_intrinsicSize(intrinsicSize) {
|
|
setReplaced(true);
|
|
}
|
|
|
|
RenderReplaced::~RenderReplaced() {}
|
|
|
|
void RenderReplaced::willBeDestroyed() {
|
|
if (!documentBeingDestroyed() && parent())
|
|
parent()->dirtyLinesFromChangedChild(this);
|
|
|
|
RenderBox::willBeDestroyed();
|
|
}
|
|
|
|
void RenderReplaced::layout() {
|
|
ASSERT(needsLayout());
|
|
|
|
setHeight(minimumReplacedHeight());
|
|
|
|
updateLogicalWidth();
|
|
updateLogicalHeight();
|
|
|
|
m_overflow.clear();
|
|
addVisualEffectOverflow();
|
|
updateLayerTransformAfterLayout();
|
|
|
|
clearNeedsLayout();
|
|
}
|
|
|
|
void RenderReplaced::intrinsicSizeChanged() {
|
|
m_intrinsicSize = IntSize(defaultWidth, defaultHeight);
|
|
setNeedsLayoutAndPrefWidthsRecalc();
|
|
}
|
|
|
|
void RenderReplaced::paint(PaintInfo& paintInfo,
|
|
const LayoutPoint& paintOffset,
|
|
Vector<RenderBox*>& layers) {
|
|
if (!shouldPaint(paintInfo, paintOffset))
|
|
return;
|
|
|
|
LayoutPoint adjustedPaintOffset = paintOffset + location();
|
|
|
|
if (hasBoxDecorationBackground())
|
|
paintBoxDecorationBackground(paintInfo, adjustedPaintOffset);
|
|
|
|
LayoutRect paintRect = LayoutRect(adjustedPaintOffset, size());
|
|
|
|
bool completelyClippedOut = false;
|
|
if (style()->hasBorderRadius()) {
|
|
LayoutRect borderRect = LayoutRect(adjustedPaintOffset, size());
|
|
|
|
if (borderRect.isEmpty())
|
|
completelyClippedOut = true;
|
|
else {
|
|
// Push a clip if we have a border radius, since we want to round the
|
|
// foreground content that gets painted.
|
|
paintInfo.context->save();
|
|
RoundedRect roundedInnerRect = style()->getRoundedInnerBorderFor(
|
|
paintRect, paddingTop() + borderTop(),
|
|
paddingBottom() + borderBottom(), paddingLeft() + borderLeft(),
|
|
paddingRight() + borderRight(), true, true);
|
|
clipRoundedInnerRect(paintInfo.context, paintRect, roundedInnerRect);
|
|
}
|
|
}
|
|
|
|
if (!completelyClippedOut) {
|
|
paintReplaced(paintInfo, adjustedPaintOffset);
|
|
if (style()->hasBorderRadius())
|
|
paintInfo.context->restore();
|
|
}
|
|
|
|
// The selection tint never gets clipped by border-radius rounding, since we
|
|
// want it to run right up to the edges of surrounding content.
|
|
if (selectionState() != SelectionNone) {
|
|
LayoutRect selectionPaintingRect = localSelectionRect();
|
|
selectionPaintingRect.moveBy(adjustedPaintOffset);
|
|
paintInfo.context->fillRect(pixelSnappedIntRect(selectionPaintingRect),
|
|
selectionBackgroundColor());
|
|
}
|
|
}
|
|
|
|
bool RenderReplaced::shouldPaint(PaintInfo& paintInfo,
|
|
const LayoutPoint& paintOffset) {
|
|
LayoutPoint adjustedPaintOffset = paintOffset + location();
|
|
|
|
// Early exit if the element touches the edges.
|
|
LayoutUnit top = adjustedPaintOffset.y() + visualOverflowRect().y();
|
|
LayoutUnit bottom = adjustedPaintOffset.y() + visualOverflowRect().maxY();
|
|
if (isSelected() && inlineBoxWrapper()) {
|
|
LayoutUnit selTop =
|
|
paintOffset.y() + inlineBoxWrapper()->root().selectionTop();
|
|
LayoutUnit selBottom =
|
|
paintOffset.y() + selTop + inlineBoxWrapper()->root().selectionHeight();
|
|
top = std::min(selTop, top);
|
|
bottom = std::max(selBottom, bottom);
|
|
}
|
|
|
|
if (adjustedPaintOffset.x() + visualOverflowRect().x() >=
|
|
paintInfo.rect.maxX() ||
|
|
adjustedPaintOffset.x() + visualOverflowRect().maxX() <=
|
|
paintInfo.rect.x())
|
|
return false;
|
|
|
|
if (top >= paintInfo.rect.maxY() || bottom <= paintInfo.rect.y())
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RenderReplaced::hasReplacedLogicalHeight() const {
|
|
if (style()->logicalHeight().isAuto())
|
|
return false;
|
|
|
|
if (style()->logicalHeight().isSpecified()) {
|
|
if (hasAutoHeightOrContainingBlockWithAutoHeight())
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
if (style()->logicalHeight().isIntrinsic())
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool RenderReplaced::needsPreferredWidthsRecalculation() const {
|
|
// If the height is a percentage and the width is auto, then the
|
|
// containingBlocks's height changing can cause this node to change it's
|
|
// preferred width because it maintains aspect ratio.
|
|
return hasRelativeLogicalHeight() && style()->logicalWidth().isAuto() &&
|
|
!hasAutoHeightOrContainingBlockWithAutoHeight();
|
|
}
|
|
|
|
static inline bool rendererHasAspectRatio(const RenderObject* renderer) {
|
|
ASSERT(renderer);
|
|
return renderer->isImage() || renderer->isCanvas();
|
|
}
|
|
|
|
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());
|
|
}
|
|
}
|
|
|
|
LayoutRect RenderReplaced::replacedContentRect(
|
|
const LayoutSize* overriddenIntrinsicSize) const {
|
|
LayoutRect contentRect = contentBoxRect();
|
|
ObjectFit objectFit = style()->objectFit();
|
|
|
|
if (objectFit == ObjectFitFill &&
|
|
style()->objectPosition() == RenderStyle::initialObjectPosition())
|
|
objectFit = ObjectFitContain;
|
|
|
|
LayoutSize intrinsicSize = overriddenIntrinsicSize ? *overriddenIntrinsicSize
|
|
: this->intrinsicSize();
|
|
if (!intrinsicSize.width() || !intrinsicSize.height())
|
|
return contentRect;
|
|
|
|
LayoutRect finalRect = contentRect;
|
|
switch (objectFit) {
|
|
case ObjectFitContain:
|
|
case ObjectFitScaleDown:
|
|
case ObjectFitCover:
|
|
finalRect.setSize(finalRect.size().fitToAspectRatio(
|
|
intrinsicSize, objectFit == ObjectFitCover ? AspectRatioFitGrow
|
|
: AspectRatioFitShrink));
|
|
if (objectFit != ObjectFitScaleDown ||
|
|
finalRect.width() <= intrinsicSize.width())
|
|
break;
|
|
// fall through
|
|
case ObjectFitNone:
|
|
finalRect.setSize(intrinsicSize);
|
|
break;
|
|
case ObjectFitFill:
|
|
break;
|
|
default:
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
|
|
LayoutUnit xOffset = minimumValueForLength(
|
|
style()->objectPosition().x(), contentRect.width() - finalRect.width());
|
|
LayoutUnit yOffset = minimumValueForLength(
|
|
style()->objectPosition().y(), contentRect.height() - finalRect.height());
|
|
finalRect.move(xOffset, yOffset);
|
|
|
|
return finalRect;
|
|
}
|
|
|
|
void RenderReplaced::computeIntrinsicRatioInformation(
|
|
FloatSize& intrinsicSize,
|
|
double& intrinsicRatio) const {
|
|
intrinsicSize = FloatSize(intrinsicLogicalWidth().toFloat(),
|
|
intrinsicLogicalHeight().toFloat());
|
|
|
|
// Figure out if we need to compute an intrinsic ratio.
|
|
if (intrinsicSize.isEmpty() || !rendererHasAspectRatio(this))
|
|
return;
|
|
|
|
intrinsicRatio = intrinsicSize.width() / intrinsicSize.height();
|
|
}
|
|
|
|
LayoutUnit RenderReplaced::computeReplacedLogicalWidth(
|
|
ShouldComputePreferred shouldComputePreferred) const {
|
|
if (style()->logicalWidth().isSpecified() ||
|
|
style()->logicalWidth().isIntrinsic())
|
|
return computeReplacedLogicalWidthRespectingMinMaxWidth(
|
|
computeReplacedLogicalWidthUsing(style()->logicalWidth()),
|
|
shouldComputePreferred);
|
|
|
|
// 10.3.2 Inline, replaced elements:
|
|
// http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-width
|
|
double intrinsicRatio = 0;
|
|
FloatSize constrainedSize;
|
|
computeAspectRatioInformationForRenderBox(constrainedSize, intrinsicRatio);
|
|
|
|
if (style()->logicalWidth().isAuto()) {
|
|
bool computedHeightIsAuto = hasAutoHeightOrContainingBlockWithAutoHeight();
|
|
bool hasIntrinsicWidth = constrainedSize.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 (computedHeightIsAuto && hasIntrinsicWidth)
|
|
return computeReplacedLogicalWidthRespectingMinMaxWidth(
|
|
constrainedSize.width(), shouldComputePreferred);
|
|
|
|
bool hasIntrinsicHeight = constrainedSize.height() > 0;
|
|
if (intrinsicRatio) {
|
|
// 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 &&
|
|
((computedHeightIsAuto && !hasIntrinsicWidth && hasIntrinsicHeight) ||
|
|
!computedHeightIsAuto)) {
|
|
LayoutUnit logicalHeight = computeReplacedLogicalHeight();
|
|
return computeReplacedLogicalWidthRespectingMinMaxWidth(
|
|
roundToInt(round(logicalHeight * intrinsicRatio)),
|
|
shouldComputePreferred);
|
|
}
|
|
|
|
// 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 (computedHeightIsAuto && !hasIntrinsicWidth && !hasIntrinsicHeight) {
|
|
if (shouldComputePreferred == ComputePreferred)
|
|
return 0;
|
|
// 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 = containingBlock()->availableLogicalWidth();
|
|
|
|
// This solves above equation for 'width' (== logicalWidth).
|
|
LayoutUnit marginStart =
|
|
minimumValueForLength(style()->marginStart(), logicalWidth);
|
|
LayoutUnit marginEnd =
|
|
minimumValueForLength(style()->marginEnd(), logicalWidth);
|
|
logicalWidth = std::max<LayoutUnit>(
|
|
0, logicalWidth -
|
|
(marginStart + marginEnd + (width() - clientWidth())));
|
|
return computeReplacedLogicalWidthRespectingMinMaxWidth(
|
|
logicalWidth, shouldComputePreferred);
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
return computeReplacedLogicalWidthRespectingMinMaxWidth(
|
|
constrainedSize.width(), shouldComputePreferred);
|
|
|
|
// 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. 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(), shouldComputePreferred);
|
|
}
|
|
|
|
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()));
|
|
|
|
// 10.6.2 Inline, replaced elements:
|
|
// http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-height
|
|
double intrinsicRatio = 0;
|
|
FloatSize constrainedSize;
|
|
computeAspectRatioInformationForRenderBox(constrainedSize, intrinsicRatio);
|
|
|
|
bool widthIsAuto = style()->logicalWidth().isAuto();
|
|
bool hasIntrinsicHeight = constrainedSize.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)
|
|
return computeReplacedLogicalHeightRespectingMinMaxHeight(
|
|
constrainedSize.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)
|
|
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)
|
|
return computeReplacedLogicalHeightRespectingMinMaxHeight(
|
|
constrainedSize.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(
|
|
intrinsicLogicalHeight());
|
|
}
|
|
|
|
void RenderReplaced::computeIntrinsicLogicalWidths(
|
|
LayoutUnit& minLogicalWidth,
|
|
LayoutUnit& maxLogicalWidth) const {
|
|
minLogicalWidth = maxLogicalWidth = intrinsicLogicalWidth();
|
|
}
|
|
|
|
void RenderReplaced::computePreferredLogicalWidths() {
|
|
ASSERT(preferredLogicalWidthsDirty());
|
|
|
|
// We cannot resolve any percent logical width here as the available logical
|
|
// width may not be set on our containing block.
|
|
if (style()->logicalWidth().isPercent())
|
|
computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth,
|
|
m_maxPreferredLogicalWidth);
|
|
else
|
|
m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth =
|
|
computeReplacedLogicalWidth(ComputePreferred);
|
|
|
|
RenderStyle* styleToUse = style();
|
|
if (styleToUse->logicalWidth().isPercent() ||
|
|
styleToUse->logicalMaxWidth().isPercent())
|
|
m_minPreferredLogicalWidth = 0;
|
|
|
|
if (styleToUse->logicalMinWidth().isFixed() &&
|
|
styleToUse->logicalMinWidth().value() > 0) {
|
|
m_maxPreferredLogicalWidth = std::max(
|
|
m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(
|
|
styleToUse->logicalMinWidth().value()));
|
|
m_minPreferredLogicalWidth = std::max(
|
|
m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(
|
|
styleToUse->logicalMinWidth().value()));
|
|
}
|
|
|
|
if (styleToUse->logicalMaxWidth().isFixed()) {
|
|
m_maxPreferredLogicalWidth = std::min(
|
|
m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(
|
|
styleToUse->logicalMaxWidth().value()));
|
|
m_minPreferredLogicalWidth = std::min(
|
|
m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(
|
|
styleToUse->logicalMaxWidth().value()));
|
|
}
|
|
|
|
LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
|
|
m_minPreferredLogicalWidth += borderAndPadding;
|
|
m_maxPreferredLogicalWidth += borderAndPadding;
|
|
|
|
clearPreferredLogicalWidthsDirty();
|
|
}
|
|
|
|
PositionWithAffinity RenderReplaced::positionForPoint(
|
|
const LayoutPoint& point) {
|
|
// FIXME: This code is buggy if the replaced element is relative positioned.
|
|
InlineBox* box = inlineBoxWrapper();
|
|
RootInlineBox* rootBox = box ? &box->root() : 0;
|
|
|
|
LayoutUnit top = rootBox ? rootBox->selectionTop() : logicalTop();
|
|
LayoutUnit bottom = rootBox ? rootBox->selectionBottom() : logicalBottom();
|
|
|
|
LayoutUnit blockDirectionPosition = point.y() + y();
|
|
|
|
if (blockDirectionPosition < top)
|
|
return createPositionWithAffinity(caretMinOffset(),
|
|
DOWNSTREAM); // coordinates are above
|
|
|
|
if (blockDirectionPosition >= bottom)
|
|
return createPositionWithAffinity(caretMaxOffset(),
|
|
DOWNSTREAM); // coordinates are below
|
|
|
|
return RenderBox::positionForPoint(point);
|
|
}
|
|
|
|
LayoutRect RenderReplaced::localSelectionRect(bool checkWhetherSelected) const {
|
|
if (checkWhetherSelected && !isSelected())
|
|
return LayoutRect();
|
|
|
|
if (!inlineBoxWrapper())
|
|
// We're a block-level replaced element. Just return our own dimensions.
|
|
return LayoutRect(LayoutPoint(), size());
|
|
|
|
RootInlineBox& root = inlineBoxWrapper()->root();
|
|
LayoutUnit newLogicalTop =
|
|
root.selectionTop() - inlineBoxWrapper()->logicalTop();
|
|
return LayoutRect(0, newLogicalTop, width(), root.selectionHeight());
|
|
}
|
|
|
|
void RenderReplaced::setSelectionState(SelectionState state) {
|
|
// The selection state for our containing block hierarchy is updated by the
|
|
// base class call.
|
|
RenderBox::setSelectionState(state);
|
|
|
|
if (!inlineBoxWrapper())
|
|
return;
|
|
|
|
if (canUpdateSelectionOnRootLineBoxes())
|
|
inlineBoxWrapper()->root().setHasSelectedChildren(isSelected());
|
|
}
|
|
|
|
bool RenderReplaced::isSelected() const {
|
|
return false;
|
|
}
|
|
|
|
} // namespace blink
|