Пример #1
0
void AXTableColumn::headerObjectsForColumn(AXObjectVector& headers) {
  if (!m_parent)
    return;

  LayoutObject* layoutObject = m_parent->getLayoutObject();
  if (!layoutObject)
    return;

  if (!m_parent->isAXTable())
    return;

  if (toAXTable(m_parent)->isAriaTable()) {
    for (const auto& cell : children()) {
      if (cell->roleValue() == ColumnHeaderRole)
        headers.append(cell);
    }
    return;
  }

  if (!layoutObject->isTable())
    return;

  LayoutTable* table = toLayoutTable(layoutObject);
  LayoutTableSection* tableSection = table->topSection();
  for (; tableSection;
       tableSection = table->sectionBelow(tableSection, SkipEmptySections)) {
    unsigned numCols = tableSection->numEffectiveColumns();
    if (m_columnIndex >= numCols)
      continue;
    unsigned numRows = tableSection->numRows();
    for (unsigned r = 0; r < numRows; r++) {
      LayoutTableCell* layoutCell =
          tableSection->primaryCellAt(r, m_columnIndex);
      if (!layoutCell)
        continue;

      AXObject* cell = axObjectCache().getOrCreate(layoutCell->node());
      if (!cell || !cell->isTableCell() || headers.contains(cell))
        continue;

      if (toAXTableCell(cell)->scanToDecideHeaderRole() == ColumnHeaderRole)
        headers.append(cell);
    }
  }
}
void PaintPropertyTreeBuilder::walk(LayoutObject& object, const PaintPropertyTreeBuilderContext& context)
{
    PaintPropertyTreeBuilderContext localContext(context);

    deriveBorderBoxFromContainerContext(object, localContext);
    RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = createPaintOffsetTranslationIfNeeded(object, localContext);
    RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = createTransformIfNeeded(object, localContext);
    RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext);
    RefPtr<ClipPaintPropertyNode> newClipNodeForOverflowClip = createOverflowClipIfNeeded(object, localContext);
    // TODO(trchen): Insert flattening transform here, as specified by
    // http://www.w3.org/TR/css3-transforms/#transform-style-property
    RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPerspectiveIfNeeded(object, localContext);
    RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = createScrollTranslationIfNeeded(object, localContext);
    updateOutOfFlowContext(object, newTransformNodeForTransform, localContext);

    if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransform || newEffectNode || newClipNodeForOverflowClip || newTransformNodeForPerspective || newTransformNodeForScrollTranslation) {
        OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProperties::create(
            newTransformNodeForPaintOffsetTranslation.release(),
            newTransformNodeForTransform.release(),
            newEffectNode.release(),
            newClipNodeForOverflowClip.release(),
            newTransformNodeForPerspective.release(),
            newTransformNodeForScrollTranslation.release());
        object.setObjectPaintProperties(updatedPaintProperties.release());
    } else {
        object.clearObjectPaintProperties();
    }

    for (LayoutObject* child = object.slowFirstChild(); child; child = child->nextSibling()) {
        if (child->isBoxModelObject() || child->isSVG())
            walk(*child, localContext);
    }
}
Пример #3
0
void PseudoElement::attach(const AttachContext& context)
{
    ASSERT(!layoutObject());

    Element::attach(context);

    LayoutObject* layoutObject = this->layoutObject();
    if (!layoutObject)
        return;

    ComputedStyle& style = layoutObject->mutableStyleRef();
    if (style.styleType() != BEFORE && style.styleType() != AFTER)
        return;
    ASSERT(style.contentData());

    for (const ContentData* content = style.contentData(); content; content = content->next()) {
        LayoutObject* child = content->createLayoutObject(document(), style);
        if (layoutObject->isChildAllowed(child, style)) {
            layoutObject->addChild(child);
            if (child->isQuote())
                toLayoutQuote(child)->attachQuote();
        } else {
            child->destroy();
        }
    }
}
Пример #4
0
bool MediaControlsPainter::paintMediaSliderThumb(const LayoutObject& object, const PaintInfo& paintInfo, const IntRect& rect)
{
    if (!object.node())
        return false;

    const HTMLMediaElement* mediaElement = toParentMediaElement(object.node()->shadowHost());
    if (!mediaElement)
        return false;

    if (!hasSource(mediaElement))
        return true;

    Image* mediaSliderThumb = getMediaSliderThumb();
    IntRect paintRect;
    const ComputedStyle& style = object.styleRef();
    adjustMediaSliderThumbPaintSize(rect, style, paintRect);
    return paintMediaButton(paintInfo.context, paintRect, mediaSliderThumb);
}
static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
{
    const ComputedStyle& style = object.styleRef();
    if (!style.hasOpacity())
        return nullptr;
    RefPtr<EffectPaintPropertyNode> newEffectNode = EffectPaintPropertyNode::create(style.opacity(), context.currentEffect);
    context.currentEffect = newEffectNode.get();
    return newEffectNode.release();
}
Пример #6
0
bool LayoutTheme::isSpinUpButtonPartPressed(const LayoutObject& o)
{
    Node* node = o.node();
    if (!node || !node->active() || !node->isElementNode()
        || !toElement(node)->isSpinButtonElement())
        return false;
    SpinButtonElement* element = toSpinButtonElement(node);
    return element->upDownState() == SpinButtonElement::Up;
}
void AutoscrollController::updateAutoscrollLayoutObject()
{
    if (!m_autoscrollLayoutObject)
        return;

    LayoutObject* layoutObject = m_autoscrollLayoutObject;

#if OS(WIN)
    HitTestResult hitTest = layoutObject->frame()->eventHandler().hitTestResultAtPoint(m_panScrollStartPos, HitTestRequest::ReadOnly | HitTestRequest::Active);

    if (Node* nodeAtPoint = hitTest.innerNode())
        layoutObject = nodeAtPoint->layoutObject();
#endif

    while (layoutObject && !(layoutObject->isBox() && toLayoutBox(layoutObject)->canAutoscroll()))
        layoutObject = layoutObject->parent();
    m_autoscrollLayoutObject = layoutObject && layoutObject->isBox() ? toLayoutBox(layoutObject) : nullptr;
}
Пример #8
0
bool LayoutTheme::controlStateChanged(LayoutObject& o, ControlState state) const
{
    if (!o.styleRef().hasAppearance())
        return false;

    // Default implementation assumes the controls don't respond to changes in :hover state
    if (state == HoverControlState && !supportsHover(o.styleRef()))
        return false;

    // Assume pressed state is only responded to if the control is enabled.
    if (state == PressedControlState && !isEnabled(&o))
        return false;

    o.setShouldDoFullPaintInvalidation();
    if (RuntimeEnabledFeatures::slimmingPaintEnabled())
        o.invalidateDisplayItemClientForNonCompositingDescendants();
    return true;
}
Пример #9
0
void SVGLayoutSupport::mapLocalToAncestor(const LayoutObject* object,
                                          const LayoutBoxModelObject* ancestor,
                                          TransformState& transformState,
                                          MapCoordinatesFlags flags) {
  transformState.applyTransform(object->localToSVGParentTransform());

  LayoutObject* parent = object->parent();

  // At the SVG/HTML boundary (aka LayoutSVGRoot), we apply the
  // localToBorderBoxTransform to map an element from SVG viewport coordinates
  // to CSS box coordinates.
  // LayoutSVGRoot's mapLocalToAncestor method expects CSS box coordinates.
  if (parent->isSVGRoot())
    transformState.applyTransform(
        toLayoutSVGRoot(parent)->localToBorderBoxTransform());

  parent->mapLocalToAncestor(ancestor, transformState, flags);
}
Пример #10
0
bool SVGLayoutSupport::pointInClippingArea(const LayoutObject& object,
                                           const FloatPoint& point) {
  ClipPathOperation* clipPathOperation = object.styleRef().clipPath();
  if (!clipPathOperation)
    return true;
  if (clipPathOperation->type() == ClipPathOperation::SHAPE) {
    ShapeClipPathOperation& clipPath =
        toShapeClipPathOperation(*clipPathOperation);
    return clipPath.path(object.objectBoundingBox()).contains(point);
  }
  DCHECK_EQ(clipPathOperation->type(), ClipPathOperation::REFERENCE);
  SVGResources* resources =
      SVGResourcesCache::cachedResourcesForLayoutObject(&object);
  if (!resources || !resources->clipper())
    return true;
  return resources->clipper()->hitTestClipContent(object.objectBoundingBox(),
                                                  point);
}
static WebLayer* webLayerFromElement(Element* element)
{
    if (!element)
        return 0;
    LayoutObject* layoutObject = element->layoutObject();
    if (!layoutObject || !layoutObject->isBoxModelObject())
        return 0;
    PaintLayer* layer = toLayoutBoxModelObject(layoutObject)->layer();
    if (!layer)
        return 0;
    if (!layer->hasCompositedLayerMapping())
        return 0;
    CompositedLayerMapping* compositedLayerMapping = layer->compositedLayerMapping();
    GraphicsLayer* graphicsLayer = compositedLayerMapping->mainGraphicsLayer();
    if (!graphicsLayer)
        return 0;
    return graphicsLayer->platformLayer();
}
void PaintPropertyTreeBuilder::updateScrollTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
{
    if (!object.isBoxModelObject() || !object.hasOverflowClip())
        return;

    PaintLayer* layer = toLayoutBoxModelObject(object).layer();
    ASSERT(layer);
    DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset();
    if (scrollOffset.isZero() && !layer->scrollsOverflow())
        return;

    RefPtr<TransformPaintPropertyNode> scrollTranslation = TransformPaintPropertyNode::create(
        TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.height()),
        FloatPoint3D(),
        context.currentTransform);
    context.currentTransform = scrollTranslation.get();
    object.getMutableForPainting().ensureObjectPaintProperties().setScrollTranslation(scrollTranslation.release());
}
// TODO(trchen): Remove this once we bake the paint offset into frameRect.
void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(const LayoutObject& object, const PaintPropertyTreeBuilderContext& context)
{
    IntPoint roundedPaintOffset = roundedIntPoint(context.paintOffset);
    if (roundedPaintOffset == IntPoint())
        return;

    if (!object.isBoxModelObject())
        return;
    PaintLayerScrollableArea* scrollableArea = toLayoutBoxModelObject(object).getScrollableArea();
    if (!scrollableArea)
        return;
    if (!scrollableArea->horizontalScrollbar() && !scrollableArea->verticalScrollbar())
        return;

    auto paintOffset = TransformationMatrix().translate(roundedPaintOffset.x(), roundedPaintOffset.y());
    object.getMutableForPainting().ensureObjectPaintProperties().setScrollbarPaintOffset(
        TransformPaintPropertyNode::create(paintOffset, FloatPoint3D(), context.currentTransform));
}
void PaintPropertyTreeBuilder::updateCssClip(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
{
    if (!object.hasClip())
        return;
    ASSERT(object.canContainAbsolutePositionObjects());

    // Create clip node for descendants that are not fixed position.
    // We don't have to setup context.clipForAbsolutePosition here because this object must be
    // a container for absolute position descendants, and will copy from in-flow context later
    // at updateOutOfFlowContext() step.
    LayoutRect clipRect = toLayoutBox(object).clipRect(context.paintOffset);
    RefPtr<ClipPaintPropertyNode> clipNode = ClipPaintPropertyNode::create(
        context.currentTransform,
        FloatRoundedRect(FloatRect(clipRect)),
        context.currentClip);
    context.currentClip = clipNode.get();
    object.getMutableForPainting().ensureObjectPaintProperties().setCssClip(clipNode.release());
}
void SVGSVGElement::svgAttributeChanged(const QualifiedName& attrName)
{
    bool updateRelativeLengthsOrViewBox = false;
    bool widthOrHeightChanged = attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr;
    if (widthOrHeightChanged
        || attrName == SVGNames::xAttr
        || attrName == SVGNames::yAttr) {
        updateRelativeLengthsOrViewBox = true;
        updateRelativeLengthsInformation();
        invalidateRelativeLengthClients();

        // At the SVG/HTML boundary (aka LayoutSVGRoot), the width and
        // height attributes can affect the replaced size so we need
        // to mark it for updating.
        if (widthOrHeightChanged) {
            LayoutObject* layoutObject = this->layoutObject();
            if (layoutObject && layoutObject->isSVGRoot()) {
                invalidateSVGPresentationAttributeStyle();
                setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::SVGContainerSizeChange));
            }
        } else {
            invalidateSVGPresentationAttributeStyle();
            setNeedsStyleRecalc(LocalStyleChange,
                StyleChangeReasonForTracing::fromAttribute(attrName));
        }
    }

    if (SVGFitToViewBox::isKnownAttribute(attrName)) {
        updateRelativeLengthsOrViewBox = true;
        invalidateRelativeLengthClients();
        if (LayoutObject* object = layoutObject())
            object->setNeedsTransformUpdate();
    }

    if (updateRelativeLengthsOrViewBox
        || SVGZoomAndPan::isKnownAttribute(attrName)) {
        SVGElement::InvalidationGuard invalidationGuard(this);
        if (layoutObject())
            markForLayoutAndParentResourceInvalidation(layoutObject());
        return;
    }

    SVGGraphicsElement::svgAttributeChanged(attrName);
}
Пример #16
0
void LayoutCounter::layoutObjectStyleChanged(LayoutObject& layoutObject, const ComputedStyle* oldStyle, const ComputedStyle& newStyle)
{
    Node* node = layoutObject.generatingNode();
    if (!node || node->needsAttach())
        return; // cannot have generated content or if it can have, it will be handled during attaching
    const CounterDirectiveMap* oldCounterDirectives = oldStyle ? oldStyle->counterDirectives() : 0;
    const CounterDirectiveMap* newCounterDirectives = newStyle.counterDirectives();
    if (oldCounterDirectives) {
        if (newCounterDirectives) {
            CounterDirectiveMap::const_iterator newMapEnd = newCounterDirectives->end();
            CounterDirectiveMap::const_iterator oldMapEnd = oldCounterDirectives->end();
            for (CounterDirectiveMap::const_iterator it = newCounterDirectives->begin(); it != newMapEnd; ++it) {
                CounterDirectiveMap::const_iterator oldMapIt = oldCounterDirectives->find(it->key);
                if (oldMapIt != oldMapEnd) {
                    if (oldMapIt->value == it->value)
                        continue;
                    LayoutCounter::destroyCounterNode(layoutObject, it->key);
                }
                // We must create this node here, because the changed node may be a node with no display such as
                // as those created by the increment or reset directives and the re-layout that will happen will
                // not catch the change if the node had no children.
                makeCounterNode(layoutObject, it->key, false);
            }
            // Destroying old counters that do not exist in the new counterDirective map.
            for (CounterDirectiveMap::const_iterator it = oldCounterDirectives->begin(); it !=oldMapEnd; ++it) {
                if (!newCounterDirectives->contains(it->key))
                    LayoutCounter::destroyCounterNode(layoutObject, it->key);
            }
        } else {
            if (layoutObject.hasCounterNodeMap())
                LayoutCounter::destroyCounterNodes(layoutObject);
        }
    } else if (newCounterDirectives) {
        if (layoutObject.hasCounterNodeMap())
            LayoutCounter::destroyCounterNodes(layoutObject);
        CounterDirectiveMap::const_iterator newMapEnd = newCounterDirectives->end();
        for (CounterDirectiveMap::const_iterator it = newCounterDirectives->begin(); it != newMapEnd; ++it) {
            // We must create this node here, because the added node may be a node with no display such as
            // as those created by the increment or reset directives and the re-layout that will happen will
            // not catch the change if the node had no children.
            makeCounterNode(layoutObject, it->key, false);
        }
    }
}
Пример #17
0
void SVGLayoutSupport::layoutChildren(LayoutObject* start, bool selfNeedsLayout)
{
    // When hasRelativeLengths() is false, no descendants have relative lengths
    // (hence no one is interested in viewport size changes).
    bool layoutSizeChanged = toSVGElement(start->node())->hasRelativeLengths()
        && layoutSizeOfNearestViewportChanged(start);
    bool transformChanged = transformToRootChanged(start);

    for (LayoutObject* child = start->slowFirstChild(); child; child = child->nextSibling()) {
        bool forceLayout = selfNeedsLayout;

        if (transformChanged) {
            // If the transform changed we need to update the text metrics (note: this also happens for layoutSizeChanged=true).
            if (child->isSVGText())
                toLayoutSVGText(child)->setNeedsTextMetricsUpdate();
            forceLayout = true;
        }

        if (layoutSizeChanged) {
            // When selfNeedsLayout is false and the layout size changed, we have to check whether this child uses relative lengths
            if (SVGElement* element = child->node()->isSVGElement() ? toSVGElement(child->node()) : 0) {
                if (element->hasRelativeLengths()) {
                    // FIXME: this should be done on invalidation, not during layout.
                    // When the layout size changed and when using relative values tell the LayoutSVGShape to update its shape object
                    if (child->isSVGShape()) {
                        toLayoutSVGShape(child)->setNeedsShapeUpdate();
                    } else if (child->isSVGText()) {
                        toLayoutSVGText(child)->setNeedsTextMetricsUpdate();
                        toLayoutSVGText(child)->setNeedsPositioningValuesUpdate();
                    }

                    forceLayout = true;
                }
            }
        }

        SubtreeLayoutScope layoutScope(*child);
        // Resource containers are nasty: they can invalidate clients outside the current SubtreeLayoutScope.
        // Since they only care about viewport size changes (to resolve their relative lengths), we trigger
        // their invalidation directly from SVGSVGElement::svgAttributeChange() or at a higher
        // SubtreeLayoutScope (in LayoutView::layout()).
        if (forceLayout && !child->isSVGResourceContainer())
            layoutScope.setNeedsLayout(child, LayoutInvalidationReason::SvgChanged);

        // Lay out any referenced resources before the child.
        layoutResourcesIfNeeded(child);
        child->layoutIfNeeded();
    }
}
PassRefPtr<const SkPicture> LayoutSVGResourceMasker::createContentPicture(AffineTransform& contentTransformation, const FloatRect& targetBoundingBox)
{
    SVGUnitTypes::SVGUnitType contentUnits = toSVGMaskElement(element())->maskContentUnits()->currentValue()->enumValue();
    if (contentUnits == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
        contentTransformation.translate(targetBoundingBox.x(), targetBoundingBox.y());
        contentTransformation.scaleNonUniform(targetBoundingBox.width(), targetBoundingBox.height());
    }

    if (m_maskContentPicture)
        return m_maskContentPicture;

    SubtreeContentTransformScope contentTransformScope(contentTransformation);

    // Using strokeBoundingBox (instead of paintInvalidationRectInLocalCoordinates) to avoid the intersection
    // with local clips/mask, which may yield incorrect results when mixing objectBoundingBox and
    // userSpaceOnUse units (http://crbug.com/294900).
    FloatRect bounds = strokeBoundingBox();

    OwnPtr<DisplayItemList> displayItemList;
    if (RuntimeEnabledFeatures::slimmingPaintEnabled())
        displayItemList = DisplayItemList::create();
    GraphicsContext context(nullptr, displayItemList.get());
    context.beginRecording(bounds);

    ColorFilter maskContentFilter = style()->svgStyle().colorInterpolation() == CI_LINEARRGB
                                    ? ColorFilterSRGBToLinearRGB : ColorFilterNone;
    context.setColorFilter(maskContentFilter);

    for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
        LayoutObject* layoutObject = childElement->layoutObject();
        if (!layoutObject)
            continue;
        const ComputedStyle* style = layoutObject->style();
        if (!style || style->display() == NONE || style->visibility() != VISIBLE)
            continue;

        SVGPaintContext::paintSubtree(&context, layoutObject);
    }

    if (displayItemList)
        displayItemList->commitNewDisplayItemsAndReplay(context);
    m_maskContentPicture = context.endRecording();
    return m_maskContentPicture;
}
Пример #19
0
bool SVGClipPainter::applyClippingToContext(const LayoutObject& target, const FloatRect& targetBoundingBox,
    const FloatRect& paintInvalidationRect, GraphicsContext* context, ClipperState& clipperState)
{
    ASSERT(context);
    ASSERT(clipperState == ClipperNotApplied);
    ASSERT_WITH_SECURITY_IMPLICATION(!m_clip.needsLayout());

    if (paintInvalidationRect.isEmpty() || m_clip.hasCycle())
        return false;

    SVGClipExpansionCycleHelper inClipExpansionChange(m_clip);

    AffineTransform animatedLocalTransform = toSVGClipPathElement(m_clip.element())->calculateAnimatedLocalTransform();
    // When drawing a clip for non-SVG elements, the CTM does not include the zoom factor.
    // In this case, we need to apply the zoom scale explicitly - but only for clips with
    // userSpaceOnUse units (the zoom is accounted for objectBoundingBox-resolved lengths).
    if (!target.isSVG() && m_clip.clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) {
        ASSERT(m_clip.style());
        animatedLocalTransform.scale(m_clip.style()->effectiveZoom());
    }

    // First, try to apply the clip as a clipPath.
    if (m_clip.tryPathOnlyClipping(target, context, animatedLocalTransform, targetBoundingBox)) {
        clipperState = ClipperAppliedPath;
        return true;
    }

    // Fall back to masking.
    clipperState = ClipperAppliedMask;

    // Begin compositing the clip mask.
    CompositingRecorder::beginCompositing(*context, target, SkXfermode::kSrcOver_Mode, 1, &paintInvalidationRect);
    {
        TransformRecorder recorder(*context, target, animatedLocalTransform);

        // clipPath can also be clipped by another clipPath.
        SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObject(&m_clip);
        LayoutSVGResourceClipper* clipPathClipper = resources ? resources->clipper() : 0;
        ClipperState clipPathClipperState = ClipperNotApplied;
        if (clipPathClipper && !SVGClipPainter(*clipPathClipper).applyClippingToContext(m_clip, targetBoundingBox, paintInvalidationRect, context, clipPathClipperState)) {
            // End the clip mask's compositor.
            CompositingRecorder::endCompositing(*context, target);
            return false;
        }

        drawClipMaskContent(context, target, targetBoundingBox);

        if (clipPathClipper)
            SVGClipPainter(*clipPathClipper).postApplyStatefulResource(m_clip, context, clipPathClipperState);
    }

    // Masked content layer start.
    CompositingRecorder::beginCompositing(*context, target, SkXfermode::kSrcIn_Mode, 1, &paintInvalidationRect);

    return true;
}
Пример #20
0
void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(
    const LayoutObject& object,
    PaintPropertyTreeBuilderContext& context) {
  // Avoid adding an ObjectPaintProperties for non-boxes to save memory, since
  // we don't need them at the moment.
  if (!object.isBox() && !object.hasLayer())
    return;

  std::unique_ptr<ObjectPaintProperties::PropertyTreeStateWithOffset>
      borderBoxContext =
          wrapUnique(new ObjectPaintProperties::PropertyTreeStateWithOffset(
              context.current.paintOffset,
              PropertyTreeState(context.current.transform, context.current.clip,
                                context.currentEffect,
                                context.current.scroll)));
  object.getMutableForPainting()
      .ensurePaintProperties()
      .setLocalBorderBoxProperties(std::move(borderBoxContext));
}
Пример #21
0
void HTMLElement::setInnerText(const String& text, ExceptionState& exceptionState)
{
    if (ieForbidsInsertHTML()) {
        exceptionState.throwDOMException(NoModificationAllowedError, "The '" + localName() + "' element does not support text insertion.");
        return;
    }
    if (shouldProhibitSetInnerOuterText(*this)) {
        exceptionState.throwDOMException(NoModificationAllowedError, "The '" + localName() + "' element does not support text insertion.");
        return;
    }

    // FIXME: This doesn't take whitespace collapsing into account at all.

    if (!text.contains('\n') && !text.contains('\r')) {
        if (text.isEmpty()) {
            removeChildren();
            return;
        }
        replaceChildrenWithText(this, text, exceptionState);
        return;
    }

    // FIXME: Do we need to be able to detect preserveNewline style even when there's no renderer?
    // FIXME: Can the renderer be out of date here? Do we need to call updateStyleIfNeeded?
    // For example, for the contents of textarea elements that are display:none?
    LayoutObject* r = layoutObject();
    if (r && r->style()->preserveNewline()) {
        if (!text.contains('\r')) {
            replaceChildrenWithText(this, text, exceptionState);
            return;
        }
        String textWithConsistentLineBreaks = text;
        textWithConsistentLineBreaks.replace("\r\n", "\n");
        textWithConsistentLineBreaks.replace('\r', '\n');
        replaceChildrenWithText(this, textWithConsistentLineBreaks, exceptionState);
        return;
    }

    // Add text nodes and <br> elements.
    RefPtrWillBeRawPtr<DocumentFragment> fragment = textToFragment(text, exceptionState);
    if (!exceptionState.hadException())
        replaceChildrenWithFragment(this, fragment.release(), exceptionState);
}
Пример #22
0
const LayoutObject* SVGLayoutSupport::pushMappingToContainer(const LayoutObject* object, const LayoutBoxModelObject* ancestorToStopAt, LayoutGeometryMap& geometryMap)
{
    ASSERT_UNUSED(ancestorToStopAt, ancestorToStopAt != object);

    LayoutObject* parent = object->parent();

    // At the SVG/HTML boundary (aka LayoutSVGRoot), we apply the localToBorderBoxTransform
    // to map an element from SVG viewport coordinates to CSS box coordinates.
    // LayoutSVGRoot's mapLocalToContainer method expects CSS box coordinates.
    if (parent->isSVGRoot()) {
        TransformationMatrix matrix(object->localToParentTransform());
        matrix.multiply(toLayoutSVGRoot(parent)->localToBorderBoxTransform());
        geometryMap.push(object, matrix);
    } else {
        geometryMap.push(object, object->localToParentTransform());
    }

    return parent;
}
TEST_F(ScrollingCoordinatorTest, iframeScrolling)
{
    registerMockedHttpURLLoad("iframe-scrolling.html");
    registerMockedHttpURLLoad("iframe-scrolling-inner.html");
    navigateTo(m_baseURL + "iframe-scrolling.html");
    forceFullCompositingUpdate();

    // Verify the properties of the accelerated scrolling element starting from the LayoutObject
    // all the way to the WebLayer.
    Element* scrollableFrame = frame()->document()->getElementById("scrollable");
    ASSERT_TRUE(scrollableFrame);

    LayoutObject* layoutObject = scrollableFrame->layoutObject();
    ASSERT_TRUE(layoutObject);
    ASSERT_TRUE(layoutObject->isLayoutPart());

    LayoutPart* layoutPart = toLayoutPart(layoutObject);
    ASSERT_TRUE(layoutPart);
    ASSERT_TRUE(layoutPart->widget());
    ASSERT_TRUE(layoutPart->widget()->isFrameView());

    FrameView* innerFrameView = toFrameView(layoutPart->widget());
    LayoutView* innerLayoutView = innerFrameView->layoutView();
    ASSERT_TRUE(innerLayoutView);

    PaintLayerCompositor* innerCompositor = innerLayoutView->compositor();
    ASSERT_TRUE(innerCompositor->inCompositingMode());
    ASSERT_TRUE(innerCompositor->scrollLayer());

    GraphicsLayer* scrollLayer = innerCompositor->scrollLayer();
    ASSERT_EQ(innerFrameView, scrollLayer->scrollableArea());

    WebLayer* webScrollLayer = scrollLayer->platformLayer();
    ASSERT_TRUE(webScrollLayer->scrollable());

#if OS(ANDROID)
    // Now verify we've attached impl-side scrollbars onto the scrollbar layers
    ASSERT_TRUE(innerCompositor->layerForHorizontalScrollbar());
    ASSERT_TRUE(innerCompositor->layerForHorizontalScrollbar()->hasContentsLayer());
    ASSERT_TRUE(innerCompositor->layerForVerticalScrollbar());
    ASSERT_TRUE(innerCompositor->layerForVerticalScrollbar()->hasContentsLayer());
#endif
}
Пример #24
0
bool ThemePainterDefault::paintMenuListButton(const LayoutObject& o,
                                              const PaintInfo& i,
                                              const IntRect& rect) {
  if (!o.isBox())
    return false;

  WebThemeEngine::ExtraParams extraParams;
  extraParams.menuList.hasBorder = false;
  extraParams.menuList.hasBorderRadius = o.styleRef().hasBorderRadius();
  extraParams.menuList.backgroundColor = Color::transparent;
  extraParams.menuList.fillContentArea = false;
  setupMenuListArrow(toLayoutBox(o), rect, extraParams);

  WebCanvas* canvas = i.context.canvas();
  Platform::current()->themeEngine()->paint(
      canvas, WebThemeEngine::PartMenuList, getWebThemeState(o), WebRect(rect),
      &extraParams);
  return false;
}
static void updateOutOfFlowContext(const LayoutObject& object, bool createdNewTransform, PaintPropertyTreeBuilderContext& context)
{
    // At the html->svg boundary (see: createPaintOffsetTranslationIfNeeded) the currentTransform is
    // up-to-date for all children of the svg root element. Additionally, inside SVG, all positioning
    // uses transforms. Therefore, we only need to check createdNewTransform and isSVGRoot() to
    // ensure out-of-flow and fixed positioning is correct at the svg->html boundary.

    if (object.isPositioned() || createdNewTransform || object.isSVGRoot()) {
        context.transformForOutOfFlowPositioned = context.currentTransform;
        context.paintOffsetForOutOfFlowPositioned = context.paintOffset;
        context.clipForOutOfFlowPositioned = context.currentClip;
    }

    if (createdNewTransform || object.isSVGRoot()) {
        context.transformForFixedPositioned = context.currentTransform;
        context.paintOffsetForFixedPositioned = context.paintOffset;
        context.clipForFixedPositioned = context.currentClip;
    }
}
Пример #26
0
bool LayoutTheme::isHovered(const LayoutObject& o)
{
    Node* node = o.node();
    if (!node)
        return false;
    if (!node->isElementNode() || !toElement(node)->isSpinButtonElement())
        return node->hovered();
    SpinButtonElement* element = toSpinButtonElement(node);
    return element->hovered() && element->upDownState() != SpinButtonElement::Indeterminate;
}
int VisiblePosition::lineDirectionPointForBlockDirectionNavigation() const
{
    if (isNull())
        return 0;

    LayoutObject* layoutObject;
    LayoutRect localRect = localCaretRect(layoutObject);
    if (localRect.isEmpty() || !layoutObject)
        return 0;

    // This ignores transforms on purpose, for now. Vertical navigation is done
    // without consulting transforms, so that 'up' in transformed text is 'up'
    // relative to the text, not absolute 'up'.
    FloatPoint caretPoint = layoutObject->localToAbsolute(FloatPoint(localRect.location()));
    LayoutObject* containingBlock = layoutObject->containingBlock();
    if (!containingBlock)
        containingBlock = layoutObject; // Just use ourselves to determine the writing mode if we have no containing block.
    return containingBlock->isHorizontalWritingMode() ? caretPoint.x() : caretPoint.y();
}
Пример #28
0
void FrameSetPainter::paintChildren(const PaintInfo& paintInfo, const LayoutPoint& adjustedPaintOffset)
{
    // Paint only those children that fit in the grid.
    // Remaining frames are "hidden".
    // See also LayoutFrameSet::positionFrames.
    LayoutObject* child = m_layoutFrameSet.firstChild();
    size_t rows = m_layoutFrameSet.rows().m_sizes.size();
    size_t cols = m_layoutFrameSet.columns().m_sizes.size();
    for (size_t r = 0; r < rows; r++) {
        for (size_t c = 0; c < cols; c++) {
            // Self-painting layers are painted during the PaintLayer paint recursion, not LayoutObject.
            if (!child->isBoxModelObject() || !toLayoutBoxModelObject(child)->hasSelfPaintingLayer())
                child->paint(paintInfo, adjustedPaintOffset);
            child = child->nextSibling();
            if (!child)
                return;
        }
    }
}
Пример #29
0
LayoutUnit LayoutListBox::itemHeight() const
{
    HTMLSelectElement* select = selectElement();
    if (!select)
        return 0;
    Element* baseItem = ElementTraversal::firstChild(*select);
    if (!baseItem)
        return defaultItemHeight();
    if (isHTMLOptGroupElement(baseItem))
        baseItem = &toHTMLOptGroupElement(baseItem)->optGroupLabelElement();
    else if (!isHTMLOptionElement(baseItem))
        return defaultItemHeight();
    LayoutObject* baseItemRenderer = baseItem->layoutObject();
    if (!baseItemRenderer)
        return defaultItemHeight();
    if (!baseItemRenderer || !baseItemRenderer->isBox())
        return defaultItemHeight();
    return toLayoutBox(baseItemRenderer)->size().height();
}
static void walkTree(LayoutSVGText* start, LayoutSVGInlineText* stopAtLeaf, MeasureTextData* data)
{
    LayoutObject* child = start->firstChild();
    while (child) {
        if (child->isSVGInlineText()) {
            LayoutSVGInlineText* text = toLayoutSVGInlineText(child);
            measureTextLayoutObject(text, data, !stopAtLeaf || stopAtLeaf == text);
            if (stopAtLeaf && stopAtLeaf == text)
                return;
        } else if (child->isSVGInline()) {
            // Visit children of text content elements.
            if (LayoutObject* inlineChild = toLayoutSVGInline(child)->firstChild()) {
                child = inlineChild;
                continue;
            }
        }
        child = child->nextInPreOrderAfterChildren(start);
    }
}