OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "config.h" |
| 6 #include "core/rendering/TextPainter.h" |
| 7 |
| 8 #include "core/rendering/InlineTextBox.h" |
| 9 #include "core/rendering/RenderCombineText.h" |
| 10 #include "core/rendering/style/ShadowList.h" |
| 11 #include "platform/fonts/Font.h" |
| 12 #include "platform/graphics/GraphicsContext.h" |
| 13 #include "platform/graphics/GraphicsContextStateSaver.h" |
| 14 #include "platform/text/TextRun.h" |
| 15 #include "wtf/Assertions.h" |
| 16 #include "wtf/unicode/CharacterNames.h" |
| 17 |
| 18 namespace blink { |
| 19 |
| 20 TextPainter::TextPainter(GraphicsContext* context, const Font& font, const TextR
un& run, const FloatPoint& textOrigin, const FloatRect& textBounds, bool horizon
tal) |
| 21 : m_graphicsContext(context) |
| 22 , m_font(font) |
| 23 , m_run(run) |
| 24 , m_textOrigin(textOrigin) |
| 25 , m_textBounds(textBounds) |
| 26 , m_horizontal(horizontal) |
| 27 , m_emphasisMarkOffset(0) |
| 28 , m_combinedText(0) |
| 29 { |
| 30 } |
| 31 |
| 32 TextPainter::~TextPainter() |
| 33 { |
| 34 } |
| 35 |
| 36 void TextPainter::setEmphasisMark(const AtomicString& emphasisMark, TextEmphasis
Position position) |
| 37 { |
| 38 m_emphasisMark = emphasisMark; |
| 39 |
| 40 if (emphasisMark.isNull()) { |
| 41 m_emphasisMarkOffset = 0; |
| 42 } else if (position == TextEmphasisPositionOver) { |
| 43 m_emphasisMarkOffset = -m_font.fontMetrics().ascent() - m_font.emphasisM
arkDescent(emphasisMark); |
| 44 } else { |
| 45 ASSERT(position == TextEmphasisPositionUnder); |
| 46 m_emphasisMarkOffset = m_font.fontMetrics().descent() + m_font.emphasisM
arkAscent(emphasisMark); |
| 47 } |
| 48 } |
| 49 |
| 50 void TextPainter::paint(int startOffset, int endOffset, int length, const Style&
textStyle) |
| 51 { |
| 52 GraphicsContextStateSaver stateSaver(*m_graphicsContext, false); |
| 53 updateGraphicsContext(textStyle, stateSaver); |
| 54 paintInternal<PaintText>(startOffset, endOffset, length); |
| 55 |
| 56 if (!m_emphasisMark.isEmpty()) { |
| 57 if (textStyle.emphasisMarkColor != textStyle.fillColor) |
| 58 m_graphicsContext->setFillColor(textStyle.emphasisMarkColor); |
| 59 |
| 60 if (m_combinedText) |
| 61 paintEmphasisMarkForCombinedText(); |
| 62 else |
| 63 paintInternal<PaintEmphasisMark>(startOffset, endOffset, length); |
| 64 } |
| 65 } |
| 66 |
| 67 // static |
| 68 void TextPainter::updateGraphicsContext(GraphicsContext* context, const Style& t
extStyle, bool horizontal, GraphicsContextStateSaver& stateSaver) |
| 69 { |
| 70 TextDrawingModeFlags mode = context->textDrawingMode(); |
| 71 if (textStyle.strokeWidth > 0) { |
| 72 TextDrawingModeFlags newMode = mode | TextModeStroke; |
| 73 if (mode != newMode) { |
| 74 if (!stateSaver.saved()) |
| 75 stateSaver.save(); |
| 76 context->setTextDrawingMode(newMode); |
| 77 mode = newMode; |
| 78 } |
| 79 } |
| 80 |
| 81 if (mode & TextModeFill && textStyle.fillColor != context->fillColor()) |
| 82 context->setFillColor(textStyle.fillColor); |
| 83 |
| 84 if (mode & TextModeStroke) { |
| 85 if (textStyle.strokeColor != context->strokeColor()) |
| 86 context->setStrokeColor(textStyle.strokeColor); |
| 87 if (textStyle.strokeWidth != context->strokeThickness()) |
| 88 context->setStrokeThickness(textStyle.strokeWidth); |
| 89 } |
| 90 |
| 91 // Text shadows are disabled when printing. http://crbug.com/258321 |
| 92 if (textStyle.shadow && !context->printing()) { |
| 93 if (!stateSaver.saved()) |
| 94 stateSaver.save(); |
| 95 context->setDrawLooper(textStyle.shadow->createDrawLooper(DrawLooperBuil
der::ShadowIgnoresAlpha, horizontal)); |
| 96 } |
| 97 } |
| 98 |
| 99 template <TextPainter::PaintInternalStep step> |
| 100 void TextPainter::paintInternalRun(TextRunPaintInfo& textRunPaintInfo, int from,
int to) |
| 101 { |
| 102 textRunPaintInfo.from = from; |
| 103 textRunPaintInfo.to = to; |
| 104 if (step == PaintEmphasisMark) |
| 105 m_graphicsContext->drawEmphasisMarks(m_font, textRunPaintInfo, m_emphasi
sMark, m_textOrigin + IntSize(0, m_emphasisMarkOffset)); |
| 106 else |
| 107 m_graphicsContext->drawText(m_font, textRunPaintInfo, m_textOrigin); |
| 108 |
| 109 } |
| 110 |
| 111 template <TextPainter::PaintInternalStep Step> |
| 112 void TextPainter::paintInternal(int startOffset, int endOffset, int truncationPo
int) |
| 113 { |
| 114 TextRunPaintInfo textRunPaintInfo(m_run); |
| 115 textRunPaintInfo.bounds = m_textBounds; |
| 116 if (startOffset <= endOffset) { |
| 117 paintInternalRun<Step>(textRunPaintInfo, startOffset, endOffset); |
| 118 } else { |
| 119 if (endOffset > 0) |
| 120 paintInternalRun<Step>(textRunPaintInfo, 0, endOffset); |
| 121 if (startOffset < truncationPoint) |
| 122 paintInternalRun<Step>(textRunPaintInfo, startOffset, truncationPoin
t); |
| 123 } |
| 124 } |
| 125 |
| 126 void TextPainter::paintEmphasisMarkForCombinedText() |
| 127 { |
| 128 ASSERT(m_combinedText); |
| 129 DEFINE_STATIC_LOCAL(TextRun, objectReplacementCharacterTextRun, (&objectRepl
acementCharacter, 1)); |
| 130 FloatPoint emphasisMarkTextOrigin(m_textBounds.x() + m_textBounds.width() /
2, m_textBounds.y() + m_font.fontMetrics().ascent() + m_emphasisMarkOffset); |
| 131 TextRunPaintInfo textRunPaintInfo(objectReplacementCharacterTextRun); |
| 132 textRunPaintInfo.bounds = m_textBounds; |
| 133 m_graphicsContext->concatCTM(InlineTextBox::rotation(m_textBounds, InlineTex
tBox::Clockwise)); |
| 134 m_graphicsContext->drawEmphasisMarks(m_combinedText->originalFont(), textRun
PaintInfo, m_emphasisMark, emphasisMarkTextOrigin); |
| 135 m_graphicsContext->concatCTM(InlineTextBox::rotation(m_textBounds, InlineTex
tBox::Counterclockwise)); |
| 136 } |
| 137 |
| 138 } // namespace blink |
OLD | NEW |