15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2009 Google Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderRuby.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderRubyRun.h"
3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/style/RenderStyle.h"
3702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch#include "wtf/RefPtr.h"
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//=== generic helper functions to avoid excessive code duplication ===
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool isAnonymousRubyInlineBlock(const RenderObject* object)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!object
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || !object->parent()->isRuby()
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || object->isRubyRun()
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || (object->isInline() && (object->isBeforeContent() || object->isAfterContent()))
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || (object->isAnonymous() && object->isRenderBlock() && object->style()->display() == INLINE_BLOCK));
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return object
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        && object->parent()->isRuby()
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        && object->isRenderBlock()
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        && !object->isRubyRun();
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool isRubyBeforeBlock(const RenderObject* object)
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return isAnonymousRubyInlineBlock(object)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        && !object->previousSibling()
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        && object->firstChild()
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        && object->firstChild()->style()->styleType() == BEFORE;
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool isRubyAfterBlock(const RenderObject* object)
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return isAnonymousRubyInlineBlock(object)
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        && !object->nextSibling()
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        && object->firstChild()
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        && object->firstChild()->style()->styleType() == AFTER;
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline RenderBlock* rubyBeforeBlock(const RenderObject* ruby)
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* child = ruby->firstChild();
76926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return isRubyBeforeBlock(child) ? toRenderBlock(child) : 0;
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline RenderBlock* rubyAfterBlock(const RenderObject* ruby)
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* child = ruby->lastChild();
82926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return isRubyAfterBlock(child) ? toRenderBlock(child) : 0;
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static RenderBlock* createAnonymousRubyInlineBlock(RenderObject* ruby)
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(ruby->style(), INLINE_BLOCK);
88926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    RenderBlock* newBlock = RenderBlock::createAnonymous(ruby->document());
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newBlock->setStyle(newStyle.release());
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newBlock;
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static RenderRubyRun* lastRubyRun(const RenderObject* ruby)
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* child = ruby->lastChild();
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (child && !child->isRubyRun())
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        child = child->previousSibling();
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!child || child->isRubyRun() || child->isBeforeContent() || child == rubyBeforeBlock(ruby));
99926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return child && child->isRubyRun() ? toRenderRubyRun(child) : 0;
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline RenderRubyRun* findRubyRunParent(RenderObject* child)
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (child && !child->isRubyRun())
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        child = child->parent();
106926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return toRenderRubyRun(child);
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//=== ruby as inline object ===
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
111926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)RenderRubyAsInline::RenderRubyAsInline(Element* element)
112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    : RenderInline(element)
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderRubyAsInline::~RenderRubyAsInline()
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderRubyAsInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderInline::styleDidChange(diff, oldStyle);
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    propagateStyleToAnonymousChildren();
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild)
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Insert :before and :after content before/after the RenderRubyRun(s)
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (child->isBeforeContent()) {
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (child->isInline()) {
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Add generated inline content normally
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderInline::addChild(child, firstChild());
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Wrap non-inline content with an anonymous inline-block.
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderBlock* beforeBlock = rubyBeforeBlock(this);
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!beforeBlock) {
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                beforeBlock = createAnonymousRubyInlineBlock(this);
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                RenderInline::addChild(beforeBlock, firstChild());
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            beforeBlock->addChild(child);
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (child->isAfterContent()) {
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (child->isInline()) {
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Add generated inline content normally
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderInline::addChild(child);
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Wrap non-inline content with an anonymous inline-block.
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderBlock* afterBlock = rubyAfterBlock(this);
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!afterBlock) {
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                afterBlock = createAnonymousRubyInlineBlock(this);
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                RenderInline::addChild(afterBlock);
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            afterBlock->addChild(child);
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the child is a ruby run, just add it normally.
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (child->isRubyRun()) {
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderInline::addChild(child, beforeChild);
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (beforeChild && !isAfterContent(beforeChild)) {
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // insert child into run
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(!beforeChild->isRubyRun());
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderObject* run = beforeChild;
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (run && !run->isRubyRun())
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            run = run->parent();
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (run) {
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            run->addChild(child, beforeChild);
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT_NOT_REACHED(); // beforeChild should always have a run as parent!
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Emergency fallback: fall through and just append.
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the new child would be appended, try to add the child to the previous run
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // if possible, or create a new run otherwise.
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // (The RenderRubyRun object will handle the details)
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderRubyRun* lastRun = lastRubyRun(this);
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!lastRun || lastRun->hasRubyText()) {
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        lastRun = RenderRubyRun::staticCreateRubyRun(this);
186926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        RenderInline::addChild(lastRun, beforeChild);
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    lastRun->addChild(child);
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderRubyAsInline::removeChild(RenderObject* child)
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the child's parent is *this (must be a ruby run or generated content or anonymous block),
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // just use the normal remove method.
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (child->parent() == this) {
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(child->isRubyRun() || child->isBeforeContent() || child->isAfterContent() || isAnonymousRubyInlineBlock(child));
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderInline::removeChild(child);
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the child's parent is an anoymous block (must be generated :before/:after content)
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // just use the block's remove method.
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isAnonymousRubyInlineBlock(child->parent())) {
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(child->isBeforeContent() || child->isAfterContent());
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        child->parent()->removeChild(child);
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeChild(child->parent());
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Otherwise find the containing run and remove it from there.
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderRubyRun* run = findRubyRunParent(child);
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(run);
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    run->removeChild(child);
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//=== ruby as block object ===
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
217926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)RenderRubyAsBlock::RenderRubyAsBlock(Element* element)
218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    : RenderBlock(element)
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderRubyAsBlock::~RenderRubyAsBlock()
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderRubyAsBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderBlock::styleDidChange(diff, oldStyle);
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    propagateStyleToAnonymousChildren();
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild)
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Insert :before and :after content before/after the RenderRubyRun(s)
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (child->isBeforeContent()) {
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (child->isInline()) {
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Add generated inline content normally
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderBlock::addChild(child, firstChild());
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Wrap non-inline content with an anonymous inline-block.
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderBlock* beforeBlock = rubyBeforeBlock(this);
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!beforeBlock) {
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                beforeBlock = createAnonymousRubyInlineBlock(this);
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                RenderBlock::addChild(beforeBlock, firstChild());
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            beforeBlock->addChild(child);
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (child->isAfterContent()) {
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (child->isInline()) {
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Add generated inline content normally
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderBlock::addChild(child);
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Wrap non-inline content with an anonymous inline-block.
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderBlock* afterBlock = rubyAfterBlock(this);
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!afterBlock) {
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                afterBlock = createAnonymousRubyInlineBlock(this);
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                RenderBlock::addChild(afterBlock);
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            afterBlock->addChild(child);
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the child is a ruby run, just add it normally.
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (child->isRubyRun()) {
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderBlock::addChild(child, beforeChild);
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (beforeChild && !isAfterContent(beforeChild)) {
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // insert child into run
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(!beforeChild->isRubyRun());
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderObject* run = beforeChild;
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (run && !run->isRubyRun())
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            run = run->parent();
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (run) {
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            run->addChild(child, beforeChild);
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT_NOT_REACHED(); // beforeChild should always have a run as parent!
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Emergency fallback: fall through and just append.
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the new child would be appended, try to add the child to the previous run
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // if possible, or create a new run otherwise.
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // (The RenderRubyRun object will handle the details)
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderRubyRun* lastRun = lastRubyRun(this);
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!lastRun || lastRun->hasRubyText()) {
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        lastRun = RenderRubyRun::staticCreateRubyRun(this);
292926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        RenderBlock::addChild(lastRun, beforeChild);
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    lastRun->addChild(child);
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderRubyAsBlock::removeChild(RenderObject* child)
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the child's parent is *this (must be a ruby run or generated content or anonymous block),
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // just use the normal remove method.
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (child->parent() == this) {
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(child->isRubyRun() || child->isBeforeContent() || child->isAfterContent() || isAnonymousRubyInlineBlock(child));
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderBlock::removeChild(child);
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the child's parent is an anoymous block (must be generated :before/:after content)
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // just use the block's remove method.
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isAnonymousRubyInlineBlock(child->parent())) {
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(child->isBeforeContent() || child->isAfterContent());
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        child->parent()->removeChild(child);
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeChild(child->parent());
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Otherwise find the containing run and remove it from there.
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderRubyRun* run = findRubyRunParent(child);
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(run);
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    run->removeChild(child);
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
322