void RenderRubyRun::getOverhang(bool firstLine, RenderObject* startRenderer, RenderObject* endRenderer, int& startOverhang, int& endOverhang) const { ASSERT(!needsLayout()); startOverhang = 0; endOverhang = 0; RenderRubyBase* rubyBase = this->rubyBase(); RenderRubyText* rubyText = this->rubyText(); if (!rubyBase || !rubyText) return; if (!rubyBase->firstRootBox()) return; int logicalWidth = this->logicalWidth(); int logicalLeftOverhang = numeric_limits<int>::max(); int logicalRightOverhang = numeric_limits<int>::max(); for (RootInlineBox* rootInlineBox = rubyBase->firstRootBox(); rootInlineBox; rootInlineBox = rootInlineBox->nextRootBox()) { logicalLeftOverhang = min<int>(logicalLeftOverhang, rootInlineBox->logicalLeft()); logicalRightOverhang = min<int>(logicalRightOverhang, logicalWidth - rootInlineBox->logicalRight()); } startOverhang = style()->isLeftToRightDirection() ? logicalLeftOverhang : logicalRightOverhang; endOverhang = style()->isLeftToRightDirection() ? logicalRightOverhang : logicalLeftOverhang; if (!startRenderer || !startRenderer->isText() || startRenderer->style(firstLine)->fontSize() > rubyBase->style(firstLine)->fontSize()) startOverhang = 0; if (!endRenderer || !endRenderer->isText() || endRenderer->style(firstLine)->fontSize() > rubyBase->style(firstLine)->fontSize()) endOverhang = 0; // We overhang a ruby only if the neighboring render object is a text. // We can overhang the ruby by no more than half the width of the neighboring text // and no more than half the font size. int halfWidthOfFontSize = rubyText->style(firstLine)->fontSize() / 2; if (startOverhang) startOverhang = min<int>(startOverhang, min<int>(toRenderText(startRenderer)->minLogicalWidth(), halfWidthOfFontSize)); if (endOverhang) endOverhang = min<int>(endOverhang, min<int>(toRenderText(endRenderer)->minLogicalWidth(), halfWidthOfFontSize)); }
void RenderRubyRun::getOverhang(bool firstLine, RenderObject* startRenderer, RenderObject* endRenderer, int& startOverhang, int& endOverhang) const { ASSERT(!needsLayout()); startOverhang = 0; endOverhang = 0; RenderRubyBase* rubyBase = this->rubyBase(); RenderRubyText* rubyText = this->rubyText(); if (!rubyBase || !rubyText) return; if (!rubyBase->firstRootBox()) return; int logicalWidth = this->logicalWidth(); // No more than half a ruby is allowed to overhang. int logicalLeftOverhang = rubyText->style(firstLine)->fontSize() / 2; int logicalRightOverhang = logicalLeftOverhang; for (RootInlineBox* rootInlineBox = rubyBase->firstRootBox(); rootInlineBox; rootInlineBox = rootInlineBox->nextRootBox()) { logicalLeftOverhang = min<int>(logicalLeftOverhang, rootInlineBox->logicalLeft()); logicalRightOverhang = min<int>(logicalRightOverhang, logicalWidth - rootInlineBox->logicalRight()); } startOverhang = style()->isLeftToRightDirection() ? logicalLeftOverhang : logicalRightOverhang; endOverhang = style()->isLeftToRightDirection() ? logicalRightOverhang : logicalLeftOverhang; if (!startRenderer || !startRenderer->isText() || startRenderer->style(firstLine)->fontSize() > rubyBase->style(firstLine)->fontSize()) startOverhang = 0; if (!endRenderer || !endRenderer->isText() || endRenderer->style(firstLine)->fontSize() > rubyBase->style(firstLine)->fontSize()) endOverhang = 0; }
void RenderRubyRun::layout() { RenderBlockFlow::layout(); RenderRubyText* rt = rubyText(); if (!rt) return; rt->setLogicalLeft(0); // Place the RenderRubyText such that its bottom is flush with the lineTop of the first line of the RenderRubyBase. LayoutUnit lastLineRubyTextBottom = rt->logicalHeight(); LayoutUnit firstLineRubyTextTop = 0; RootInlineBox* rootBox = rt->lastRootBox(); if (rootBox) { // In order to align, we have to ignore negative leading. firstLineRubyTextTop = rt->firstRootBox()->logicalTopLayoutOverflow(); lastLineRubyTextBottom = rootBox->logicalBottomLayoutOverflow(); } if (isHorizontalWritingMode() && rt->style().rubyPosition() == RubyPositionInterCharacter) { // Bopomofo. We need to move the RenderRubyText over to the right side and center it // vertically relative to the base. const Font& font = style().font(); float distanceBetweenBase = max(font.letterSpacing(), 2.0f * rt->style().font().fontMetrics().height()); setWidth(width() + distanceBetweenBase - font.letterSpacing()); if (RenderRubyBase* rb = rubyBase()) { LayoutUnit firstLineTop = 0; LayoutUnit lastLineBottom = logicalHeight(); RootInlineBox* rootBox = rb->firstRootBox(); if (rootBox) firstLineTop = rootBox->logicalTopLayoutOverflow(); firstLineTop += rb->logicalTop(); if (rootBox) lastLineBottom = rootBox->logicalBottomLayoutOverflow(); lastLineBottom += rb->logicalTop(); rt->setX(rb->x() + rb->width() - font.letterSpacing()); LayoutUnit extent = lastLineBottom - firstLineTop; rt->setY(firstLineTop + (extent - rt->height()) / 2); } } else if (style().isFlippedLinesWritingMode() == (style().rubyPosition() == RubyPositionAfter)) { LayoutUnit firstLineTop = 0; if (RenderRubyBase* rb = rubyBase()) { RootInlineBox* rootBox = rb->firstRootBox(); if (rootBox) firstLineTop = rootBox->logicalTopLayoutOverflow(); firstLineTop += rb->logicalTop(); } rt->setLogicalTop(-lastLineRubyTextBottom + firstLineTop); } else { LayoutUnit lastLineBottom = logicalHeight(); if (RenderRubyBase* rb = rubyBase()) { RootInlineBox* rootBox = rb->lastRootBox(); if (rootBox) lastLineBottom = rootBox->logicalBottomLayoutOverflow(); lastLineBottom += rb->logicalTop(); } rt->setLogicalTop(-firstLineRubyTextTop + lastLineBottom); } // Update our overflow to account for the new RenderRubyText position. computeOverflow(clientLogicalBottom()); }