Example #1
0
StyleDifference RenderStyle::visualInvalidationDiff(const RenderStyle& other) const
{
    // Note, we use .get() on each DataRef below because DataRef::operator== will do a deep
    // compare, which is duplicate work when we're going to compare each property inside
    // this function anyway.

    StyleDifference diff;

    if (diffNeedsFullLayout(other)) {
        diff.setNeedsFullLayout();
    } else if (position() != StaticPosition && surround->offset != other.surround->offset) {
        // Optimize for the case where a positioned layer is moving but not changing size.
        if (positionedObjectMovedOnly(surround->offset, other.surround->offset, m_box->width()))
            diff.setNeedsPositionedMovementLayout();
        else
            diff.setNeedsFullLayout();
    }

    updatePropertySpecificDifferences(other, diff);

    // Cursors are not checked, since they will be set appropriately in response to mouse events,
    // so they don't need to cause any paint invalidation or layout.

    return diff;
}
void RenderLayerModelObject::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
{
    s_wasFloating = isFloating();

    // If our z-index changes value or our visibility changes,
    // we need to dirty our stacking context's z-order list.
    RenderStyle* oldStyle = style();
    if (oldStyle) {
        // Do a repaint with the old style first through RenderLayerRepainter.
        // RenderObject::styleWillChange takes care of repainting objects without RenderLayers.
        if (parent() && diff.needsRepaintLayer()) {
            layer()->repainter().repaintIncludingNonCompositingDescendants();
            if (oldStyle->hasClip() != newStyle.hasClip()
                || oldStyle->clip() != newStyle.clip())
                layer()->clipper().clearClipRectsIncludingDescendants();
        } else if (diff.needsFullLayout()) {
            if (hasLayer()) {
                if (!layer()->hasCompositedLayerMapping() && oldStyle->position() != newStyle.position())
                    layer()->repainter().repaintIncludingNonCompositingDescendants();
            } else if (newStyle.hasTransform() || newStyle.opacity() < 1 || newStyle.hasFilter()) {
                // If we don't have a layer yet, but we are going to get one because of transform or opacity,
                //  then we need to repaint the old position of the object.
                paintInvalidationForWholeRenderer();
            }
        }
    }

    RenderObject::styleWillChange(diff, newStyle);
}
void RenderSVGResourceContainer::registerResource()
{
    SVGDocumentExtensions& extensions = svgExtensionsFromElement(element());
    if (!extensions.hasPendingResource(m_id)) {
        extensions.addResource(m_id, this);
        return;
    }

    OwnPtr<SVGDocumentExtensions::SVGPendingElements> clients(extensions.removePendingResource(m_id));

    // Cache us with the new id.
    extensions.addResource(m_id, this);

    // Update cached resources of pending clients.
    const SVGDocumentExtensions::SVGPendingElements::const_iterator end = clients->end();
    for (SVGDocumentExtensions::SVGPendingElements::const_iterator it = clients->begin(); it != end; ++it) {
        ASSERT((*it)->hasPendingResources());
        extensions.clearHasPendingResourcesIfPossible(*it);
        RenderObject* renderer = (*it)->renderer();
        if (!renderer)
            continue;

        StyleDifference diff;
        diff.setNeedsFullLayout();
        SVGResourcesCache::clientStyleChanged(renderer, diff, renderer->style());
        renderer->setNeedsLayoutAndFullPaintInvalidation();
    }
}
Example #4
0
void LayoutSVGRoot::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
{
    if (diff.needsFullLayout())
        setNeedsBoundariesUpdate();
    if (diff.needsPaintInvalidation()) {
        // Box decorations may have appeared/disappeared - recompute status.
        m_hasBoxDecorationBackground = calculateHasBoxDecorations();
    }

    LayoutReplaced::styleDidChange(diff, oldStyle);
    SVGResourcesCache::clientStyleChanged(this, diff, styleRef());
}
Example #5
0
void RenderSVGRoot::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    if (diff.needsFullLayout())
        setNeedsBoundariesUpdate();
    if (diff.needsRepaint()) {
        // Box decorations may have appeared/disappeared - recompute status.
        m_hasBoxDecorations = calculateHasBoxDecorations();
    }

    RenderReplaced::styleDidChange(diff, oldStyle);
    SVGResourcesCache::clientStyleChanged(this, diff, style());
}
Example #6
0
StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const
{
    StyleDifference styleDifference;

    if (diffNeedsLayoutAndPaintInvalidation(other)) {
        styleDifference.setNeedsFullLayout();
        styleDifference.setNeedsPaintInvalidationObject();
    } else if (diffNeedsPaintInvalidation(other)) {
        styleDifference.setNeedsPaintInvalidationObject();
    }

    return styleDifference;
}
Example #7
0
StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const
{
    StyleDifference styleDifference;

    if (diffNeedsLayoutAndRepaint(other)) {
        styleDifference.setNeedsFullLayout();
        styleDifference.setNeedsRepaintObject();
    } else if (diffNeedsRepaint(other)) {
        styleDifference.setNeedsRepaintObject();
    }

    return styleDifference;
}
Example #8
0
void LayoutTableRow::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
{
    ASSERT(style()->display() == TABLE_ROW);

    LayoutBox::styleDidChange(diff, oldStyle);
    propagateStyleToAnonymousChildren();

    if (section() && oldStyle && style()->logicalHeight() != oldStyle->logicalHeight())
        section()->rowLogicalHeightChanged(this);

    // If border was changed, notify table.
    if (parent()) {
        LayoutTable* table = this->table();
        if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
            table->invalidateCollapsedBorders();

        if (table && oldStyle && diff.needsFullLayout() && needsLayout() && table->collapseBorders() && borderWidthChanged(oldStyle, style())) {
            // If the border width changes on a row, we need to make sure the cells in the row know to lay out again.
            // This only happens when borders are collapsed, since they end up affecting the border sides of the cell
            // itself.
            for (LayoutBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
                if (!childBox->isTableCell())
                    continue;
                childBox->setChildNeedsLayout();
            }
        }
    }
}
Example #9
0
void LayoutSVGInline::styleDidChange(StyleDifference diff,
                                     const ComputedStyle* oldStyle) {
  if (diff.needsFullLayout())
    setNeedsBoundariesUpdate();

  LayoutInline::styleDidChange(diff, oldStyle);
  SVGResourcesCache::clientStyleChanged(this, diff, styleRef());
}
Example #10
0
void RenderStyle::updatePropertySpecificDifferences(const RenderStyle& other, StyleDifference& diff) const
{
    // StyleAdjuster has ensured that zIndex is non-auto only if it's applicable.
    if (m_box->zIndex() != other.m_box->zIndex() || m_box->hasAutoZIndex() != other.m_box->hasAutoZIndex())
        diff.setZIndexChanged();

    if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
        if (!transformDataEquivalent(other))
            diff.setTransformChanged();

        if (rareNonInheritedData->opacity != other.rareNonInheritedData->opacity)
            diff.setOpacityChanged();

        if (rareNonInheritedData->m_filter != other.rareNonInheritedData->m_filter)
            diff.setFilterChanged();
    }
}
void LayoutSVGBlock::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
{
    if (diff.needsFullLayout()) {
        setNeedsBoundariesUpdate();
        if (diff.transformChanged())
            setNeedsTransformUpdate();
    }

    if (isBlendingAllowed()) {
        bool hasBlendModeChanged = (oldStyle && oldStyle->hasBlendMode()) == !style()->hasBlendMode();
        if (parent() && hasBlendModeChanged)
            parent()->descendantIsolationRequirementsChanged(style()->hasBlendMode() ? DescendantIsolationRequired : DescendantIsolationNeedsUpdate);
    }

    LayoutBlock::styleDidChange(diff, oldStyle);
    SVGResourcesCache::clientStyleChanged(this, diff, styleRef());
}
Example #12
0
void RenderSVGBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    if (diff.needsFullLayout())
        setNeedsBoundariesUpdate();

    RenderBlock::styleDidChange(diff, oldStyle);
    SVGResourcesCache::clientStyleChanged(this, diff, style());
}
void LayoutScrollbarPart::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
{
    LayoutBlock::styleDidChange(diff, oldStyle);
    setInline(false);
    clearPositionedState();
    setFloating(false);
    setHasOverflowClip(false);
    if (oldStyle && m_scrollbar && m_part != NoPart && (diff.needsPaintInvalidation() || diff.needsLayout()))
        m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part);
}
Example #14
0
void LayoutSVGResourceContainer::registerResource()
{
    SVGDocumentExtensions& extensions = svgExtensionsFromElement(element());
    if (!extensions.hasPendingResource(m_id)) {
        extensions.addResource(m_id, this);
        return;
    }

    SVGDocumentExtensions::SVGPendingElements* clients(extensions.removePendingResource(m_id));

    // Cache us with the new id.
    extensions.addResource(m_id, this);

    // Update cached resources of pending clients.
    for (const auto& pendingClient : *clients) {
        ASSERT(pendingClient->hasPendingResources());
        extensions.clearHasPendingResourcesIfPossible(pendingClient);
        LayoutObject* layoutObject = pendingClient->layoutObject();
        if (!layoutObject)
            continue;

        const ComputedStyle& style = layoutObject->styleRef();

        // If the client has a layer (is a non-SVGElement) we need to signal
        // invalidation in the same way as is done in markAllResourceClientsForInvalidation above.
        if (layoutObject->hasLayer() && resourceType() == FilterResourceType) {
            if (style.hasFilter())
                toLayoutBoxModelObject(layoutObject)->layer()->filterNeedsPaintInvalidation();
            // If this is the SVG root, we could have both 'filter' and
            // '-webkit-filter' applied, so we need to do the invalidation
            // below as well, unless we can optimistically determine that
            // 'filter' does not apply to the element in question.
            if (!layoutObject->isSVGRoot() || !style.svgStyle().hasFilter())
                continue;
        }

        StyleDifference diff;
        diff.setNeedsFullLayout();
        SVGResourcesCache::clientStyleChanged(layoutObject, diff, style);
        layoutObject->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::SvgResourceInvalidated);
    }
}
void SVGInlineTextBoxPainter::paintText(const PaintInfo& paintInfo, const ComputedStyle& style,
    const ComputedStyle& selectionStyle, const SVGTextFragment& fragment,
    LayoutSVGResourceMode resourceMode, bool shouldPaintSelection)
{
    int startPosition = 0;
    int endPosition = 0;
    if (shouldPaintSelection) {
        m_svgInlineTextBox.selectionStartEnd(startPosition, endPosition);
        shouldPaintSelection = m_svgInlineTextBox.mapStartEndPositionsIntoFragmentCoordinates(fragment, startPosition, endPosition);
    }

    // Fast path if there is no selection, just draw the whole chunk part using the regular style
    TextRun textRun = m_svgInlineTextBox.constructTextRun(style, fragment);
    if (!shouldPaintSelection || startPosition >= endPosition) {
        paintTextWithShadows(paintInfo, style, textRun, fragment, 0, fragment.length, resourceMode);
        return;
    }

    // Eventually draw text using regular style until the start position of the selection
    bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection;
    if (startPosition > 0 && !paintSelectedTextOnly)
        paintTextWithShadows(paintInfo, style, textRun, fragment, 0, startPosition, resourceMode);

    // Draw text using selection style from the start to the end position of the selection
    if (style != selectionStyle) {
        StyleDifference diff;
        diff.setNeedsPaintInvalidationObject();
        SVGResourcesCache::clientStyleChanged(&m_svgInlineTextBox.parent()->layoutObject(), diff, selectionStyle);
    }

    paintTextWithShadows(paintInfo, selectionStyle, textRun, fragment, startPosition, endPosition, resourceMode);

    if (style != selectionStyle) {
        StyleDifference diff;
        diff.setNeedsPaintInvalidationObject();
        SVGResourcesCache::clientStyleChanged(&m_svgInlineTextBox.parent()->layoutObject(), diff, style);
    }

    // Eventually draw text using regular style from the end position of the selection to the end of the current chunk part
    if (endPosition < static_cast<int>(fragment.length) && !paintSelectedTextOnly)
        paintTextWithShadows(paintInfo, style, textRun, fragment, endPosition, fragment.length, resourceMode);
}
Example #16
0
void RenderSVGModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    if (diff.needsFullLayout()) {
        setNeedsBoundariesUpdate();
        if (style()->hasTransform())
            setNeedsTransformUpdate();
    }

    RenderObject::styleDidChange(diff, oldStyle);
    SVGResourcesCache::clientStyleChanged(this, diff, style());
}
void RenderLayerModelObject::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
{
    if (RenderStyle* oldStyle = style()) {
        if (parent() && diff.needsPaintInvalidationLayer()) {
            if (oldStyle->hasAutoClip() != newStyle.hasAutoClip()
                || oldStyle->clip() != newStyle.clip())
                layer()->clipper().clearClipRectsIncludingDescendants();
        }
    }

    RenderObject::styleWillChange(diff, newStyle);
}
void SVGResourcesCache::clientStyleChanged(LayoutObject* layoutObject, StyleDifference diff, const ComputedStyle& newStyle)
{
    ASSERT(layoutObject);
    ASSERT(layoutObject->node());
    ASSERT(layoutObject->node()->isSVGElement());

    if (!diff.hasDifference() || !layoutObject->parent())
        return;

    // In this case the proper SVGFE*Element will decide whether the modified CSS properties require a relayout or paintInvalidation.
    if (layoutObject->isSVGResourceFilterPrimitive() && !diff.needsLayout())
        return;

    // Dynamic changes of CSS properties like 'clip-path' may require us to recompute the associated resources for a layoutObject.
    // FIXME: Avoid passing in a useless StyleDifference, but instead compare oldStyle/newStyle to see which resources changed
    // to be able to selectively rebuild individual resources, instead of all of them.
    if (layoutObjectCanHaveResources(layoutObject)) {
        SVGResourcesCache* cache = resourcesCacheFromLayoutObject(layoutObject);
        cache->removeResourcesFromLayoutObject(layoutObject);
        cache->addResourcesFromLayoutObject(layoutObject, newStyle);
    }

    LayoutSVGResourceContainer::markForLayoutAndParentResourceInvalidation(layoutObject, false);
}
void LayoutSVGRect::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
{
    if (diff.needsFullLayout() && oldStyle) {
        const SVGComputedStyle& oldSvgStyle = oldStyle->svgStyle();
        const SVGComputedStyle& svgStyle = style()->svgStyle();
        if (oldSvgStyle.rx() != svgStyle.rx()
            || oldSvgStyle.ry() != svgStyle.ry()
            || oldSvgStyle.vectorEffect() != svgStyle.vectorEffect()
            || definitelyHasSimpleStroke(oldSvgStyle) != definitelyHasSimpleStroke(svgStyle))
            setNeedsShapeUpdate();
    }

    // Superclass will take care of calling clientStyleChanged.
    LayoutSVGShape::styleDidChange(diff, oldStyle);
}
void RenderSVGGradientStop::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    RenderObject::styleDidChange(diff, oldStyle);
    if (!diff.hasDifference())
        return;

    // <stop> elements should only be allowed to make renderers under gradient elements
    // but I can imagine a few cases we might not be catching, so let's not crash if our parent isn't a gradient.
    SVGGradientElement* gradient = gradientElement();
    if (!gradient)
        return;

    RenderObject* renderer = gradient->renderer();
    if (!renderer)
        return;

    RenderSVGResourceContainer* container = toRenderSVGResourceContainer(renderer);
    container->removeAllClientsFromCache();
}
void LayoutSVGInlineText::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
{
    LayoutText::styleDidChange(diff, oldStyle);
    updateScaledFont();

    bool newPreserves = style() ? style()->whiteSpace() == PRE : false;
    bool oldPreserves = oldStyle ? oldStyle->whiteSpace() == PRE : false;
    if (oldPreserves != newPreserves) {
        setText(originalText(), true);
        return;
    }

    if (!diff.needsFullLayout())
        return;

    // The text metrics may be influenced by style changes.
    if (LayoutSVGText* textLayoutObject = LayoutSVGText::locateLayoutSVGTextAncestor(this))
        textLayoutObject->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::StyleChange);
}
void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    m_desiredInnerEditorLogicalHeight = -1;
    RenderTextControl::styleDidChange(diff, oldStyle);

    // We may have set the width and the height in the old style in layout().
    // Reset them now to avoid getting a spurious layout hint.
    Element* viewPort = editingViewPortElement();
    if (RenderObject* viewPortRenderer = viewPort ? viewPort->renderer() : 0) {
        viewPortRenderer->style()->setHeight(Length());
        viewPortRenderer->style()->setWidth(Length());
    }
    Element* container = containerElement();
    if (RenderObject* containerRenderer = container ? container->renderer() : 0) {
        containerRenderer->style()->setHeight(Length());
        containerRenderer->style()->setWidth(Length());
    }
    RenderObject* innerEditorRenderer = innerEditorElement()->renderer();
    if (innerEditorRenderer && diff.needsFullLayout())
        innerEditorRenderer->setNeedsLayoutAndFullPaintInvalidation();
    if (HTMLElement* placeholder = inputElement()->placeholderElement())
        placeholder->setInlineStyleProperty(CSSPropertyTextOverflow, textShouldBeTruncated() ? CSSValueEllipsis : CSSValueClip);
    setHasOverflowClip(false);
}