| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 #include "core/paint/ListMarkerPainter.h" | 6 #include "core/paint/ListMarkerPainter.h" |
| 7 | 7 |
| 8 #include "core/layout/LayoutListItem.h" | 8 #include "core/layout/LayoutListItem.h" |
| 9 #include "core/layout/LayoutListMarker.h" | 9 #include "core/layout/LayoutListMarker.h" |
| 10 #include "core/layout/ListMarkerText.h" | 10 #include "core/layout/ListMarkerText.h" |
| 11 #include "core/layout/TextRunConstructor.h" | 11 #include "core/layout/TextRunConstructor.h" |
| 12 #include "core/layout/api/SelectionState.h" | 12 #include "core/layout/api/SelectionState.h" |
| 13 #include "core/paint/BlockPainter.h" | 13 #include "core/paint/BlockPainter.h" |
| 14 #include "core/paint/LayoutObjectDrawingRecorder.h" | 14 #include "core/paint/LayoutObjectDrawingRecorder.h" |
| 15 #include "core/paint/PaintInfo.h" | 15 #include "core/paint/PaintInfo.h" |
| 16 #include "platform/RuntimeEnabledFeatures.h" | 16 #include "platform/RuntimeEnabledFeatures.h" |
| 17 #include "platform/geometry/LayoutPoint.h" | 17 #include "platform/geometry/LayoutPoint.h" |
| 18 #include "platform/graphics/GraphicsContextStateSaver.h" | 18 #include "platform/graphics/GraphicsContextStateSaver.h" |
| 19 #include "wtf/text/CharacterNames.h" | 19 #include "wtf/text/CharacterNames.h" |
| 20 | 20 |
| 21 namespace blink { | 21 namespace blink { |
| 22 | 22 |
| 23 static inline void paintSymbol(GraphicsContext* context, const Color& color, | 23 static inline void paintSymbol(GraphicsContext& context, const Color& color, |
| 24 const IntRect& marker, EListStyleType listStyle) | 24 const IntRect& marker, EListStyleType listStyle) |
| 25 { | 25 { |
| 26 context->setStrokeColor(color); | 26 context.setStrokeColor(color); |
| 27 context->setStrokeStyle(SolidStroke); | 27 context.setStrokeStyle(SolidStroke); |
| 28 context->setStrokeThickness(1.0f); | 28 context.setStrokeThickness(1.0f); |
| 29 switch (listStyle) { | 29 switch (listStyle) { |
| 30 case Disc: | 30 case Disc: |
| 31 context->fillEllipse(marker); | 31 context.fillEllipse(marker); |
| 32 break; | 32 break; |
| 33 case Circle: | 33 case Circle: |
| 34 context->strokeEllipse(marker); | 34 context.strokeEllipse(marker); |
| 35 break; | 35 break; |
| 36 case Square: | 36 case Square: |
| 37 context->fillRect(marker); | 37 context.fillRect(marker); |
| 38 break; | 38 break; |
| 39 default: | 39 default: |
| 40 ASSERT_NOT_REACHED(); | 40 ASSERT_NOT_REACHED(); |
| 41 break; | 41 break; |
| 42 } | 42 } |
| 43 } | 43 } |
| 44 | 44 |
| 45 void ListMarkerPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& pai
ntOffset) | 45 void ListMarkerPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& pai
ntOffset) |
| 46 { | 46 { |
| 47 if (paintInfo.phase != PaintPhaseForeground) | 47 if (paintInfo.phase != PaintPhaseForeground) |
| 48 return; | 48 return; |
| 49 | 49 |
| 50 if (m_layoutListMarker.style()->visibility() != VISIBLE) | 50 if (m_layoutListMarker.style()->visibility() != VISIBLE) |
| 51 return; | 51 return; |
| 52 | 52 |
| 53 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.conte
xt, m_layoutListMarker, paintInfo.phase, paintOffset)) | 53 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.contex
t, m_layoutListMarker, paintInfo.phase, paintOffset)) |
| 54 return; | 54 return; |
| 55 | 55 |
| 56 LayoutPoint boxOrigin(paintOffset + m_layoutListMarker.location()); | 56 LayoutPoint boxOrigin(paintOffset + m_layoutListMarker.location()); |
| 57 LayoutRect overflowRect(m_layoutListMarker.visualOverflowRect()); | 57 LayoutRect overflowRect(m_layoutListMarker.visualOverflowRect()); |
| 58 if (!RuntimeEnabledFeatures::selectionPaintingWithoutSelectionGapsEnabled() | 58 if (!RuntimeEnabledFeatures::selectionPaintingWithoutSelectionGapsEnabled() |
| 59 && m_layoutListMarker.selectionState() != SelectionNone) | 59 && m_layoutListMarker.selectionState() != SelectionNone) |
| 60 overflowRect.unite(m_layoutListMarker.localSelectionRect()); | 60 overflowRect.unite(m_layoutListMarker.localSelectionRect()); |
| 61 overflowRect.moveBy(boxOrigin); | 61 overflowRect.moveBy(boxOrigin); |
| 62 | 62 |
| 63 IntRect pixelSnappedOverflowRect = pixelSnappedIntRect(overflowRect); | 63 IntRect pixelSnappedOverflowRect = pixelSnappedIntRect(overflowRect); |
| 64 if (!paintInfo.cullRect().intersectsCullRect(overflowRect)) | 64 if (!paintInfo.cullRect().intersectsCullRect(overflowRect)) |
| 65 return; | 65 return; |
| 66 | 66 |
| 67 LayoutObjectDrawingRecorder recorder(*paintInfo.context, m_layoutListMarker,
paintInfo.phase, pixelSnappedOverflowRect, paintOffset); | 67 LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutListMarker,
paintInfo.phase, pixelSnappedOverflowRect, paintOffset); |
| 68 | 68 |
| 69 LayoutRect box(boxOrigin, m_layoutListMarker.size()); | 69 LayoutRect box(boxOrigin, m_layoutListMarker.size()); |
| 70 | 70 |
| 71 IntRect marker = m_layoutListMarker.getRelativeMarkerRect(); | 71 IntRect marker = m_layoutListMarker.getRelativeMarkerRect(); |
| 72 marker.moveBy(roundedIntPoint(boxOrigin)); | 72 marker.moveBy(roundedIntPoint(boxOrigin)); |
| 73 | 73 |
| 74 GraphicsContext* context = paintInfo.context; | 74 GraphicsContext& context = paintInfo.context; |
| 75 | 75 |
| 76 if (m_layoutListMarker.isImage()) { | 76 if (m_layoutListMarker.isImage()) { |
| 77 context->drawImage(m_layoutListMarker.image()->image( | 77 context.drawImage(m_layoutListMarker.image()->image( |
| 78 &m_layoutListMarker, marker.size(), m_layoutListMarker.styleRef().ef
fectiveZoom()).get(), marker); | 78 &m_layoutListMarker, marker.size(), m_layoutListMarker.styleRef().ef
fectiveZoom()).get(), marker); |
| 79 if (m_layoutListMarker.selectionState() != SelectionNone) { | 79 if (m_layoutListMarker.selectionState() != SelectionNone) { |
| 80 LayoutRect selRect = m_layoutListMarker.localSelectionRect(); | 80 LayoutRect selRect = m_layoutListMarker.localSelectionRect(); |
| 81 selRect.moveBy(boxOrigin); | 81 selRect.moveBy(boxOrigin); |
| 82 context->fillRect(pixelSnappedIntRect(selRect), m_layoutListMarker.l
istItem()->selectionBackgroundColor()); | 82 context.fillRect(pixelSnappedIntRect(selRect), m_layoutListMarker.li
stItem()->selectionBackgroundColor()); |
| 83 } | 83 } |
| 84 return; | 84 return; |
| 85 } | 85 } |
| 86 | 86 |
| 87 if (!RuntimeEnabledFeatures::selectionPaintingWithoutSelectionGapsEnabled() | 87 if (!RuntimeEnabledFeatures::selectionPaintingWithoutSelectionGapsEnabled() |
| 88 && m_layoutListMarker.selectionState() != SelectionNone) { | 88 && m_layoutListMarker.selectionState() != SelectionNone) { |
| 89 LayoutRect selRect = m_layoutListMarker.localSelectionRect(); | 89 LayoutRect selRect = m_layoutListMarker.localSelectionRect(); |
| 90 selRect.moveBy(boxOrigin); | 90 selRect.moveBy(boxOrigin); |
| 91 context->fillRect(pixelSnappedIntRect(selRect), m_layoutListMarker.listI
tem()->selectionBackgroundColor()); | 91 context.fillRect(pixelSnappedIntRect(selRect), m_layoutListMarker.listIt
em()->selectionBackgroundColor()); |
| 92 } | 92 } |
| 93 | 93 |
| 94 LayoutListMarker::ListStyleCategory styleCategory = m_layoutListMarker.listS
tyleCategory(); | 94 LayoutListMarker::ListStyleCategory styleCategory = m_layoutListMarker.listS
tyleCategory(); |
| 95 if (styleCategory == LayoutListMarker::ListStyleCategory::None) | 95 if (styleCategory == LayoutListMarker::ListStyleCategory::None) |
| 96 return; | 96 return; |
| 97 | 97 |
| 98 const Color color(m_layoutListMarker.resolveColor(CSSPropertyColor)); | 98 const Color color(m_layoutListMarker.resolveColor(CSSPropertyColor)); |
| 99 // Apply the color to the list marker text. | 99 // Apply the color to the list marker text. |
| 100 context->setFillColor(color); | 100 context.setFillColor(color); |
| 101 | 101 |
| 102 const EListStyleType listStyle = m_layoutListMarker.style()->listStyleType()
; | 102 const EListStyleType listStyle = m_layoutListMarker.style()->listStyleType()
; |
| 103 if (styleCategory == LayoutListMarker::ListStyleCategory::Symbol) { | 103 if (styleCategory == LayoutListMarker::ListStyleCategory::Symbol) { |
| 104 paintSymbol(context, color, marker, listStyle); | 104 paintSymbol(context, color, marker, listStyle); |
| 105 return; | 105 return; |
| 106 } | 106 } |
| 107 | 107 |
| 108 if (m_layoutListMarker.text().isEmpty()) | 108 if (m_layoutListMarker.text().isEmpty()) |
| 109 return; | 109 return; |
| 110 | 110 |
| 111 const Font& font = m_layoutListMarker.style()->font(); | 111 const Font& font = m_layoutListMarker.style()->font(); |
| 112 TextRun textRun = constructTextRun(font, m_layoutListMarker.text(), m_layout
ListMarker.styleRef()); | 112 TextRun textRun = constructTextRun(font, m_layoutListMarker.text(), m_layout
ListMarker.styleRef()); |
| 113 | 113 |
| 114 GraphicsContextStateSaver stateSaver(*context, false); | 114 GraphicsContextStateSaver stateSaver(context, false); |
| 115 if (!m_layoutListMarker.style()->isHorizontalWritingMode()) { | 115 if (!m_layoutListMarker.style()->isHorizontalWritingMode()) { |
| 116 marker.moveBy(roundedIntPoint(-boxOrigin)); | 116 marker.moveBy(roundedIntPoint(-boxOrigin)); |
| 117 marker = marker.transposedRect(); | 117 marker = marker.transposedRect(); |
| 118 marker.moveBy(IntPoint(roundToInt(box.x()), roundToInt(box.y() - m_layou
tListMarker.logicalHeight()))); | 118 marker.moveBy(IntPoint(roundToInt(box.x()), roundToInt(box.y() - m_layou
tListMarker.logicalHeight()))); |
| 119 stateSaver.save(); | 119 stateSaver.save(); |
| 120 context->translate(marker.x(), marker.maxY()); | 120 context.translate(marker.x(), marker.maxY()); |
| 121 context->rotate(static_cast<float>(deg2rad(90.))); | 121 context.rotate(static_cast<float>(deg2rad(90.))); |
| 122 context->translate(-marker.x(), -marker.maxY()); | 122 context.translate(-marker.x(), -marker.maxY()); |
| 123 } | 123 } |
| 124 | 124 |
| 125 TextRunPaintInfo textRunPaintInfo(textRun); | 125 TextRunPaintInfo textRunPaintInfo(textRun); |
| 126 textRunPaintInfo.bounds = marker; | 126 textRunPaintInfo.bounds = marker; |
| 127 IntPoint textOrigin = IntPoint(marker.x(), marker.y() + m_layoutListMarker.s
tyle()->fontMetrics().ascent()); | 127 IntPoint textOrigin = IntPoint(marker.x(), marker.y() + m_layoutListMarker.s
tyle()->fontMetrics().ascent()); |
| 128 | 128 |
| 129 // Text is not arbitrary. We can judge whether it's RTL from the first chara
cter, | 129 // Text is not arbitrary. We can judge whether it's RTL from the first chara
cter, |
| 130 // and we only need to handle the direction RightToLeft for now. | 130 // and we only need to handle the direction RightToLeft for now. |
| 131 bool textNeedsReversing = WTF::Unicode::direction(m_layoutListMarker.text()[
0]) == WTF::Unicode::RightToLeft; | 131 bool textNeedsReversing = WTF::Unicode::direction(m_layoutListMarker.text()[
0]) == WTF::Unicode::RightToLeft; |
| 132 StringBuilder reversedText; | 132 StringBuilder reversedText; |
| 133 if (textNeedsReversing) { | 133 if (textNeedsReversing) { |
| 134 unsigned length = m_layoutListMarker.text().length(); | 134 unsigned length = m_layoutListMarker.text().length(); |
| 135 reversedText.reserveCapacity(length); | 135 reversedText.reserveCapacity(length); |
| 136 for (int i = length - 1; i >= 0; --i) | 136 for (int i = length - 1; i >= 0; --i) |
| 137 reversedText.append(m_layoutListMarker.text()[i]); | 137 reversedText.append(m_layoutListMarker.text()[i]); |
| 138 ASSERT(reversedText.length() == length); | 138 ASSERT(reversedText.length() == length); |
| 139 textRun.setText(reversedText.toString()); | 139 textRun.setText(reversedText.toString()); |
| 140 } | 140 } |
| 141 | 141 |
| 142 const UChar suffix = ListMarkerText::suffix(listStyle, m_layoutListMarker.li
stItem()->value()); | 142 const UChar suffix = ListMarkerText::suffix(listStyle, m_layoutListMarker.li
stItem()->value()); |
| 143 UChar suffixStr[2] = { suffix, static_cast<UChar>(' ') }; | 143 UChar suffixStr[2] = { suffix, static_cast<UChar>(' ') }; |
| 144 TextRun suffixRun = constructTextRun(font, suffixStr, 2, m_layoutListMarker.
styleRef(), m_layoutListMarker.style()->direction()); | 144 TextRun suffixRun = constructTextRun(font, suffixStr, 2, m_layoutListMarker.
styleRef(), m_layoutListMarker.style()->direction()); |
| 145 TextRunPaintInfo suffixRunInfo(suffixRun); | 145 TextRunPaintInfo suffixRunInfo(suffixRun); |
| 146 suffixRunInfo.bounds = marker; | 146 suffixRunInfo.bounds = marker; |
| 147 | 147 |
| 148 if (m_layoutListMarker.style()->isLeftToRightDirection()) { | 148 if (m_layoutListMarker.style()->isLeftToRightDirection()) { |
| 149 context->drawText(font, textRunPaintInfo, textOrigin); | 149 context.drawText(font, textRunPaintInfo, textOrigin); |
| 150 context->drawText(font, suffixRunInfo, textOrigin + IntSize(font.width(t
extRun), 0)); | 150 context.drawText(font, suffixRunInfo, textOrigin + IntSize(font.width(te
xtRun), 0)); |
| 151 } else { | 151 } else { |
| 152 context->drawText(font, suffixRunInfo, textOrigin); | 152 context.drawText(font, suffixRunInfo, textOrigin); |
| 153 context->drawText(font, textRunPaintInfo, textOrigin + IntSize(font.widt
h(suffixRun), 0)); | 153 context.drawText(font, textRunPaintInfo, textOrigin + IntSize(font.width
(suffixRun), 0)); |
| 154 } | 154 } |
| 155 } | 155 } |
| 156 | 156 |
| 157 } // namespace blink | 157 } // namespace blink |
| OLD | NEW |