PaintInvalidationState::PaintInvalidationState(PaintInvalidationState& next, LayoutBoxModelObject& layoutObject, const LayoutBoxModelObject& paintInvalidationContainer)
    : m_clipped(false)
    , m_cachedOffsetsEnabled(true)
    , m_forcedSubtreeInvalidationWithinContainer(next.m_forcedSubtreeInvalidationWithinContainer)
    , m_forcedSubtreeInvalidationRectUpdateWithinContainer(next.m_forcedSubtreeInvalidationRectUpdateWithinContainer)
    , m_viewClippingAndScrollOffsetDisabled(false)
    , m_paintInvalidationContainer(paintInvalidationContainer)
    , m_pendingDelayedPaintInvalidations(next.pendingDelayedPaintInvalidationTargets())
    , m_enclosingSelfPaintingLayer(next.enclosingSelfPaintingLayer(layoutObject))
{
    // FIXME: SVG could probably benefit from a stack-based optimization like html does. crbug.com/391054
    bool establishesPaintInvalidationContainer = layoutObject == m_paintInvalidationContainer;
    bool fixed = layoutObject.style()->position() == FixedPosition;

    if (!layoutObject.supportsPaintInvalidationStateCachedOffsets() || !next.m_cachedOffsetsEnabled)
        m_cachedOffsetsEnabled = false;
    if (establishesPaintInvalidationContainer) {
        // When we hit a new paint invalidation container, we don't need to
        // continue forcing a check for paint invalidation, since we're
        // descending into a different invalidation container. (For instance if
        // our parents were moved, the entire container will just move.)
        m_forcedSubtreeInvalidationWithinContainer = false;
    } else {
        if (m_cachedOffsetsEnabled) {
            if (fixed) {
                FloatPoint fixedOffset = layoutObject.localToAncestorPoint(FloatPoint(), &m_paintInvalidationContainer, TraverseDocumentBoundaries);
                m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y());
            } else {
                LayoutSize offset = layoutObject.isBox() && !layoutObject.isTableRow() ? toLayoutBox(layoutObject).locationOffset() : LayoutSize();
                m_paintOffset = next.m_paintOffset + offset;
            }

            if (layoutObject.isOutOfFlowPositioned() && !fixed) {
                if (LayoutObject* container = layoutObject.container()) {
                    if (container->style()->hasInFlowPosition() && container->isLayoutInline())
                        m_paintOffset += toLayoutInline(container)->offsetForInFlowPositionedInline(toLayoutBox(layoutObject));
                }
            }

            if (layoutObject.style()->hasInFlowPosition() && layoutObject.hasLayer())
                m_paintOffset += layoutObject.layer()->offsetForInFlowPosition();
        }

        m_clipped = !fixed && next.m_clipped;
        if (m_clipped)
            m_clipRect = next.m_clipRect;
    }

    if (m_cachedOffsetsEnabled && layoutObject.isSVGRoot()) {
        const LayoutSVGRoot& svgRoot = toLayoutSVGRoot(layoutObject);
        m_svgTransform = AffineTransform(svgRoot.localToBorderBoxTransform());
        if (svgRoot.shouldApplyViewportClip())
            addClipRectRelativeToPaintOffset(LayoutSize(svgRoot.pixelSnappedSize()));
    }

    applyClipIfNeeded(layoutObject);

    // FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present.
}
AXObject* AXObjectCacheImpl::createFromRenderer(LayoutObject* layoutObject)
{
    // FIXME: How could layoutObject->node() ever not be an Element?
    Node* node = layoutObject->node();

    // If the node is aria role="list" or the aria role is empty and its a
    // ul/ol/dl type (it shouldn't be a list if aria says otherwise).
    if (nodeHasRole(node, "list") || nodeHasRole(node, "directory")
        || (nodeHasRole(node, nullAtom) && (isHTMLUListElement(node) || isHTMLOListElement(node) || isHTMLDListElement(node))))
        return AXList::create(layoutObject, *this);

    // aria tables
    if (nodeHasRole(node, "grid") || nodeHasRole(node, "treegrid"))
        return AXARIAGrid::create(layoutObject, *this);
    if (nodeHasRole(node, "row"))
        return AXARIAGridRow::create(layoutObject, *this);
    if (nodeHasRole(node, "gridcell") || nodeHasRole(node, "columnheader") || nodeHasRole(node, "rowheader"))
        return AXARIAGridCell::create(layoutObject, *this);

    // media controls
    if (node && node->isMediaControlElement())
        return AccessibilityMediaControl::create(layoutObject, *this);

    if (isHTMLOptionElement(node))
        return AXListBoxOption::create(layoutObject, *this);

    if (layoutObject->isSVGRoot())
        return AXSVGRoot::create(layoutObject, *this);

    if (layoutObject->isBoxModelObject()) {
        LayoutBoxModelObject* cssBox = toLayoutBoxModelObject(layoutObject);
        if (cssBox->isListBox())
            return AXListBox::create(toLayoutListBox(cssBox), *this);
        if (cssBox->isMenuList())
            return AXMenuList::create(toLayoutMenuList(cssBox), *this);

        // standard tables
        if (cssBox->isTable())
            return AXTable::create(toLayoutTable(cssBox), *this);
        if (cssBox->isTableRow())
            return AXTableRow::create(toLayoutTableRow(cssBox), *this);
        if (cssBox->isTableCell())
            return AXTableCell::create(toLayoutTableCell(cssBox), *this);

        // progress bar
        if (cssBox->isProgress())
            return AXProgressIndicator::create(toLayoutProgress(cssBox), *this);

        // input type=range
        if (cssBox->isSlider())
            return AXSlider::create(toLayoutSlider(cssBox), *this);
    }

    return AXLayoutObject::create(layoutObject, *this);
}