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);
}
}