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/TextPainter.h" | 6 #include "core/paint/TextPainter.h" |
7 | 7 |
8 #include "core/CSSPropertyNames.h" | 8 #include "core/CSSPropertyNames.h" |
9 #include "core/frame/Settings.h" | 9 #include "core/frame/Settings.h" |
10 #include "core/layout/LayoutObject.h" | 10 #include "core/layout/LayoutObject.h" |
11 #include "core/layout/LayoutTextCombine.h" | 11 #include "core/layout/LayoutTextCombine.h" |
12 #include "core/layout/line/InlineTextBox.h" | 12 #include "core/layout/line/InlineTextBox.h" |
13 #include "core/paint/BoxPainter.h" | 13 #include "core/paint/BoxPainter.h" |
14 #include "core/paint/PaintInfo.h" | 14 #include "core/paint/PaintInfo.h" |
15 #include "core/style/ComputedStyle.h" | 15 #include "core/style/ComputedStyle.h" |
16 #include "core/style/ShadowList.h" | 16 #include "core/style/ShadowList.h" |
17 #include "platform/fonts/Font.h" | 17 #include "platform/fonts/Font.h" |
18 #include "platform/graphics/GraphicsContext.h" | 18 #include "platform/graphics/GraphicsContext.h" |
19 #include "platform/graphics/GraphicsContextStateSaver.h" | 19 #include "platform/graphics/GraphicsContextStateSaver.h" |
20 #include "platform/text/TextRun.h" | 20 #include "platform/text/TextRun.h" |
21 #include "wtf/Assertions.h" | 21 #include "wtf/Assertions.h" |
22 #include "wtf/text/CharacterNames.h" | 22 #include "wtf/text/CharacterNames.h" |
23 | 23 |
24 namespace blink { | 24 namespace blink { |
25 | 25 |
26 TextPainter::TextPainter(GraphicsContext* context, const Font& font, const TextR
un& run, const LayoutPoint& textOrigin, const LayoutRect& textBounds, bool horiz
ontal) | 26 TextPainter::TextPainter(GraphicsContext& context, const Font& font, const TextR
un& run, const LayoutPoint& textOrigin, const LayoutRect& textBounds, bool horiz
ontal) |
27 : m_graphicsContext(context) | 27 : m_graphicsContext(context) |
28 , m_font(font) | 28 , m_font(font) |
29 , m_run(run) | 29 , m_run(run) |
30 , m_textOrigin(textOrigin) | 30 , m_textOrigin(textOrigin) |
31 , m_textBounds(textBounds) | 31 , m_textBounds(textBounds) |
32 , m_horizontal(horizontal) | 32 , m_horizontal(horizontal) |
33 , m_emphasisMarkOffset(0) | 33 , m_emphasisMarkOffset(0) |
34 , m_combinedText(0) | 34 , m_combinedText(0) |
35 { | 35 { |
36 } | 36 } |
(...skipping 11 matching lines...) Expand all Loading... |
48 } else if (position == TextEmphasisPositionOver) { | 48 } else if (position == TextEmphasisPositionOver) { |
49 m_emphasisMarkOffset = -m_font.fontMetrics().ascent() - m_font.emphasisM
arkDescent(emphasisMark); | 49 m_emphasisMarkOffset = -m_font.fontMetrics().ascent() - m_font.emphasisM
arkDescent(emphasisMark); |
50 } else { | 50 } else { |
51 ASSERT(position == TextEmphasisPositionUnder); | 51 ASSERT(position == TextEmphasisPositionUnder); |
52 m_emphasisMarkOffset = m_font.fontMetrics().descent() + m_font.emphasisM
arkAscent(emphasisMark); | 52 m_emphasisMarkOffset = m_font.fontMetrics().descent() + m_font.emphasisM
arkAscent(emphasisMark); |
53 } | 53 } |
54 } | 54 } |
55 | 55 |
56 void TextPainter::paint(int startOffset, int endOffset, int length, const Style&
textStyle, TextBlobPtr* cachedTextBlob) | 56 void TextPainter::paint(int startOffset, int endOffset, int length, const Style&
textStyle, TextBlobPtr* cachedTextBlob) |
57 { | 57 { |
58 GraphicsContextStateSaver stateSaver(*m_graphicsContext, false); | 58 GraphicsContextStateSaver stateSaver(m_graphicsContext, false); |
59 updateGraphicsContext(textStyle, stateSaver); | 59 updateGraphicsContext(textStyle, stateSaver); |
60 if (m_combinedText) { | 60 if (m_combinedText) { |
61 m_graphicsContext->save(); | 61 m_graphicsContext.save(); |
62 m_combinedText->transformToInlineCoordinates(*m_graphicsContext, m_textB
ounds); | 62 m_combinedText->transformToInlineCoordinates(m_graphicsContext, m_textBo
unds); |
63 paintInternal<PaintText>(startOffset, endOffset, length, cachedTextBlob)
; | 63 paintInternal<PaintText>(startOffset, endOffset, length, cachedTextBlob)
; |
64 m_graphicsContext->restore(); | 64 m_graphicsContext.restore(); |
65 } else { | 65 } else { |
66 paintInternal<PaintText>(startOffset, endOffset, length, cachedTextBlob)
; | 66 paintInternal<PaintText>(startOffset, endOffset, length, cachedTextBlob)
; |
67 } | 67 } |
68 | 68 |
69 if (!m_emphasisMark.isEmpty()) { | 69 if (!m_emphasisMark.isEmpty()) { |
70 if (textStyle.emphasisMarkColor != textStyle.fillColor) | 70 if (textStyle.emphasisMarkColor != textStyle.fillColor) |
71 m_graphicsContext->setFillColor(textStyle.emphasisMarkColor); | 71 m_graphicsContext.setFillColor(textStyle.emphasisMarkColor); |
72 | 72 |
73 if (m_combinedText) | 73 if (m_combinedText) |
74 paintEmphasisMarkForCombinedText(); | 74 paintEmphasisMarkForCombinedText(); |
75 else | 75 else |
76 paintInternal<PaintEmphasisMark>(startOffset, endOffset, length); | 76 paintInternal<PaintEmphasisMark>(startOffset, endOffset, length); |
77 } | 77 } |
78 } | 78 } |
79 | 79 |
80 // static | 80 // static |
81 void TextPainter::updateGraphicsContext(GraphicsContext* context, const Style& t
extStyle, bool horizontal, GraphicsContextStateSaver& stateSaver) | 81 void TextPainter::updateGraphicsContext(GraphicsContext& context, const Style& t
extStyle, bool horizontal, GraphicsContextStateSaver& stateSaver) |
82 { | 82 { |
83 TextDrawingModeFlags mode = context->textDrawingMode(); | 83 TextDrawingModeFlags mode = context.textDrawingMode(); |
84 if (textStyle.strokeWidth > 0) { | 84 if (textStyle.strokeWidth > 0) { |
85 TextDrawingModeFlags newMode = mode | TextModeStroke; | 85 TextDrawingModeFlags newMode = mode | TextModeStroke; |
86 if (mode != newMode) { | 86 if (mode != newMode) { |
87 if (!stateSaver.saved()) | 87 if (!stateSaver.saved()) |
88 stateSaver.save(); | 88 stateSaver.save(); |
89 context->setTextDrawingMode(newMode); | 89 context.setTextDrawingMode(newMode); |
90 mode = newMode; | 90 mode = newMode; |
91 } | 91 } |
92 } | 92 } |
93 | 93 |
94 if (mode & TextModeFill && textStyle.fillColor != context->fillColor()) | 94 if (mode & TextModeFill && textStyle.fillColor != context.fillColor()) |
95 context->setFillColor(textStyle.fillColor); | 95 context.setFillColor(textStyle.fillColor); |
96 | 96 |
97 if (mode & TextModeStroke) { | 97 if (mode & TextModeStroke) { |
98 if (textStyle.strokeColor != context->strokeColor()) | 98 if (textStyle.strokeColor != context.strokeColor()) |
99 context->setStrokeColor(textStyle.strokeColor); | 99 context.setStrokeColor(textStyle.strokeColor); |
100 if (textStyle.strokeWidth != context->strokeThickness()) | 100 if (textStyle.strokeWidth != context.strokeThickness()) |
101 context->setStrokeThickness(textStyle.strokeWidth); | 101 context.setStrokeThickness(textStyle.strokeWidth); |
102 } | 102 } |
103 | 103 |
104 if (textStyle.shadow) { | 104 if (textStyle.shadow) { |
105 if (!stateSaver.saved()) | 105 if (!stateSaver.saved()) |
106 stateSaver.save(); | 106 stateSaver.save(); |
107 context->setDrawLooper(textStyle.shadow->createDrawLooper(DrawLooperBuil
der::ShadowIgnoresAlpha, textStyle.currentColor, horizontal)); | 107 context.setDrawLooper(textStyle.shadow->createDrawLooper(DrawLooperBuild
er::ShadowIgnoresAlpha, textStyle.currentColor, horizontal)); |
108 } | 108 } |
109 } | 109 } |
110 | 110 |
111 static Color textColorForWhiteBackground(Color textColor) | 111 static Color textColorForWhiteBackground(Color textColor) |
112 { | 112 { |
113 int distanceFromWhite = differenceSquared(textColor, Color::white); | 113 int distanceFromWhite = differenceSquared(textColor, Color::white); |
114 // semi-arbitrarily chose 65025 (255^2) value here after a few tests; | 114 // semi-arbitrarily chose 65025 (255^2) value here after a few tests; |
115 return distanceFromWhite > 65025 ? textColor : textColor.dark(); | 115 return distanceFromWhite > 65025 ? textColor : textColor.dark(); |
116 } | 116 } |
117 | 117 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 template <TextPainter::PaintInternalStep step> | 183 template <TextPainter::PaintInternalStep step> |
184 void TextPainter::paintInternalRun(TextRunPaintInfo& textRunPaintInfo, int from,
int to) | 184 void TextPainter::paintInternalRun(TextRunPaintInfo& textRunPaintInfo, int from,
int to) |
185 { | 185 { |
186 ASSERT(from <= textRunPaintInfo.run.length()); | 186 ASSERT(from <= textRunPaintInfo.run.length()); |
187 ASSERT(to <= textRunPaintInfo.run.length()); | 187 ASSERT(to <= textRunPaintInfo.run.length()); |
188 | 188 |
189 textRunPaintInfo.from = from; | 189 textRunPaintInfo.from = from; |
190 textRunPaintInfo.to = to; | 190 textRunPaintInfo.to = to; |
191 | 191 |
192 if (step == PaintEmphasisMark) { | 192 if (step == PaintEmphasisMark) { |
193 m_graphicsContext->drawEmphasisMarks(m_font, textRunPaintInfo, m_emphasi
sMark, | 193 m_graphicsContext.drawEmphasisMarks(m_font, textRunPaintInfo, m_emphasis
Mark, |
194 FloatPoint(m_textOrigin) + IntSize(0, m_emphasisMarkOffset)); | 194 FloatPoint(m_textOrigin) + IntSize(0, m_emphasisMarkOffset)); |
195 } else { | 195 } else { |
196 ASSERT(step == PaintText); | 196 ASSERT(step == PaintText); |
197 m_graphicsContext->drawText(m_font, textRunPaintInfo, FloatPoint(m_textO
rigin)); | 197 m_graphicsContext.drawText(m_font, textRunPaintInfo, FloatPoint(m_textOr
igin)); |
198 } | 198 } |
199 } | 199 } |
200 | 200 |
201 template <TextPainter::PaintInternalStep Step> | 201 template <TextPainter::PaintInternalStep Step> |
202 void TextPainter::paintInternal(int startOffset, int endOffset, int truncationPo
int, TextBlobPtr* cachedTextBlob) | 202 void TextPainter::paintInternal(int startOffset, int endOffset, int truncationPo
int, TextBlobPtr* cachedTextBlob) |
203 { | 203 { |
204 TextRunPaintInfo textRunPaintInfo(m_run); | 204 TextRunPaintInfo textRunPaintInfo(m_run); |
205 textRunPaintInfo.bounds = FloatRect(m_textBounds); | 205 textRunPaintInfo.bounds = FloatRect(m_textBounds); |
206 if (startOffset <= endOffset) { | 206 if (startOffset <= endOffset) { |
207 // FIXME: We should be able to use cachedTextBlob in more cases. | 207 // FIXME: We should be able to use cachedTextBlob in more cases. |
208 textRunPaintInfo.cachedTextBlob = cachedTextBlob; | 208 textRunPaintInfo.cachedTextBlob = cachedTextBlob; |
209 paintInternalRun<Step>(textRunPaintInfo, startOffset, endOffset); | 209 paintInternalRun<Step>(textRunPaintInfo, startOffset, endOffset); |
210 } else { | 210 } else { |
211 if (endOffset > 0) | 211 if (endOffset > 0) |
212 paintInternalRun<Step>(textRunPaintInfo, 0, endOffset); | 212 paintInternalRun<Step>(textRunPaintInfo, 0, endOffset); |
213 if (startOffset < truncationPoint) | 213 if (startOffset < truncationPoint) |
214 paintInternalRun<Step>(textRunPaintInfo, startOffset, truncationPoin
t); | 214 paintInternalRun<Step>(textRunPaintInfo, startOffset, truncationPoin
t); |
215 } | 215 } |
216 } | 216 } |
217 | 217 |
218 void TextPainter::paintEmphasisMarkForCombinedText() | 218 void TextPainter::paintEmphasisMarkForCombinedText() |
219 { | 219 { |
220 ASSERT(m_combinedText); | 220 ASSERT(m_combinedText); |
221 DEFINE_STATIC_LOCAL(TextRun, placeholderTextRun, (&ideographicFullStopCharac
ter, 1)); | 221 DEFINE_STATIC_LOCAL(TextRun, placeholderTextRun, (&ideographicFullStopCharac
ter, 1)); |
222 FloatPoint emphasisMarkTextOrigin(m_textBounds.x().toFloat(), m_textBounds.y
().toFloat() + m_font.fontMetrics().ascent() + m_emphasisMarkOffset); | 222 FloatPoint emphasisMarkTextOrigin(m_textBounds.x().toFloat(), m_textBounds.y
().toFloat() + m_font.fontMetrics().ascent() + m_emphasisMarkOffset); |
223 TextRunPaintInfo textRunPaintInfo(placeholderTextRun); | 223 TextRunPaintInfo textRunPaintInfo(placeholderTextRun); |
224 textRunPaintInfo.bounds = FloatRect(m_textBounds); | 224 textRunPaintInfo.bounds = FloatRect(m_textBounds); |
225 m_graphicsContext->concatCTM(rotation(m_textBounds, Clockwise)); | 225 m_graphicsContext.concatCTM(rotation(m_textBounds, Clockwise)); |
226 m_graphicsContext->drawEmphasisMarks(m_combinedText->originalFont(), textRun
PaintInfo, m_emphasisMark, emphasisMarkTextOrigin); | 226 m_graphicsContext.drawEmphasisMarks(m_combinedText->originalFont(), textRunP
aintInfo, m_emphasisMark, emphasisMarkTextOrigin); |
227 m_graphicsContext->concatCTM(rotation(m_textBounds, Counterclockwise)); | 227 m_graphicsContext.concatCTM(rotation(m_textBounds, Counterclockwise)); |
228 } | 228 } |
229 | 229 |
230 } // namespace blink | 230 } // namespace blink |
OLD | NEW |