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