void LayoutRubyRun::addChild(LayoutObject* child, LayoutObject* beforeChild)
{
    ASSERT(child);

    if (child->isRubyText()) {
        if (!beforeChild) {
            // LayoutRuby has already ascertained that we can add the child here.
            ASSERT(!hasRubyText());
            // prepend ruby texts as first child
            LayoutBlockFlow::addChild(child, firstChild());
        }  else if (beforeChild->isRubyText()) {
            // New text is inserted just before another.
            // In this case the new text takes the place of the old one, and
            // the old text goes into a new run that is inserted as next sibling.
            ASSERT(beforeChild->parent() == this);
            LayoutObject* ruby = parent();
            ASSERT(ruby->isRuby());
            LayoutBlock* newRun = staticCreateRubyRun(ruby);
            ruby->addChild(newRun, nextSibling());
            // Add the new ruby text and move the old one to the new run
            // Note: Doing it in this order and not using LayoutRubyRun's methods,
            // in order to avoid automatic removal of the ruby run in case there is no
            // other child besides the old ruby text.
            LayoutBlockFlow::addChild(child, beforeChild);
            LayoutBlockFlow::removeChild(beforeChild);
            newRun->addChild(beforeChild);
        } else if (hasRubyBase()) {
            // Insertion before a ruby base object.
            // In this case we need insert a new run before the current one and split the base.
            LayoutObject* ruby = parent();
            LayoutRubyRun* newRun = staticCreateRubyRun(ruby);
            ruby->addChild(newRun, this);
            newRun->addChild(child);

            // Make sure we don't leave anything in the percentage descendant
            // map before moving the children to the new base.
            if (hasPercentHeightDescendants())
                clearPercentHeightDescendants();
            rubyBaseSafe()->moveChildren(newRun->rubyBaseSafe(), beforeChild);
        }
    } else {
        // child is not a text -> insert it into the base
        // (append it instead if beforeChild is the ruby text)
        LayoutRubyBase* base = rubyBaseSafe();
        if (beforeChild == base)
            beforeChild = base->firstChild();
        if (beforeChild && beforeChild->isRubyText())
            beforeChild = 0;
        ASSERT(!beforeChild || beforeChild->isDescendantOf(base));
        base->addChild(child, beforeChild);
    }
}
void PseudoElement::attach(const AttachContext& context)
{
    ASSERT(!layoutObject());

    Element::attach(context);

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

    ComputedStyle& style = renderer->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 (renderer->isChildAllowed(child, style)) {
            renderer->addChild(child);
            if (child->isQuote())
                toLayoutQuote(child)->attachQuote();
        } else
            child->destroy();
    }
}
bool LayoutListItem::updateMarkerLocation()
{
    ASSERT(m_marker);

    LayoutObject* markerParent = m_marker->parent();
    LayoutObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker);
    if (!lineBoxParent) {
        // If the marker is currently contained inside an anonymous box, then we
        // are the only item in that anonymous box (since no line box parent was
        // found). It's ok to just leave the marker where it is in this case.
        if (markerParent && markerParent->isAnonymousBlock())
            lineBoxParent = markerParent;
        else
            lineBoxParent = this;
    }

    if (markerParent != lineBoxParent) {
        m_marker->remove();
        lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent));
        m_marker->updateMarginsAndContent();
        // If markerParent is an anonymous block with no children, destroy it.
        if (markerParent && markerParent->isAnonymousBlock() && !toLayoutBlock(markerParent)->firstChild() && !toLayoutBlock(markerParent)->continuation())
            markerParent->destroy();
        return true;
    }

    return false;
}
void LayoutRubyAsInline::addChild(LayoutObject* child, LayoutObject* beforeChild)
{
    // If the child is a ruby run, just add it normally.
    if (child->isRubyRun()) {
        LayoutInline::addChild(child, beforeChild);
        return;
    }

    if (beforeChild) {
        // insert child into run
        LayoutObject* run = beforeChild;
        while (run && !run->isRubyRun())
            run = run->parent();
        if (run) {
            if (beforeChild == run)
                beforeChild = toLayoutRubyRun(beforeChild)->firstChild();
            ASSERT(!beforeChild || beforeChild->isDescendantOf(run));
            run->addChild(child, beforeChild);
            return;
        }
        ASSERT_NOT_REACHED(); // beforeChild should always have a run as parent!
        // Emergency fallback: fall through and just append.
    }

    // If the new child would be appended, try to add the child to the previous run
    // if possible, or create a new run otherwise.
    // (The LayoutRubyRun object will handle the details)
    LayoutRubyRun* lastRun = lastRubyRun(this);
    if (!lastRun || lastRun->hasRubyText()) {
        lastRun = LayoutRubyRun::staticCreateRubyRun(this);
        LayoutInline::addChild(lastRun, beforeChild);
    }
    lastRun->addChild(child);
}
Example #5
0
void LayoutTreeBuilderForElement::createLayoutObject()
{
    ComputedStyle& style = this->style();

    LayoutObject* newLayoutObject = m_node->createLayoutObject(style);
    if (!newLayoutObject)
        return;

    LayoutObject* parentLayoutObject = this->parentLayoutObject();

    if (!parentLayoutObject->isChildAllowed(newLayoutObject, style)) {
        newLayoutObject->destroy();
        return;
    }

    // Make sure the LayoutObject already knows it is going to be added to a LayoutFlowThread before we set the style
    // for the first time. Otherwise code using inLayoutFlowThread() in the styleWillChange and styleDidChange will fail.
    newLayoutObject->setIsInsideFlowThread(parentLayoutObject->isInsideFlowThread());

    LayoutObject* nextLayoutObject = this->nextLayoutObject();
    m_node->setLayoutObject(newLayoutObject);
    newLayoutObject->setStyle(&style); // setStyle() can depend on layoutObject() already being set.

    if (Fullscreen::isActiveFullScreenElement(*m_node)) {
        newLayoutObject = LayoutFullScreen::wrapLayoutObject(newLayoutObject, parentLayoutObject, &m_node->document());
        if (!newLayoutObject)
            return;
    }

    // Note: Adding newLayoutObject instead of layoutObject(). layoutObject() may be a child of newLayoutObject.
    parentLayoutObject->addChild(newLayoutObject, nextLayoutObject);
}
Example #6
0
void PseudoElement::attachLayoutTree(const AttachContext& context) {
  DCHECK(!layoutObject());

  Element::attachLayoutTree(context);

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

  ComputedStyle& style = layoutObject->mutableStyleRef();
  if (style.styleType() != PseudoIdBefore && style.styleType() != PseudoIdAfter)
    return;
  DCHECK(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();
    }
  }
}
Example #7
0
bool LayoutListItem::updateMarkerLocation() {
  ASSERT(m_marker);

  LayoutObject* markerParent = m_marker->parent();
  // list-style-position:inside makes the ::marker pseudo an ordinary
  // position:static element that should be attached to LayoutListItem block.
  LayoutObject* lineBoxParent =
      m_marker->isInside() ? this : getParentOfFirstLineBox(this, m_marker);
  if (!lineBoxParent) {
    // If the marker is currently contained inside an anonymous box, then we
    // are the only item in that anonymous box (since no line box parent was
    // found). It's ok to just leave the marker where it is in this case.
    if (markerParent && markerParent->isAnonymousBlock())
      lineBoxParent = markerParent;
    else
      lineBoxParent = this;
  }

  if (markerParent != lineBoxParent) {
    m_marker->remove();
    lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent));
    // TODO(rhogan): lineBoxParent and markerParent may be deleted by addChild,
    // so they are not safe to reference here.
    // Once we have a safe way of referencing them delete markerParent if it is
    // an empty anonymous block.
    m_marker->updateMarginsAndContent();
    return true;
  }

  return false;
}
Example #8
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();
}
Example #9
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();
}