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/RenderRubyRun.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderRubyBase.h"
3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderRubyText.h"
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderText.h"
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
39c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
41926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)RenderRubyRun::RenderRubyRun()
428abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    : RenderBlockFlow(0)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setReplaced(true);
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setInline(true);
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderRubyRun::~RenderRubyRun()
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderRubyRun::hasRubyText() const
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The only place where a ruby text can be is in the first position
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Note: As anonymous blocks, ruby runs do not have ':before' or ':after' content themselves.
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return firstChild() && firstChild()->isRubyText();
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderRubyRun::hasRubyBase() const
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The only place where a ruby base can be is in the last position
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Note: As anonymous blocks, ruby runs do not have ':before' or ':after' content themselves.
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return lastChild() && lastChild()->isRubyBase();
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderRubyText* RenderRubyRun::rubyText() const
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* child = firstChild();
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If in future it becomes necessary to support floating or positioned ruby text,
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // layout will have to be changed to handle them properly.
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!child || !child->isRubyText() || !child->isFloatingOrOutOfFlowPositioned());
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return child && child->isRubyText() ? static_cast<RenderRubyText*>(child) : 0;
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderRubyBase* RenderRubyRun::rubyBase() const
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* child = lastChild();
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return child && child->isRubyBase() ? static_cast<RenderRubyBase*>(child) : 0;
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderRubyBase* RenderRubyRun::rubyBaseSafe()
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderRubyBase* base = rubyBase();
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!base) {
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        base = createRubyBase();
8609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        RenderBlockFlow::addChild(base);
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return base;
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderRubyRun::isChildAllowed(RenderObject* child, RenderStyle*) const
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return child->isRubyText() || child->isInline();
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderRubyRun::addChild(RenderObject* child, RenderObject* beforeChild)
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(child);
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (child->isRubyText()) {
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!beforeChild) {
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // RenderRuby has already ascertained that we can add the child here.
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ASSERT(!hasRubyText());
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // prepend ruby texts as first child
10509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            RenderBlockFlow::addChild(child, firstChild());
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }  else if (beforeChild->isRubyText()) {
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // New text is inserted just before another.
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // In this case the new text takes the place of the old one, and
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // the old text goes into a new run that is inserted as next sibling.
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ASSERT(beforeChild->parent() == this);
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderObject* ruby = parent();
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ASSERT(ruby->isRuby());
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderBlock* newRun = staticCreateRubyRun(ruby);
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ruby->addChild(newRun, nextSibling());
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Add the new ruby text and move the old one to the new run
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Note: Doing it in this order and not using RenderRubyRun's methods,
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // in order to avoid automatic removal of the ruby run in case there is no
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // other child besides the old ruby text.
11909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            RenderBlockFlow::addChild(child, beforeChild);
12009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            RenderBlockFlow::removeChild(beforeChild);
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            newRun->addChild(beforeChild);
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else if (hasRubyBase()) {
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Insertion before a ruby base object.
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // In this case we need insert a new run before the current one and split the base.
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderObject* ruby = parent();
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderRubyRun* newRun = staticCreateRubyRun(ruby);
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ruby->addChild(newRun, this);
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            newRun->addChild(child);
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            rubyBaseSafe()->moveChildren(newRun->rubyBaseSafe(), beforeChild);
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // child is not a text -> insert it into the base
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // (append it instead if beforeChild is the ruby text)
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (beforeChild && beforeChild->isRubyText())
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            beforeChild = 0;
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rubyBaseSafe()->addChild(child, beforeChild);
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderRubyRun::removeChild(RenderObject* child)
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the child is a ruby text, then merge the ruby base with the base of
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // the right sibling run, if possible.
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!beingDestroyed() && !documentBeingDestroyed() && child->isRubyText()) {
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderRubyBase* base = rubyBase();
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderObject* rightNeighbour = nextSibling();
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (base && rightNeighbour && rightNeighbour->isRubyRun()) {
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Ruby run without a base can happen only at the first run.
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderRubyRun* rightRun = toRenderRubyRun(rightNeighbour);
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (rightRun->hasRubyBase()) {
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                RenderRubyBase* rightBase = rightRun->rubyBaseSafe();
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // Collect all children in a single base, then swap the bases.
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                rightBase->moveChildren(base);
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                moveChildTo(rightRun, base);
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                rightRun->moveChildTo(this, rightBase);
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // The now empty ruby base will be removed below.
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ASSERT(!rubyBase()->firstChild());
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RenderBlockFlow::removeChild(child);
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!beingDestroyed() && !documentBeingDestroyed()) {
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Check if our base (if any) is now empty. If so, destroy it.
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderBlock* base = rubyBase();
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (base && !base->firstChild()) {
16809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            RenderBlockFlow::removeChild(base);
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            base->deleteLineBoxTree();
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            base->destroy();
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If any of the above leaves the run empty, destroy it as well.
174f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        if (!hasRubyText() && !hasRubyBase()) {
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            deleteLineBoxTree();
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            destroy();
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderRubyBase* RenderRubyRun::createRubyBase() const
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1838abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    RenderRubyBase* renderer = RenderRubyBase::createAnonymous(&document());
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK);
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newStyle->setTextAlign(CENTER); // FIXME: use WEBKIT_CENTER?
186926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    renderer->setStyle(newStyle.release());
187926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return renderer;
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderRubyRun* RenderRubyRun::staticCreateRubyRun(const RenderObject* parentRuby)
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(parentRuby && parentRuby->isRuby());
193f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    RenderRubyRun* rr = new RenderRubyRun();
1948abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    rr->setDocumentForAnonymous(&parentRuby->document());
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parentRuby->style(), INLINE_BLOCK);
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    rr->setStyle(newStyle.release());
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return rr;
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
200e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)RenderObject* RenderRubyRun::layoutSpecialExcludedChild(bool relayoutChildren, SubtreeLayoutScope& layoutScope)
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Don't bother positioning the RenderRubyRun yet.
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderRubyText* rt = rubyText();
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!rt)
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (relayoutChildren)
207e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        layoutScope.setChildNeedsLayout(rt);
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    rt->layoutIfNeeded();
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return rt;
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderRubyRun::layout()
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
21409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RenderBlockFlow::layout();
21502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderRubyText* rt = rubyText();
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!rt)
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    rt->setLogicalLeft(0);
22102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
222926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Place the RenderRubyText such that its bottom is flush with the lineTop of the first line of the RenderRubyBase.
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayoutUnit lastLineRubyTextBottom = rt->logicalHeight();
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayoutUnit firstLineRubyTextTop = 0;
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RootInlineBox* rootBox = rt->lastRootBox();
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (rootBox) {
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // In order to align, we have to ignore negative leading.
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        firstLineRubyTextTop = rt->firstRootBox()->logicalTopLayoutOverflow();
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        lastLineRubyTextBottom = rootBox->logicalBottomLayoutOverflow();
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (style()->isFlippedLinesWritingMode() == (style()->rubyPosition() == RubyPositionAfter)) {
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LayoutUnit firstLineTop = 0;
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (RenderRubyBase* rb = rubyBase()) {
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RootInlineBox* rootBox = rb->firstRootBox();
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (rootBox)
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                firstLineTop = rootBox->logicalTopLayoutOverflow();
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            firstLineTop += rb->logicalTop();
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
24002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rt->setLogicalTop(-lastLineRubyTextBottom + firstLineTop);
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LayoutUnit lastLineBottom = logicalHeight();
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (RenderRubyBase* rb = rubyBase()) {
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RootInlineBox* rootBox = rb->lastRootBox();
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (rootBox)
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                lastLineBottom = rootBox->logicalBottomLayoutOverflow();
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            lastLineBottom += rb->logicalTop();
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rt->setLogicalTop(-firstLineRubyTextTop + lastLineBottom);
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Update our overflow to account for the new RenderRubyText position.
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    computeOverflow(clientLogicalBottom());
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderRubyRun::getOverhang(bool firstLine, RenderObject* startRenderer, RenderObject* endRenderer, int& startOverhang, int& endOverhang) const
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!needsLayout());
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    startOverhang = 0;
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    endOverhang = 0;
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderRubyBase* rubyBase = this->rubyBase();
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderRubyText* rubyText = this->rubyText();
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!rubyBase || !rubyText)
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!rubyBase->firstRootBox())
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int logicalWidth = this->logicalWidth();
275197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    int logicalLeftOverhang = std::numeric_limits<int>::max();
276197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    int logicalRightOverhang = std::numeric_limits<int>::max();
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (RootInlineBox* rootInlineBox = rubyBase->firstRootBox(); rootInlineBox; rootInlineBox = rootInlineBox->nextRootBox()) {
278197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        logicalLeftOverhang = std::min<int>(logicalLeftOverhang, rootInlineBox->logicalLeft());
279197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        logicalRightOverhang = std::min<int>(logicalRightOverhang, logicalWidth - rootInlineBox->logicalRight());
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    startOverhang = style()->isLeftToRightDirection() ? logicalLeftOverhang : logicalRightOverhang;
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    endOverhang = style()->isLeftToRightDirection() ? logicalRightOverhang : logicalLeftOverhang;
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!startRenderer || !startRenderer->isText() || startRenderer->style(firstLine)->fontSize() > rubyBase->style(firstLine)->fontSize())
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        startOverhang = 0;
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!endRenderer || !endRenderer->isText() || endRenderer->style(firstLine)->fontSize() > rubyBase->style(firstLine)->fontSize())
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        endOverhang = 0;
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We overhang a ruby only if the neighboring render object is a text.
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We can overhang the ruby by no more than half the width of the neighboring text
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // and no more than half the font size.
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int halfWidthOfFontSize = rubyText->style(firstLine)->fontSize() / 2;
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (startOverhang)
296197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        startOverhang = std::min<int>(startOverhang, std::min<int>(toRenderText(startRenderer)->minLogicalWidth(), halfWidthOfFontSize));
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (endOverhang)
298197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        endOverhang = std::min<int>(endOverhang, std::min<int>(toRenderText(endRenderer)->minLogicalWidth(), halfWidthOfFontSize));
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
301c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
302