📄 renderlistmarker.cpp
字号:
TextRun textRun(m_text); // Text is not arbitrary. We can judge whether it's RTL from the first character, // and we only need to handle the direction RightToLeft for now. bool textNeedsReversing = direction(m_text[0]) == RightToLeft; Vector<UChar> reversedText; if (textNeedsReversing) { int length = m_text.length(); reversedText.grow(length); for (int i = 0; i < length; ++i) reversedText[length - i - 1] = m_text[i]; textRun = TextRun(reversedText.data(), length); } const Font& font = style()->font(); if (style()->direction() == LTR) { int width = font.width(textRun); context->drawText(style()->font(), textRun, marker.location()); const UChar periodSpace[2] = { '.', ' ' }; context->drawText(style()->font(), TextRun(periodSpace, 2), marker.location() + IntSize(width, 0)); } else { const UChar spacePeriod[2] = { ' ', '.' }; TextRun spacePeriodRun(spacePeriod, 2); int width = font.width(spacePeriodRun); context->drawText(style()->font(), spacePeriodRun, marker.location()); context->drawText(style()->font(), textRun, marker.location() + IntSize(width, 0)); }}void RenderListMarker::layout(){ ASSERT(needsLayout()); ASSERT(!prefWidthsDirty()); if (isImage()) { setWidth(m_image->imageSize(this, style()->effectiveZoom()).width()); setHeight(m_image->imageSize(this, style()->effectiveZoom()).height()); } else { setWidth(minPrefWidth()); setHeight(style()->font().height()); } m_marginLeft = m_marginRight = 0; Length leftMargin = style()->marginLeft(); Length rightMargin = style()->marginRight(); if (leftMargin.isFixed()) m_marginLeft = leftMargin.value(); if (rightMargin.isFixed()) m_marginRight = rightMargin.value(); setNeedsLayout(false);}void RenderListMarker::imageChanged(WrappedImagePtr o, const IntRect*){ // A list marker can't have a background or border image, so no need to call the base class method. if (o != m_image->data()) return; if (width() != m_image->imageSize(this, style()->effectiveZoom()).width() || height() != m_image->imageSize(this, style()->effectiveZoom()).height() || m_image->errorOccurred()) setNeedsLayoutAndPrefWidthsRecalc(); else repaint();}void RenderListMarker::calcPrefWidths(){ ASSERT(prefWidthsDirty()); m_text = ""; const Font& font = style()->font(); if (isImage()) { // FIXME: This is a somewhat arbitrary width. Generated images for markers really won't become particularly useful // until we support the CSS3 marker pseudoclass to allow control over the width and height of the marker box. int bulletWidth = font.ascent() / 2; m_image->setImageContainerSize(IntSize(bulletWidth, bulletWidth)); m_minPrefWidth = m_maxPrefWidth = m_image->imageSize(this, style()->effectiveZoom()).width(); setPrefWidthsDirty(false); updateMargins(); return; } int width = 0; EListStyleType type = style()->listStyleType(); switch (type) { case LNONE: break; case CIRCLE: case DISC: case SQUARE: m_text = listMarkerText(type, 0); // value is ignored for these types width = (font.ascent() * 2 / 3 + 1) / 2 + 2; break; case ARMENIAN: case CJK_IDEOGRAPHIC: case DECIMAL_LEADING_ZERO: case GEORGIAN: case HEBREW: case HIRAGANA: case HIRAGANA_IROHA: case KATAKANA: case KATAKANA_IROHA: case LDECIMAL: case LOWER_ALPHA: case LOWER_GREEK: case LOWER_LATIN: case LOWER_ROMAN: case UPPER_ALPHA: case UPPER_LATIN: case UPPER_ROMAN: m_text = listMarkerText(type, m_listItem->value()); if (m_text.isEmpty()) width = 0; else { int itemWidth = font.width(m_text); const UChar periodSpace[2] = { '.', ' ' }; int periodSpaceWidth = font.width(TextRun(periodSpace, 2)); width = itemWidth + periodSpaceWidth; } break; } m_minPrefWidth = width; m_maxPrefWidth = width; setPrefWidthsDirty(false); updateMargins();}void RenderListMarker::updateMargins(){ const Font& font = style()->font(); int marginLeft = 0; int marginRight = 0; if (isInside()) { if (isImage()) { if (style()->direction() == LTR) marginRight = cMarkerPadding; else marginLeft = cMarkerPadding; } else switch (style()->listStyleType()) { case DISC: case CIRCLE: case SQUARE: if (style()->direction() == LTR) { marginLeft = -1; marginRight = font.ascent() - minPrefWidth() + 1; } else { marginLeft = font.ascent() - minPrefWidth() + 1; marginRight = -1; } break; default: break; } } else { if (style()->direction() == LTR) { if (isImage()) marginLeft = -minPrefWidth() - cMarkerPadding; else { int offset = font.ascent() * 2 / 3; switch (style()->listStyleType()) { case DISC: case CIRCLE: case SQUARE: marginLeft = -offset - cMarkerPadding - 1; break; case LNONE: break; default: marginLeft = m_text.isEmpty() ? 0 : -minPrefWidth() - offset / 2; } } } else { if (isImage()) marginLeft = cMarkerPadding; else { int offset = font.ascent() * 2 / 3; switch (style()->listStyleType()) { case DISC: case CIRCLE: case SQUARE: marginLeft = offset + cMarkerPadding + 1 - minPrefWidth(); break; case LNONE: break; default: marginLeft = m_text.isEmpty() ? 0 : offset / 2; } } } marginRight = -marginLeft - minPrefWidth(); } style()->setMarginLeft(Length(marginLeft, Fixed)); style()->setMarginRight(Length(marginRight, Fixed));}int RenderListMarker::lineHeight(bool, bool) const{ if (!isImage()) return m_listItem->lineHeight(false, true); return height();}int RenderListMarker::baselinePosition(bool, bool) const{ if (!isImage()) { const Font& font = style()->font(); return font.ascent() + (lineHeight(false) - font.height())/2; } return height();}bool RenderListMarker::isInside() const{ return m_listItem->notInList() || style()->listStylePosition() == INSIDE;}IntRect RenderListMarker::getRelativeMarkerRect(){ if (isImage()) return IntRect(x(), y(), m_image->imageSize(this, style()->effectiveZoom()).width(), m_image->imageSize(this, style()->effectiveZoom()).height()); switch (style()->listStyleType()) { case DISC: case CIRCLE: case SQUARE: { // FIXME: Are these particular rounding rules necessary? const Font& font = style()->font(); int ascent = font.ascent(); int bulletWidth = (ascent * 2 / 3 + 1) / 2; return IntRect(x() + 1, y() + 3 * (ascent - ascent * 2 / 3) / 2, bulletWidth, bulletWidth); } case LNONE: return IntRect(); case ARMENIAN: case CJK_IDEOGRAPHIC: case DECIMAL_LEADING_ZERO: case GEORGIAN: case HEBREW: case HIRAGANA: case HIRAGANA_IROHA: case KATAKANA: case KATAKANA_IROHA: case LDECIMAL: case LOWER_ALPHA: case LOWER_GREEK: case LOWER_LATIN: case LOWER_ROMAN: case UPPER_ALPHA: case UPPER_LATIN: case UPPER_ROMAN: if (m_text.isEmpty()) return IntRect(); const Font& font = style()->font(); int itemWidth = font.width(m_text); const UChar periodSpace[2] = { '.', ' ' }; int periodSpaceWidth = font.width(TextRun(periodSpace, 2)); return IntRect(x(), y() + font.ascent(), itemWidth + periodSpaceWidth, font.height()); } return IntRect();}void RenderListMarker::setSelectionState(SelectionState state){ RenderBox::setSelectionState(state); if (InlineBox* box = inlineBoxWrapper()) if (RootInlineBox* root = box->root()) root->setHasSelectedChildren(state != SelectionNone); containingBlock()->setSelectionState(state);}IntRect RenderListMarker::selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent){ ASSERT(!needsLayout()); if (selectionState() == SelectionNone || !inlineBoxWrapper()) return IntRect(); RootInlineBox* root = inlineBoxWrapper()->root(); IntRect rect(0, root->selectionTop() - y(), width(), root->selectionHeight()); if (clipToVisibleContent) computeRectForRepaint(repaintContainer, rect); else rect = localToContainerQuad(FloatRect(rect), repaintContainer).enclosingBoundingBox(); return rect;}} // namespace WebCore
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -