Index: Source/core/paint/ListMarkerPainter.cpp |
diff --git a/Source/core/paint/ListMarkerPainter.cpp b/Source/core/paint/ListMarkerPainter.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..42153720d7fe1ea5073e0bd2942eba532063e2ce |
--- /dev/null |
+++ b/Source/core/paint/ListMarkerPainter.cpp |
@@ -0,0 +1,214 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "config.h" |
+#include "core/paint/ListMarkerPainter.h" |
+ |
+#include "core/paint/BlockPainter.h" |
+#include "core/rendering/GraphicsContextAnnotator.h" |
+#include "core/rendering/PaintInfo.h" |
+#include "core/rendering/RenderListItem.h" |
+#include "core/rendering/RenderListMarker.h" |
+#include "core/rendering/TextRunConstructor.h" |
+#include "platform/geometry/LayoutPoint.h" |
+#include "platform/graphics/GraphicsContextStateSaver.h" |
+#include "wtf/unicode/CharacterNames.h" |
+ |
+namespace blink { |
+ |
+void ListMarkerPainter::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) |
+{ |
+ ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderListMarker); |
+ |
+ if (paintInfo.phase != PaintPhaseForeground) |
+ return; |
+ |
+ if (m_renderListMarker.style()->visibility() != VISIBLE) |
+ return; |
+ |
+ LayoutPoint boxOrigin(paintOffset + m_renderListMarker.location()); |
+ LayoutRect overflowRect(m_renderListMarker.visualOverflowRect()); |
+ overflowRect.moveBy(boxOrigin); |
+ |
+ if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect))) |
+ return; |
+ |
+ LayoutRect box(boxOrigin, m_renderListMarker.size()); |
+ |
+ IntRect marker = m_renderListMarker.getRelativeMarkerRect(); |
+ marker.moveBy(roundedIntPoint(boxOrigin)); |
+ |
+ GraphicsContext* context = paintInfo.context; |
+ |
+ if (m_renderListMarker.isImage()) { |
+ context->drawImage(m_renderListMarker.image()->image(&m_renderListMarker, marker.size()).get(), marker); |
+ if (m_renderListMarker.selectionState() != RenderObject::SelectionNone) { |
+ LayoutRect selRect = m_renderListMarker.localSelectionRect(); |
+ selRect.moveBy(boxOrigin); |
+ context->fillRect(pixelSnappedIntRect(selRect), m_renderListMarker.selectionBackgroundColor()); |
+ } |
+ return; |
+ } |
+ |
+ if (m_renderListMarker.selectionState() != RenderObject::SelectionNone) { |
+ LayoutRect selRect = m_renderListMarker.localSelectionRect(); |
+ selRect.moveBy(boxOrigin); |
+ context->fillRect(pixelSnappedIntRect(selRect), m_renderListMarker.selectionBackgroundColor()); |
+ } |
+ |
+ const Color color(m_renderListMarker.resolveColor(CSSPropertyColor)); |
+ context->setStrokeColor(color); |
+ context->setStrokeStyle(SolidStroke); |
+ context->setStrokeThickness(1.0f); |
+ context->setFillColor(color); |
+ |
+ EListStyleType type = m_renderListMarker.style()->listStyleType(); |
+ switch (type) { |
+ case Disc: |
+ context->fillEllipse(marker); |
+ return; |
+ case Circle: |
+ context->strokeEllipse(marker); |
+ return; |
+ case Square: |
+ context->fillRect(marker); |
+ return; |
+ case NoneListStyle: |
+ return; |
+ case Afar: |
+ case Amharic: |
+ case AmharicAbegede: |
+ case ArabicIndic: |
+ case Armenian: |
+ case BinaryListStyle: |
+ case Bengali: |
+ case Cambodian: |
+ case CJKIdeographic: |
+ case CjkEarthlyBranch: |
+ case CjkHeavenlyStem: |
+ case DecimalLeadingZero: |
+ case DecimalListStyle: |
+ case Devanagari: |
+ case Ethiopic: |
+ case EthiopicAbegede: |
+ case EthiopicAbegedeAmEt: |
+ case EthiopicAbegedeGez: |
+ case EthiopicAbegedeTiEr: |
+ case EthiopicAbegedeTiEt: |
+ case EthiopicHalehameAaEr: |
+ case EthiopicHalehameAaEt: |
+ case EthiopicHalehameAmEt: |
+ case EthiopicHalehameGez: |
+ case EthiopicHalehameOmEt: |
+ case EthiopicHalehameSidEt: |
+ case EthiopicHalehameSoEt: |
+ case EthiopicHalehameTiEr: |
+ case EthiopicHalehameTiEt: |
+ case EthiopicHalehameTig: |
+ case Georgian: |
+ case Gujarati: |
+ case Gurmukhi: |
+ case Hangul: |
+ case HangulConsonant: |
+ case Hebrew: |
+ case Hiragana: |
+ case HiraganaIroha: |
+ case Kannada: |
+ case Katakana: |
+ case KatakanaIroha: |
+ case Khmer: |
+ case Lao: |
+ case LowerAlpha: |
+ case LowerArmenian: |
+ case LowerGreek: |
+ case LowerHexadecimal: |
+ case LowerLatin: |
+ case LowerNorwegian: |
+ case LowerRoman: |
+ case Malayalam: |
+ case Mongolian: |
+ case Myanmar: |
+ case Octal: |
+ case Oriya: |
+ case Oromo: |
+ case Persian: |
+ case Sidama: |
+ case Somali: |
+ case Telugu: |
+ case Thai: |
+ case Tibetan: |
+ case Tigre: |
+ case TigrinyaEr: |
+ case TigrinyaErAbegede: |
+ case TigrinyaEt: |
+ case TigrinyaEtAbegede: |
+ case UpperAlpha: |
+ case UpperArmenian: |
+ case UpperGreek: |
+ case UpperHexadecimal: |
+ case UpperLatin: |
+ case UpperNorwegian: |
+ case UpperRoman: |
+ case Urdu: |
+ case Asterisks: |
+ case Footnotes: |
+ break; |
+ } |
+ if (m_renderListMarker.text().isEmpty()) |
+ return; |
+ |
+ const Font& font = m_renderListMarker.style()->font(); |
+ TextRun textRun = constructTextRun(&m_renderListMarker, font, m_renderListMarker.text(), m_renderListMarker.style()); |
+ |
+ GraphicsContextStateSaver stateSaver(*context, false); |
+ if (!m_renderListMarker.style()->isHorizontalWritingMode()) { |
+ marker.moveBy(roundedIntPoint(-boxOrigin)); |
+ marker = marker.transposedRect(); |
+ marker.moveBy(IntPoint(roundToInt(box.x()), roundToInt(box.y() - m_renderListMarker.logicalHeight()))); |
+ stateSaver.save(); |
+ context->translate(marker.x(), marker.maxY()); |
+ context->rotate(static_cast<float>(deg2rad(90.))); |
+ context->translate(-marker.x(), -marker.maxY()); |
+ } |
+ |
+ TextRunPaintInfo textRunPaintInfo(textRun); |
+ textRunPaintInfo.bounds = marker; |
+ IntPoint textOrigin = IntPoint(marker.x(), marker.y() + m_renderListMarker.style()->fontMetrics().ascent()); |
+ |
+ if (type == Asterisks || type == Footnotes) { |
+ context->drawText(font, textRunPaintInfo, textOrigin); |
+ } else { |
+ // 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 = WTF::Unicode::direction(m_renderListMarker.text()[0]) == WTF::Unicode::RightToLeft; |
+ StringBuilder reversedText; |
+ if (textNeedsReversing) { |
+ int length = m_renderListMarker.text().length(); |
+ reversedText.reserveCapacity(length); |
+ for (int i = length - 1; i >= 0; --i) |
+ reversedText.append(m_renderListMarker.text()[i]); |
+ ASSERT(reversedText.length() == reversedText.capacity()); |
+ textRun.setText(reversedText.toString()); |
+ } |
+ |
+ const UChar suffix = m_renderListMarker.listMarkerSuffix(type, m_renderListMarker.listItem()->value()); |
+ UChar suffixStr[2] = { |
+ m_renderListMarker.style()->isLeftToRightDirection() ? suffix : ' ', |
+ m_renderListMarker.style()->isLeftToRightDirection() ? ' ' : suffix |
+ }; |
+ TextRun suffixRun = constructTextRun(&m_renderListMarker, font, suffixStr, 2, m_renderListMarker.style(), m_renderListMarker.style()->direction()); |
+ TextRunPaintInfo suffixRunInfo(suffixRun); |
+ suffixRunInfo.bounds = marker; |
+ |
+ if (m_renderListMarker.style()->isLeftToRightDirection()) { |
+ context->drawText(font, textRunPaintInfo, textOrigin); |
+ context->drawText(font, suffixRunInfo, textOrigin + IntSize(font.width(textRun), 0)); |
+ } else { |
+ context->drawText(font, suffixRunInfo, textOrigin); |
+ context->drawText(font, textRunPaintInfo, textOrigin + IntSize(font.width(suffixRun), 0)); |
+ } |
+ } |
+} |
+ |
+} // namespace blink |