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 |