This source file includes following definitions.
- isAnonymousRubyInlineBlock
 
- isRubyBeforeBlock
 
- isRubyAfterBlock
 
- rubyBeforeBlock
 
- rubyAfterBlock
 
- createAnonymousRubyInlineBlock
 
- lastRubyRun
 
- findRubyRunParent
 
- styleDidChange
 
- addChild
 
- removeChild
 
- styleDidChange
 
- addChild
 
- removeChild
 
#include "config.h"
#include "core/rendering/RenderRuby.h"
#include "core/rendering/RenderRubyRun.h"
#include "core/rendering/style/RenderStyle.h"
#include "wtf/RefPtr.h"
namespace WebCore {
static inline bool isAnonymousRubyInlineBlock(const RenderObject* object)
{
    ASSERT(!object
        || !object->parent()->isRuby()
        || object->isRubyRun()
        || (object->isInline() && (object->isBeforeContent() || object->isAfterContent()))
        || (object->isAnonymous() && object->isRenderBlock() && object->style()->display() == INLINE_BLOCK));
    return object
        && object->parent()->isRuby()
        && object->isRenderBlock()
        && !object->isRubyRun();
}
static inline bool isRubyBeforeBlock(const RenderObject* object)
{
    return isAnonymousRubyInlineBlock(object)
        && !object->previousSibling()
        && object->firstChild()
        && object->firstChild()->style()->styleType() == BEFORE;
}
static inline bool isRubyAfterBlock(const RenderObject* object)
{
    return isAnonymousRubyInlineBlock(object)
        && !object->nextSibling()
        && object->firstChild()
        && object->firstChild()->style()->styleType() == AFTER;
}
static inline RenderBlock* rubyBeforeBlock(const RenderObject* ruby)
{
    RenderObject* child = ruby->firstChild();
    return isRubyBeforeBlock(child) ? toRenderBlock(child) : 0;
}
static inline RenderBlock* rubyAfterBlock(const RenderObject* ruby)
{
    RenderObject* child = ruby->lastChild();
    return isRubyAfterBlock(child) ? toRenderBlock(child) : 0;
}
static RenderBlockFlow* createAnonymousRubyInlineBlock(RenderObject* ruby)
{
    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(ruby->style(), INLINE_BLOCK);
    RenderBlockFlow* newBlock = RenderBlockFlow::createAnonymous(&ruby->document());
    newBlock->setStyle(newStyle.release());
    return newBlock;
}
static RenderRubyRun* lastRubyRun(const RenderObject* ruby)
{
    RenderObject* child = ruby->lastChild();
    if (child && !child->isRubyRun())
        child = child->previousSibling();
    ASSERT(!child || child->isRubyRun() || child->isBeforeContent() || child == rubyBeforeBlock(ruby));
    return child && child->isRubyRun() ? toRenderRubyRun(child) : 0;
}
static inline RenderRubyRun* findRubyRunParent(RenderObject* child)
{
    while (child && !child->isRubyRun())
        child = child->parent();
    return toRenderRubyRun(child);
}
RenderRubyAsInline::RenderRubyAsInline(Element* element)
    : RenderInline(element)
{
}
RenderRubyAsInline::~RenderRubyAsInline()
{
}
void RenderRubyAsInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    RenderInline::styleDidChange(diff, oldStyle);
    propagateStyleToAnonymousChildren();
}
void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild)
{
    
    if (child->isBeforeContent()) {
        if (child->isInline()) {
            
            RenderInline::addChild(child, firstChild());
        } else {
            
            RenderBlock* beforeBlock = rubyBeforeBlock(this);
            if (!beforeBlock) {
                beforeBlock = createAnonymousRubyInlineBlock(this);
                RenderInline::addChild(beforeBlock, firstChild());
            }
            beforeBlock->addChild(child);
        }
        return;
    }
    if (child->isAfterContent()) {
        if (child->isInline()) {
            
            RenderInline::addChild(child);
        } else {
            
            RenderBlock* afterBlock = rubyAfterBlock(this);
            if (!afterBlock) {
                afterBlock = createAnonymousRubyInlineBlock(this);
                RenderInline::addChild(afterBlock);
            }
            afterBlock->addChild(child);
        }
        return;
    }
    
    if (child->isRubyRun()) {
        RenderInline::addChild(child, beforeChild);
        return;
    }
    if (beforeChild && !isAfterContent(beforeChild)) {
        
        ASSERT(!beforeChild->isRubyRun());
        RenderObject* run = beforeChild;
        while (run && !run->isRubyRun())
            run = run->parent();
        if (run) {
            run->addChild(child, beforeChild);
            return;
        }
        ASSERT_NOT_REACHED(); 
        
    }
    
    
    
    RenderRubyRun* lastRun = lastRubyRun(this);
    if (!lastRun || lastRun->hasRubyText()) {
        lastRun = RenderRubyRun::staticCreateRubyRun(this);
        RenderInline::addChild(lastRun, beforeChild);
    }
    lastRun->addChild(child);
}
void RenderRubyAsInline::removeChild(RenderObject* child)
{
    
    
    if (child->parent() == this) {
        ASSERT(child->isRubyRun() || child->isBeforeContent() || child->isAfterContent() || isAnonymousRubyInlineBlock(child));
        RenderInline::removeChild(child);
        return;
    }
    
    
    if (isAnonymousRubyInlineBlock(child->parent())) {
        ASSERT(child->isBeforeContent() || child->isAfterContent());
        child->parent()->removeChild(child);
        removeChild(child->parent());
        return;
    }
    
    RenderRubyRun* run = findRubyRunParent(child);
    ASSERT(run);
    run->removeChild(child);
}
RenderRubyAsBlock::RenderRubyAsBlock(Element* element)
    : RenderBlockFlow(element)
{
}
RenderRubyAsBlock::~RenderRubyAsBlock()
{
}
void RenderRubyAsBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    RenderBlockFlow::styleDidChange(diff, oldStyle);
    propagateStyleToAnonymousChildren();
}
void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild)
{
    
    if (child->isBeforeContent()) {
        if (child->isInline()) {
            
            RenderBlockFlow::addChild(child, firstChild());
        } else {
            
            RenderBlock* beforeBlock = rubyBeforeBlock(this);
            if (!beforeBlock) {
                beforeBlock = createAnonymousRubyInlineBlock(this);
                RenderBlockFlow::addChild(beforeBlock, firstChild());
            }
            beforeBlock->addChild(child);
        }
        return;
    }
    if (child->isAfterContent()) {
        if (child->isInline()) {
            
            RenderBlockFlow::addChild(child);
        } else {
            
            RenderBlock* afterBlock = rubyAfterBlock(this);
            if (!afterBlock) {
                afterBlock = createAnonymousRubyInlineBlock(this);
                RenderBlockFlow::addChild(afterBlock);
            }
            afterBlock->addChild(child);
        }
        return;
    }
    
    if (child->isRubyRun()) {
        RenderBlockFlow::addChild(child, beforeChild);
        return;
    }
    if (beforeChild && !isAfterContent(beforeChild)) {
        
        ASSERT(!beforeChild->isRubyRun());
        RenderObject* run = beforeChild;
        while (run && !run->isRubyRun())
            run = run->parent();
        if (run) {
            run->addChild(child, beforeChild);
            return;
        }
        ASSERT_NOT_REACHED(); 
        
    }
    
    
    
    RenderRubyRun* lastRun = lastRubyRun(this);
    if (!lastRun || lastRun->hasRubyText()) {
        lastRun = RenderRubyRun::staticCreateRubyRun(this);
        RenderBlockFlow::addChild(lastRun, beforeChild);
    }
    lastRun->addChild(child);
}
void RenderRubyAsBlock::removeChild(RenderObject* child)
{
    
    
    if (child->parent() == this) {
        ASSERT(child->isRubyRun() || child->isBeforeContent() || child->isAfterContent() || isAnonymousRubyInlineBlock(child));
        RenderBlockFlow::removeChild(child);
        return;
    }
    
    
    if (isAnonymousRubyInlineBlock(child->parent())) {
        ASSERT(child->isBeforeContent() || child->isAfterContent());
        child->parent()->removeChild(child);
        removeChild(child->parent());
        return;
    }
    
    RenderRubyRun* run = findRubyRunParent(child);
    ASSERT(run);
    run->removeChild(child);
}
}