• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 
33 #include "core/rendering/RenderRubyBase.h"
34 #include "core/rendering/RenderRubyRun.h"
35 
36 using namespace std;
37 
38 namespace WebCore {
39 
RenderRubyBase()40 RenderRubyBase::RenderRubyBase()
41     : RenderBlockFlow(0)
42 {
43     setInline(false);
44 }
45 
~RenderRubyBase()46 RenderRubyBase::~RenderRubyBase()
47 {
48 }
49 
createAnonymous(Document * document)50 RenderRubyBase* RenderRubyBase::createAnonymous(Document* document)
51 {
52     RenderRubyBase* renderer = new RenderRubyBase();
53     renderer->setDocumentForAnonymous(document);
54     return renderer;
55 }
56 
isChildAllowed(RenderObject * child,RenderStyle *) const57 bool RenderRubyBase::isChildAllowed(RenderObject* child, RenderStyle*) const
58 {
59     return child->isInline();
60 }
61 
moveChildren(RenderRubyBase * toBase,RenderObject * beforeChild)62 void RenderRubyBase::moveChildren(RenderRubyBase* toBase, RenderObject* beforeChild)
63 {
64     // This function removes all children that are before (!) beforeChild
65     // and appends them to toBase.
66     ASSERT_ARG(toBase, toBase);
67 
68     if (beforeChild && beforeChild->parent() != this)
69         beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
70 
71     if (childrenInline())
72         moveInlineChildren(toBase, beforeChild);
73     else
74         moveBlockChildren(toBase, beforeChild);
75 
76     setNeedsLayoutAndPrefWidthsRecalc();
77     toBase->setNeedsLayoutAndPrefWidthsRecalc();
78 }
79 
moveInlineChildren(RenderRubyBase * toBase,RenderObject * beforeChild)80 void RenderRubyBase::moveInlineChildren(RenderRubyBase* toBase, RenderObject* beforeChild)
81 {
82     ASSERT(childrenInline());
83     ASSERT_ARG(toBase, toBase);
84 
85     if (!firstChild())
86         return;
87 
88     RenderBlock* toBlock;
89     if (toBase->childrenInline()) {
90         // The standard and easy case: move the children into the target base
91         toBlock = toBase;
92     } else {
93         // We need to wrap the inline objects into an anonymous block.
94         // If toBase has a suitable block, we re-use it, otherwise create a new one.
95         RenderObject* lastChild = toBase->lastChild();
96         if (lastChild && lastChild->isAnonymousBlock() && lastChild->childrenInline())
97             toBlock = toRenderBlock(lastChild);
98         else {
99             toBlock = toBase->createAnonymousBlock();
100             toBase->children()->appendChildNode(toBase, toBlock);
101         }
102     }
103     // Move our inline children into the target block we determined above.
104     moveChildrenTo(toBlock, firstChild(), beforeChild);
105 }
106 
moveBlockChildren(RenderRubyBase * toBase,RenderObject * beforeChild)107 void RenderRubyBase::moveBlockChildren(RenderRubyBase* toBase, RenderObject* beforeChild)
108 {
109     ASSERT(!childrenInline());
110     ASSERT_ARG(toBase, toBase);
111 
112     if (!firstChild())
113         return;
114 
115     if (toBase->childrenInline())
116         toBase->makeChildrenNonInline();
117 
118     // If an anonymous block would be put next to another such block, then merge those.
119     RenderObject* firstChildHere = firstChild();
120     RenderObject* lastChildThere = toBase->lastChild();
121     if (firstChildHere->isAnonymousBlock() && firstChildHere->childrenInline()
122             && lastChildThere && lastChildThere->isAnonymousBlock() && lastChildThere->childrenInline()) {
123         RenderBlock* anonBlockHere = toRenderBlock(firstChildHere);
124         RenderBlock* anonBlockThere = toRenderBlock(lastChildThere);
125         anonBlockHere->moveAllChildrenTo(anonBlockThere, anonBlockThere->children());
126         anonBlockHere->deleteLineBoxTree();
127         anonBlockHere->destroy();
128     }
129     // Move all remaining children normally.
130     moveChildrenTo(toBase, firstChild(), beforeChild);
131 }
132 
rubyRun() const133 RenderRubyRun* RenderRubyBase::rubyRun() const
134 {
135     ASSERT(parent());
136     ASSERT(parent()->isRubyRun());
137 
138     return toRenderRubyRun(parent());
139 }
140 
textAlignmentForLine(bool) const141 ETextAlign RenderRubyBase::textAlignmentForLine(bool /* endsWithSoftBreak */) const
142 {
143     return JUSTIFY;
144 }
145 
adjustInlineDirectionLineBounds(int expansionOpportunityCount,float & logicalLeft,float & logicalWidth) const146 void RenderRubyBase::adjustInlineDirectionLineBounds(int expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const
147 {
148     int maxPreferredLogicalWidth = this->maxPreferredLogicalWidth();
149     if (maxPreferredLogicalWidth >= logicalWidth)
150         return;
151 
152     // Inset the ruby base by half the inter-ideograph expansion amount.
153     float inset = (logicalWidth - maxPreferredLogicalWidth) / (expansionOpportunityCount + 1);
154 
155     logicalLeft += inset / 2;
156     logicalWidth -= inset;
157 }
158 
159 } // namespace WebCore
160