int RenderTextControl::textBlockLogicalHeight() const { return logicalHeight() - borderAndPaddingLogicalHeight(); }
int LayoutTextControl::textBlockLogicalHeight() const { return (logicalHeight() - borderAndPaddingLogicalHeight()).toInt(); }
float RootInlineBox::placeEllipsis(const AtomicString& ellipsisStr, bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, InlineBox* markupBox) { if (!gEllipsisBoxMap) gEllipsisBoxMap = new EllipsisBoxMap(); // Create an ellipsis box. auto newEllipsisBox = std::make_unique<EllipsisBox>(blockFlow(), ellipsisStr, this, ellipsisWidth - (markupBox ? markupBox->logicalWidth() : 0), logicalHeight(), y(), !prevRootBox(), isHorizontal(), markupBox); auto ellipsisBox = newEllipsisBox.get(); gEllipsisBoxMap->add(this, std::move(newEllipsisBox)); setHasEllipsisBox(true); // FIXME: Do we need an RTL version of this? if (ltr && (x() + logicalWidth() + ellipsisWidth) <= blockRightEdge) { ellipsisBox->setX(x() + logicalWidth()); return logicalWidth() + ellipsisWidth; } // Now attempt to find the nearest glyph horizontally and place just to the right (or left in RTL) // of that glyph. Mark all of the objects that intersect the ellipsis box as not painting (as being // truncated). bool foundBox = false; float truncatedWidth = 0; float position = placeEllipsisBox(ltr, blockLeftEdge, blockRightEdge, ellipsisWidth, truncatedWidth, foundBox); ellipsisBox->setX(position); return truncatedWidth; }
LayoutUnit RootInlineBox::lineSnapAdjustment(LayoutUnit delta) const { // If our block doesn't have snapping turned on, do nothing. // FIXME: Implement bounds snapping. if (blockFlow().style().lineSnap() == LineSnapNone) return 0; // Get the current line grid and offset. LayoutState* layoutState = blockFlow().view().layoutState(); RenderBlockFlow* lineGrid = layoutState->lineGrid(); LayoutSize lineGridOffset = layoutState->lineGridOffset(); if (!lineGrid || lineGrid->style().writingMode() != blockFlow().style().writingMode()) return 0; // Get the hypothetical line box used to establish the grid. RootInlineBox* lineGridBox = lineGrid->lineGridBox(); if (!lineGridBox) return 0; LayoutUnit lineGridBlockOffset = lineGrid->isHorizontalWritingMode() ? lineGridOffset.height() : lineGridOffset.width(); LayoutUnit blockOffset = blockFlow().isHorizontalWritingMode() ? layoutState->layoutOffset().height() : layoutState->layoutOffset().width(); // Now determine our position on the grid. Our baseline needs to be adjusted to the nearest baseline multiple // as established by the line box. // FIXME: Need to handle crazy line-box-contain values that cause the root line box to not be considered. I assume // the grid should honor line-box-contain. LayoutUnit gridLineHeight = lineGridBox->lineBottomWithLeading() - lineGridBox->lineTopWithLeading(); if (!gridLineHeight) return 0; LayoutUnit lineGridFontAscent = lineGrid->style().fontMetrics().ascent(baselineType()); LayoutUnit lineGridFontHeight = lineGridBox->logicalHeight(); LayoutUnit firstTextTop = lineGridBlockOffset + lineGridBox->logicalTop(); LayoutUnit firstLineTopWithLeading = lineGridBlockOffset + lineGridBox->lineTopWithLeading(); LayoutUnit firstBaselinePosition = firstTextTop + lineGridFontAscent; LayoutUnit currentTextTop = blockOffset + logicalTop() + delta; LayoutUnit currentFontAscent = blockFlow().style().fontMetrics().ascent(baselineType()); LayoutUnit currentBaselinePosition = currentTextTop + currentFontAscent; LayoutUnit lineGridPaginationOrigin = isHorizontal() ? layoutState->lineGridPaginationOrigin().height() : layoutState->lineGridPaginationOrigin().width(); // If we're paginated, see if we're on a page after the first one. If so, the grid resets on subsequent pages. // FIXME: If the grid is an ancestor of the pagination establisher, then this is incorrect. LayoutUnit pageLogicalTop = 0; if (layoutState->isPaginated() && layoutState->pageLogicalHeight()) { pageLogicalTop = blockFlow().pageLogicalTopForOffset(lineTopWithLeading() + delta); if (pageLogicalTop > firstLineTopWithLeading) firstTextTop = pageLogicalTop + lineGridBox->logicalTop() - lineGrid->borderAndPaddingBefore() + lineGridPaginationOrigin; } if (blockFlow().style().lineSnap() == LineSnapContain) { // Compute the desired offset from the text-top of a grid line. // Look at our height (logicalHeight()). // Look at the total available height. It's going to be (textBottom - textTop) + (n-1)*(multiple with leading) // where n is number of grid lines required to enclose us. if (logicalHeight() <= lineGridFontHeight) firstTextTop += (lineGridFontHeight - logicalHeight()) / 2; else { LayoutUnit numberOfLinesWithLeading = ceilf(static_cast<float>(logicalHeight() - lineGridFontHeight) / gridLineHeight); LayoutUnit totalHeight = lineGridFontHeight + numberOfLinesWithLeading * gridLineHeight; firstTextTop += (totalHeight - logicalHeight()) / 2; } firstBaselinePosition = firstTextTop + currentFontAscent; } else firstBaselinePosition = firstTextTop + lineGridFontAscent; // If we're above the first line, just push to the first line. if (currentBaselinePosition < firstBaselinePosition) return delta + firstBaselinePosition - currentBaselinePosition; // Otherwise we're in the middle of the grid somewhere. Just push to the next line. LayoutUnit baselineOffset = currentBaselinePosition - firstBaselinePosition; LayoutUnit remainder = roundToInt(baselineOffset) % roundToInt(gridLineHeight); LayoutUnit result = delta; if (remainder) result += gridLineHeight - remainder; // If we aren't paginated we can return the result. if (!layoutState->isPaginated() || !layoutState->pageLogicalHeight() || result == delta) return result; // We may end up shifted to a new page. We need to do a re-snap when that happens. LayoutUnit newPageLogicalTop = blockFlow().pageLogicalTopForOffset(lineBottomWithLeading() + result); if (newPageLogicalTop == pageLogicalTop) return result; // Put ourselves at the top of the next page to force a snap onto the new grid established by that page. return lineSnapAdjustment(newPageLogicalTop - (blockOffset + lineTopWithLeading())); }
unsigned MultiColumnFragmentainerGroup::columnIndexAtVisualPoint(const LayoutPoint& visualPoint) const { bool isColumnProgressionInline = m_columnSet.multiColumnFlowThread()->progressionIsInline(); bool isHorizontalWritingMode = m_columnSet.isHorizontalWritingMode(); LayoutUnit columnLengthInColumnProgressionDirection = isColumnProgressionInline ? m_columnSet.pageLogicalWidth() : logicalHeight(); LayoutUnit offsetInColumnProgressionDirection = isHorizontalWritingMode == isColumnProgressionInline ? visualPoint.x() : visualPoint.y(); if (!m_columnSet.style()->isLeftToRightDirection() && isColumnProgressionInline) offsetInColumnProgressionDirection = m_columnSet.logicalWidth() - offsetInColumnProgressionDirection; LayoutUnit columnGap = m_columnSet.columnGap(); if (columnLengthInColumnProgressionDirection + columnGap <= 0) return 0; // Column boundaries are in the middle of the column gap. int index = (offsetInColumnProgressionDirection + columnGap / 2) / (columnLengthInColumnProgressionDirection + columnGap); if (index < 0) return 0; return std::min(unsigned(index), actualColumnCount() - 1); }