| /* |
| * Copyright (C) 2009 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "core/layout/LayoutRubyBase.h" |
| |
| namespace blink { |
| |
| LayoutRubyBase::LayoutRubyBase() : LayoutBlockFlow(nullptr) { |
| setInline(false); |
| } |
| |
| LayoutRubyBase::~LayoutRubyBase() {} |
| |
| LayoutRubyBase* LayoutRubyBase::createAnonymous(Document* document) { |
| LayoutRubyBase* layoutObject = new LayoutRubyBase(); |
| layoutObject->setDocumentForAnonymous(document); |
| return layoutObject; |
| } |
| |
| bool LayoutRubyBase::isChildAllowed(LayoutObject* child, |
| const ComputedStyle&) const { |
| return child->isInline(); |
| } |
| |
| void LayoutRubyBase::moveChildren(LayoutRubyBase* toBase, |
| LayoutObject* beforeChild) { |
| // This function removes all children that are before (!) beforeChild |
| // and appends them to toBase. |
| DCHECK(toBase); |
| // Callers should have handled the percent height descendant map. |
| ASSERT(!hasPercentHeightDescendants()); |
| |
| if (beforeChild && beforeChild->parent() != this) |
| beforeChild = splitAnonymousBoxesAroundChild(beforeChild); |
| |
| if (childrenInline()) |
| moveInlineChildren(toBase, beforeChild); |
| else |
| moveBlockChildren(toBase, beforeChild); |
| |
| setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
| LayoutInvalidationReason::Unknown); |
| toBase->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
| LayoutInvalidationReason::Unknown); |
| } |
| |
| void LayoutRubyBase::moveInlineChildren(LayoutRubyBase* toBase, |
| LayoutObject* beforeChild) { |
| ASSERT(childrenInline()); |
| DCHECK(toBase); |
| |
| if (!firstChild()) |
| return; |
| |
| LayoutBlock* toBlock; |
| if (toBase->childrenInline()) { |
| // The standard and easy case: move the children into the target base |
| toBlock = toBase; |
| } else { |
| // We need to wrap the inline objects into an anonymous block. |
| // If toBase has a suitable block, we re-use it, otherwise create a new one. |
| LayoutObject* lastChild = toBase->lastChild(); |
| if (lastChild && lastChild->isAnonymousBlock() && |
| lastChild->childrenInline()) { |
| toBlock = toLayoutBlock(lastChild); |
| } else { |
| toBlock = toBase->createAnonymousBlock(); |
| toBase->children()->appendChildNode(toBase, toBlock); |
| } |
| } |
| // Move our inline children into the target block we determined above. |
| moveChildrenTo(toBlock, firstChild(), beforeChild); |
| } |
| |
| void LayoutRubyBase::moveBlockChildren(LayoutRubyBase* toBase, |
| LayoutObject* beforeChild) { |
| ASSERT(!childrenInline()); |
| DCHECK(toBase); |
| |
| if (!firstChild()) |
| return; |
| |
| if (toBase->childrenInline()) |
| toBase->makeChildrenNonInline(); |
| |
| // If an anonymous block would be put next to another such block, then merge |
| // those. |
| LayoutObject* firstChildHere = firstChild(); |
| LayoutObject* lastChildThere = toBase->lastChild(); |
| if (firstChildHere->isAnonymousBlock() && firstChildHere->childrenInline() && |
| lastChildThere && lastChildThere->isAnonymousBlock() && |
| lastChildThere->childrenInline()) { |
| LayoutBlockFlow* anonBlockHere = toLayoutBlockFlow(firstChildHere); |
| LayoutBlockFlow* anonBlockThere = toLayoutBlockFlow(lastChildThere); |
| anonBlockHere->moveAllChildrenTo(anonBlockThere, |
| anonBlockThere->children()); |
| anonBlockHere->deleteLineBoxTree(); |
| anonBlockHere->destroy(); |
| } |
| // Move all remaining children normally. If moving all children, include our |
| // float list. |
| if (!beforeChild) |
| moveAllChildrenIncludingFloatsTo(toBase, toBase->hasLayer() || hasLayer()); |
| else |
| moveChildrenTo(toBase, firstChild(), beforeChild, toBase->children()); |
| } |
| |
| ETextAlign LayoutRubyBase::textAlignmentForLine( |
| bool /* endsWithSoftBreak */) const { |
| return ETextAlign::Justify; |
| } |
| |
| void LayoutRubyBase::adjustInlineDirectionLineBounds( |
| unsigned expansionOpportunityCount, |
| LayoutUnit& logicalLeft, |
| LayoutUnit& logicalWidth) const { |
| int maxPreferredLogicalWidth = this->maxPreferredLogicalWidth().toInt(); |
| if (maxPreferredLogicalWidth >= logicalWidth) |
| return; |
| |
| unsigned maxCount = static_cast<unsigned>(LayoutUnit::max().floor()); |
| if (expansionOpportunityCount > maxCount) |
| expansionOpportunityCount = maxCount; |
| |
| // Inset the ruby base by half the inter-ideograph expansion amount. |
| LayoutUnit inset = (logicalWidth - maxPreferredLogicalWidth) / |
| (expansionOpportunityCount + 1); |
| |
| logicalLeft += inset / 2; |
| logicalWidth -= inset; |
| } |
| |
| } // namespace blink |