RenderRubyRun* RenderRubyRun::staticCreateRubyRun(const RenderObject* parentRuby) { ASSERT(parentRuby && parentRuby->isRuby()); RenderRubyRun* rr = new (parentRuby->renderArena()) RenderRubyRun(parentRuby->document() /* anonymous */); RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parentRuby->style(), INLINE_BLOCK); rr->setStyle(newStyle.release()); return rr; }
void RenderRubyAsBlock::removeChild(RenderObject* child) { // If the child's parent is *this (a ruby run or :before or :after content), // just use the normal remove method. if (child->isRubyRun() || child->isBeforeContent() || child->isAfterContent()) { RenderBlock::removeChild(child); return; } // Otherwise find the containing run and remove it from there. ASSERT(child->parent() != this); RenderRubyRun* run = findRubyRunParent(child); ASSERT(run); run->removeChild(child); }
void RenderRubyRun::addChild(RenderObject* child, RenderObject* beforeChild) { ASSERT(child); if (child->isRubyText()) { if (!beforeChild) { // RenderRuby has already ascertained that we can add the child here. ASSERT(!hasRubyText()); // prepend ruby texts as first child RenderBlockFlow::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); RenderObject* ruby = parent(); ASSERT(ruby->isRuby()); RenderBlock* 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 RenderRubyRun's methods, // in order to avoid automatic removal of the ruby run in case there is no // other child besides the old ruby text. RenderBlockFlow::addChild(child, beforeChild); RenderBlockFlow::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. RenderObject* ruby = parent(); RenderRubyRun* newRun = staticCreateRubyRun(ruby); ruby->addChild(newRun, this); newRun->addChild(child); 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) RenderRubyBase* base = rubyBaseSafe(); if (beforeChild == base) beforeChild = base->firstChild(); if (beforeChild && beforeChild->isRubyText()) beforeChild = 0; ASSERT(!beforeChild || beforeChild->isDescendantOf(base)); base->addChild(child, beforeChild); } }
RenderObject* RenderRubyRun::removeChild(RenderObject& child) { // If the child is a ruby text, then merge the ruby base with the base of // the right sibling run, if possible. if (!beingDestroyed() && !documentBeingDestroyed() && child.isRubyText()) { RenderRubyBase* base = rubyBase(); RenderObject* rightNeighbour = nextSibling(); if (base && rightNeighbour && rightNeighbour->isRubyRun()) { // Ruby run without a base can happen only at the first run. RenderRubyRun* rightRun = toRenderRubyRun(rightNeighbour); if (rightRun->hasRubyBase()) { RenderRubyBase* rightBase = rightRun->rubyBaseSafe(); // Collect all children in a single base, then swap the bases. rightBase->mergeChildrenWithBase(base); moveChildTo(rightRun, base); rightRun->moveChildTo(this, rightBase); // The now empty ruby base will be removed below. ASSERT(!rubyBase()->firstChild()); } } } RenderObject* next = RenderBlockFlow::removeChild(child); if (!beingDestroyed() && !documentBeingDestroyed()) { // Check if our base (if any) is now empty. If so, destroy it. RenderBlock* base = rubyBase(); if (base && !base->firstChild()) { next = RenderBlockFlow::removeChild(*base); base->deleteLines(); base->destroy(); } // If any of the above leaves the run empty, destroy it as well. if (isEmpty()) { parent()->removeChild(*this); deleteLines(); destroy(); next = nullptr; } } return next; }
void RenderRubyRun::removeChild(RenderObject* child) { // If the child is a ruby text, then merge the ruby base with the base of // the right sibling run, if possible. if (!m_beingDestroyed && !documentBeingDestroyed() && child->isRubyText()) { RenderRubyBase* base = rubyBase(); RenderObject* rightNeighbour = nextSibling(); if (base && rightNeighbour && rightNeighbour->isRubyRun()) { // Ruby run without a base can happen only at the first run. RenderRubyRun* rightRun = static_cast<RenderRubyRun*>(rightNeighbour); if (rightRun->hasRubyBase()) { RenderRubyBase* rightBase = rightRun->rubyBaseSafe(); // Collect all children in a single base, then swap the bases. rightBase->moveChildren(base); moveChildTo(rightRun, base); rightRun->moveChildTo(this, rightBase); // The now empty ruby base will be removed below. } } } RenderBlock::removeChild(child); if (!m_beingDestroyed && !documentBeingDestroyed()) { // Check if our base (if any) is now empty. If so, destroy it. RenderBlock* base = rubyBase(); if (base && !base->firstChild()) { RenderBlock::removeChild(base); base->deleteLineBoxTree(); base->destroy(); } // If any of the above leaves the run empty, destroy it as well. if (isEmpty()) { parent()->removeChild(this); deleteLineBoxTree(); destroy(); } } }
void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild) { // Insert :before and :after content outside of ruby runs. if (child->isBeforeContent() || child->isAfterContent()) { RenderInline::addChild(child, beforeChild); return; } // If the child is a ruby run, just add it normally. if (child->isRubyRun()) { RenderInline::addChild(child, beforeChild); return; } if (beforeChild && !isAfterContent(beforeChild)) { // insert child into run ASSERT(!beforeChild->isRubyRun()); RenderObject* run = beforeChild; while (run && !run->isRubyRun()) run = run->parent(); if (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 RenderRubyRun object will handle the details) RenderRubyRun* lastRun = lastRubyRun(this); if (!lastRun || lastRun->hasRubyText()) { lastRun = RenderRubyRun::staticCreateRubyRun(this); RenderInline::addChild(lastRun); } lastRun->addChild(child); }
void RenderRubyAsBlock::removeChild(RenderObject* child) { // If the child's parent is *this (must be a ruby run or generated content or anonymous block), // just use the normal remove method. if (child->parent() == this) { ASSERT(child->isRubyRun() || child->isBeforeContent() || child->isAfterContent() || isAnonymousRubyInlineBlock(child)); RenderBlock::removeChild(child); return; } // If the child's parent is an anoymous block (must be generated :before/:after content) // just use the block's remove method. if (isAnonymousRubyInlineBlock(child->parent())) { ASSERT(child->isBeforeContent() || child->isAfterContent()); child->parent()->removeChild(child); removeChild(child->parent()); return; } // Otherwise find the containing run and remove it from there. RenderRubyRun* run = findRubyRunParent(child); ASSERT(run); run->removeChild(child); }
void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild) { // Insert :before and :after content before/after the RenderRubyRun(s) if (child->isBeforeContent()) { if (child->isInline()) { // Add generated inline content normally RenderBlock::addChild(child, firstChild()); } else { // Wrap non-inline content with an anonymous inline-block. RenderBlock* beforeBlock = rubyBeforeBlock(this); if (!beforeBlock) { beforeBlock = createAnonymousRubyInlineBlock(this); RenderBlock::addChild(beforeBlock, firstChild()); } beforeBlock->addChild(child); } return; } if (child->isAfterContent()) { if (child->isInline()) { // Add generated inline content normally RenderBlock::addChild(child); } else { // Wrap non-inline content with an anonymous inline-block. RenderBlock* afterBlock = rubyAfterBlock(this); if (!afterBlock) { afterBlock = createAnonymousRubyInlineBlock(this); RenderBlock::addChild(afterBlock); } afterBlock->addChild(child); } return; } // If the child is a ruby run, just add it normally. if (child->isRubyRun()) { RenderBlock::addChild(child, beforeChild); return; } if (beforeChild && !isAfterContent(beforeChild)) { // insert child into run ASSERT(!beforeChild->isRubyRun()); RenderObject* run = beforeChild; while (run && !run->isRubyRun()) run = run->parent(); if (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 RenderRubyRun object will handle the details) RenderRubyRun* lastRun = lastRubyRun(this); if (!lastRun || lastRun->hasRubyText()) { lastRun = RenderRubyRun::staticCreateRubyRun(this); RenderBlock::addChild(lastRun, beforeChild); } lastRun->addChild(child); }