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 "RenderRubyBase.h" 34#include "RenderRubyRun.h" 35#include "RenderRubyText.h" 36 37namespace WebCore { 38 39RenderRubyBase::RenderRubyBase(Document& document, PassRef<RenderStyle> style) 40 : RenderBlockFlow(document, WTF::move(style)) 41{ 42 setInline(false); 43} 44 45RenderRubyBase::~RenderRubyBase() 46{ 47} 48 49bool RenderRubyBase::isChildAllowed(const RenderObject& child, const RenderStyle&) const 50{ 51 return child.isInline(); 52} 53 54void RenderRubyBase::moveChildren(RenderRubyBase* toBase, RenderObject* beforeChild) 55{ 56 // This function removes all children that are before (!) beforeChild 57 // and appends them to toBase. 58 ASSERT_ARG(toBase, toBase); 59 60 if (beforeChild && beforeChild->parent() != this) 61 beforeChild = splitAnonymousBoxesAroundChild(beforeChild); 62 63 if (childrenInline()) 64 moveInlineChildren(toBase, beforeChild); 65 else 66 moveBlockChildren(toBase, beforeChild); 67 68 setNeedsLayoutAndPrefWidthsRecalc(); 69 toBase->setNeedsLayoutAndPrefWidthsRecalc(); 70} 71 72void RenderRubyBase::mergeChildrenWithBase(RenderRubyBase* toBlock) 73{ 74 moveChildren(toBlock); 75 moveFloatsTo(toBlock); 76} 77 78void RenderRubyBase::moveInlineChildren(RenderRubyBase* toBase, RenderObject* beforeChild) 79{ 80 ASSERT(childrenInline()); 81 ASSERT_ARG(toBase, toBase); 82 83 if (!firstChild()) 84 return; 85 86 RenderBlock* toBlock; 87 if (toBase->childrenInline()) { 88 // The standard and easy case: move the children into the target base 89 toBlock = toBase; 90 } else { 91 // We need to wrap the inline objects into an anonymous block. 92 // If toBase has a suitable block, we re-use it, otherwise create a new one. 93 RenderObject* lastChild = toBase->lastChild(); 94 if (lastChild && lastChild->isAnonymousBlock() && lastChild->childrenInline()) 95 toBlock = toRenderBlock(lastChild); 96 else { 97 toBlock = toBase->createAnonymousBlock(); 98 toBase->insertChildInternal(toBlock, nullptr, NotifyChildren); 99 } 100 } 101 // Move our inline children into the target block we determined above. 102 moveChildrenTo(toBlock, firstChild(), beforeChild); 103} 104 105void RenderRubyBase::moveBlockChildren(RenderRubyBase* toBase, RenderObject* beforeChild) 106{ 107 ASSERT(!childrenInline()); 108 ASSERT_ARG(toBase, toBase); 109 110 if (!firstChild()) 111 return; 112 113 if (toBase->childrenInline()) 114 toBase->makeChildrenNonInline(); 115 116 // If an anonymous block would be put next to another such block, then merge those. 117 RenderObject* firstChildHere = firstChild(); 118 RenderObject* lastChildThere = toBase->lastChild(); 119 if (firstChildHere->isAnonymousBlock() && firstChildHere->childrenInline() 120 && lastChildThere && lastChildThere->isAnonymousBlock() && lastChildThere->childrenInline()) { 121 RenderBlock* anonBlockHere = toRenderBlock(firstChildHere); 122 RenderBlock* anonBlockThere = toRenderBlock(lastChildThere); 123 anonBlockHere->moveAllChildrenTo(anonBlockThere, true); 124 anonBlockHere->deleteLines(); 125 anonBlockHere->destroy(); 126 } 127 // Move all remaining children normally. 128 moveChildrenTo(toBase, firstChild(), beforeChild); 129} 130 131RenderRubyRun* RenderRubyBase::rubyRun() const 132{ 133 ASSERT(parent()); 134 ASSERT(parent()->isRubyRun()); 135 136 return &toRenderRubyRun(*parent()); 137} 138 139ETextAlign RenderRubyBase::textAlignmentForLine(bool /* endsWithSoftBreak */) const 140{ 141 return JUSTIFY; 142} 143 144void RenderRubyBase::adjustInlineDirectionLineBounds(int expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const 145{ 146 int maxPreferredLogicalWidth = this->maxPreferredLogicalWidth(); 147 if (maxPreferredLogicalWidth >= logicalWidth) 148 return; 149 150 // Inset the ruby base by half the inter-ideograph expansion amount. 151 float inset = (logicalWidth - maxPreferredLogicalWidth) / (expansionOpportunityCount + 1); 152 153 logicalLeft += inset / 2; 154 logicalWidth -= inset; 155} 156 157} // namespace WebCore 158