Exemplo n.º 1
0
void LayoutTableRow::addChild(LayoutObject* child, LayoutObject* beforeChild)
{
    if (!child->isTableCell()) {
        LayoutObject* last = beforeChild;
        if (!last)
            last = lastCell();
        if (last && last->isAnonymous() && last->isTableCell() && !last->isBeforeOrAfterContent()) {
            LayoutTableCell* lastCell = toLayoutTableCell(last);
            if (beforeChild == lastCell)
                beforeChild = lastCell->firstChild();
            lastCell->addChild(child, beforeChild);
            return;
        }

        if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
            LayoutObject* cell = beforeChild->previousSibling();
            if (cell && cell->isTableCell() && cell->isAnonymous()) {
                cell->addChild(child);
                return;
            }
        }

        // If beforeChild is inside an anonymous cell, insert into the cell.
        if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous() && !last->parent()->isBeforeOrAfterContent()) {
            last->parent()->addChild(child, beforeChild);
            return;
        }

        LayoutTableCell* cell = LayoutTableCell::createAnonymousWithParent(this);
        addChild(cell, beforeChild);
        cell->addChild(child);
        return;
    }

    if (beforeChild && beforeChild->parent() != this)
        beforeChild = splitAnonymousBoxesAroundChild(beforeChild);

    LayoutTableCell* cell = toLayoutTableCell(child);

    ASSERT(!beforeChild || beforeChild->isTableCell());
    LayoutBox::addChild(cell, beforeChild);

    // Generated content can result in us having a null section so make sure to null check our parent.
    if (parent())
        section()->addCell(cell, this);

    if (beforeChild || nextRow())
        section()->setNeedsCellRecalc();
}
PassRefPtr<StringImpl> LayoutCounter::originalText() const
{
    if (!m_counterNode) {
        LayoutObject* beforeAfterContainer = parent();
        while (true) {
            if (!beforeAfterContainer)
                return nullptr;
            if (!beforeAfterContainer->isAnonymous() && !beforeAfterContainer->isPseudoElement())
                return nullptr; // LayoutCounters are restricted to before and after pseudo elements
            PseudoId containerStyle = beforeAfterContainer->style()->styleType();
            if ((containerStyle == BEFORE) || (containerStyle == AFTER))
                break;
            beforeAfterContainer = beforeAfterContainer->parent();
        }
        makeCounterNode(*beforeAfterContainer, m_counter.identifier(), true)->addLayoutObject(const_cast<LayoutCounter*>(this));
        ASSERT(m_counterNode);
    }
    CounterNode* child = m_counterNode;
    int value = child->actsAsReset() ? child->value() : child->countInParent();

    String text = ListMarkerText::text(m_counter.listStyle(), value);

    if (!m_counter.separator().isNull()) {
        if (!child->actsAsReset())
            child = child->parent();
        while (CounterNode* parent = child->parent()) {
            text = ListMarkerText::text(m_counter.listStyle(), child->countInParent())
                + m_counter.separator() + text;
            child = parent;
        }
    }

    return text.impl();
}
TracedLayoutObject::TracedLayoutObject(const LayoutObject& object)
    : m_address((unsigned long) &object)
    , m_isAnonymous(object.isAnonymous())
    , m_isPositioned(object.isOutOfFlowPositioned())
    , m_isRelPositioned(object.isRelPositioned())
    , m_isStickyPositioned(object.isStickyPositioned())
    , m_isFloating(object.isFloating())
    , m_selfNeeds(object.selfNeedsLayout())
    , m_positionedMovement(object.needsPositionedMovementLayout())
    , m_childNeeds(object.normalChildNeedsLayout())
    , m_posChildNeeds(object.posChildNeedsLayout())
    , m_isTableCell(object.isTableCell())
    , m_name(String(object.name()).isolatedCopy())
    , m_absRect(object.absoluteBoundingBoxRect())
{
    if (Node* node = object.node()) {
        m_tag = String(node->nodeName()).isolatedCopy();
        if (node->isElementNode()) {
            Element& element = toElement(*node);
            if (element.hasID())
                m_id = String(element.getIdAttribute()).isolatedCopy();
            if (element.hasClass()) {
                for (size_t i = 0; i < element.classNames().size(); ++i) {
                    m_classNames.append(
                        String(element.classNames()[i]).isolatedCopy());
                }
            }
        }
    }

    // FIXME: When the fixmes in LayoutTreeAsText::writeLayoutObject() are
    // fixed, deduplicate it with this.
    if (object.isText()) {
        m_rect = LayoutRect(toLayoutText(object).linesBoundingBox());
    } else if (object.isLayoutInline()) {
        m_rect = LayoutRect(toLayoutInline(object).linesBoundingBox());
    } else if (object.isBox()) {
        m_rect = toLayoutBox(&object)->frameRect();
    }

    if (m_isTableCell) {
        const LayoutTableCell& c = toLayoutTableCell(object);
        if (c.row() && c.row()->rowIndexWasSet() && c.hasCol()
            && (!c.row()->section() || !c.row()->section()->needsCellRecalc())) {
            m_row = c.rowIndex();
            m_col = c.col();
            m_rowSpan = c.rowSpan();
            m_colSpan = c.colSpan();
        }
    }

    for (LayoutObject* child = object.slowFirstChild(); child; child = child->nextSibling()) {
        m_children.append(adoptRef(new TracedLayoutObject(*child)));
    }
}
Exemplo n.º 4
0
static inline bool hasGeneratedAnonymousTableCells(const LayoutObject& parent)
{
    // We're checking whether the table part has generated anonymous table
    // part wrappers to hold its contents, so inspecting its first child will suffice.
    LayoutObject* child = parent.slowFirstChild();
    if (!child || !child->isAnonymous())
        return false;
    if (child->isTableCell()) {
        LayoutObject* firstChild = child->slowFirstChild();
        // Ignore the anonymous table cell if it is wrapping a table cell element (e.g. because of <td style="display:block;">).
        return !firstChild || !firstChild->node() || !isHTMLTableCellElement(firstChild->node());
    }
    if (child->isTableSection() || child->isTableRow())
        return hasGeneratedAnonymousTableCells(*child);
    return false;
}
Exemplo n.º 5
0
// With PseudoElements the DOM tree and Layout tree can differ. When you attach
// a, first-letter for example, into the DOM we walk down the Layout
// tree to find the correct insertion point for the LayoutObject. But, this
// means if we ask for the parentOrShadowHost Node from the first-letter
// pseudo element we will get some arbitrary ancestor of the LayoutObject.
//
// For hit testing, we need the parent Node of the LayoutObject for the
// first-letter pseudo element. So, by walking up the Layout tree we know
// we will get the parent and not some other ancestor.
Node* PseudoElement::findAssociatedNode() const
{
    // The ::backdrop element is parented to the LayoutView, not to the node
    // that it's associated with. We need to make sure ::backdrop sends the
    // events to the parent node correctly.
    if (pseudoId() == BACKDROP)
        return parentOrShadowHostNode();

    ASSERT(layoutObject());
    ASSERT(layoutObject()->parent());

    // We can have any number of anonymous layout objects inserted between
    // us and our parent so make sure we skip over them.
    LayoutObject* ancestor = layoutObject()->parent();
    while (ancestor->isAnonymous() || (ancestor->node() && ancestor->node()->isPseudoElement())) {
        ASSERT(ancestor->parent());
        ancestor = ancestor->parent();
    }
    return ancestor->node();
}
Exemplo n.º 6
0
void LayoutTableRow::addChild(LayoutObject* child, LayoutObject* beforeChild) {
  if (!child->isTableCell()) {
    LayoutObject* last = beforeChild;
    if (!last)
      last = lastCell();
    if (last && last->isAnonymous() && last->isTableCell() &&
        !last->isBeforeOrAfterContent()) {
      LayoutTableCell* lastCell = toLayoutTableCell(last);
      if (beforeChild == lastCell)
        beforeChild = lastCell->firstChild();
      lastCell->addChild(child, beforeChild);
      return;
    }

    if (beforeChild && !beforeChild->isAnonymous() &&
        beforeChild->parent() == this) {
      LayoutObject* cell = beforeChild->previousSibling();
      if (cell && cell->isTableCell() && cell->isAnonymous()) {
        cell->addChild(child);
        return;
      }
    }

    // If beforeChild is inside an anonymous cell, insert into the cell.
    if (last && !last->isTableCell() && last->parent() &&
        last->parent()->isAnonymous() &&
        !last->parent()->isBeforeOrAfterContent()) {
      last->parent()->addChild(child, beforeChild);
      return;
    }

    LayoutTableCell* cell = LayoutTableCell::createAnonymousWithParent(this);
    addChild(cell, beforeChild);
    cell->addChild(child);
    return;
  }

  if (beforeChild && beforeChild->parent() != this)
    beforeChild = splitAnonymousBoxesAroundChild(beforeChild);

  LayoutTableCell* cell = toLayoutTableCell(child);

  ASSERT(!beforeChild || beforeChild->isTableCell());
  LayoutTableBoxComponent::addChild(cell, beforeChild);

  // Generated content can result in us having a null section so make sure to
  // null check our parent.
  if (parent()) {
    section()->addCell(cell, this);
    // When borders collapse, adding a cell can affect the the width of
    // neighboring cells.
    LayoutTable* enclosingTable = table();
    if (enclosingTable && enclosingTable->collapseBorders()) {
      if (LayoutTableCell* previousCell = cell->previousCell())
        previousCell->setNeedsLayoutAndPrefWidthsRecalc(
            LayoutInvalidationReason::TableChanged);
      if (LayoutTableCell* nextCell = cell->nextCell())
        nextCell->setNeedsLayoutAndPrefWidthsRecalc(
            LayoutInvalidationReason::TableChanged);
    }
  }

  if (beforeChild || nextRow())
    section()->setNeedsCellRecalc();
}