| Index: Source/core/rendering/TextPainter.cpp
|
| diff --git a/Source/core/rendering/TextPainter.cpp b/Source/core/rendering/TextPainter.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..724bfd40e08cfb73a176ae714b49bde12b390877
|
| --- /dev/null
|
| +++ b/Source/core/rendering/TextPainter.cpp
|
| @@ -0,0 +1,138 @@
|
| +// 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/rendering/TextPainter.h"
|
| +
|
| +#include "core/rendering/InlineTextBox.h"
|
| +#include "core/rendering/RenderCombineText.h"
|
| +#include "core/rendering/style/ShadowList.h"
|
| +#include "platform/fonts/Font.h"
|
| +#include "platform/graphics/GraphicsContext.h"
|
| +#include "platform/graphics/GraphicsContextStateSaver.h"
|
| +#include "platform/text/TextRun.h"
|
| +#include "wtf/Assertions.h"
|
| +#include "wtf/unicode/CharacterNames.h"
|
| +
|
| +namespace blink {
|
| +
|
| +TextPainter::TextPainter(GraphicsContext* context, const Font& font, const TextRun& run, const FloatPoint& textOrigin, const FloatRect& textBounds, bool horizontal)
|
| + : m_graphicsContext(context)
|
| + , m_font(font)
|
| + , m_run(run)
|
| + , m_textOrigin(textOrigin)
|
| + , m_textBounds(textBounds)
|
| + , m_horizontal(horizontal)
|
| + , m_emphasisMarkOffset(0)
|
| + , m_combinedText(0)
|
| +{
|
| +}
|
| +
|
| +TextPainter::~TextPainter()
|
| +{
|
| +}
|
| +
|
| +void TextPainter::setEmphasisMark(const AtomicString& emphasisMark, TextEmphasisPosition position)
|
| +{
|
| + m_emphasisMark = emphasisMark;
|
| +
|
| + if (emphasisMark.isNull()) {
|
| + m_emphasisMarkOffset = 0;
|
| + } else if (position == TextEmphasisPositionOver) {
|
| + m_emphasisMarkOffset = -m_font.fontMetrics().ascent() - m_font.emphasisMarkDescent(emphasisMark);
|
| + } else {
|
| + ASSERT(position == TextEmphasisPositionUnder);
|
| + m_emphasisMarkOffset = m_font.fontMetrics().descent() + m_font.emphasisMarkAscent(emphasisMark);
|
| + }
|
| +}
|
| +
|
| +void TextPainter::paint(int startOffset, int endOffset, int length, const Style& textStyle)
|
| +{
|
| + GraphicsContextStateSaver stateSaver(*m_graphicsContext, false);
|
| + updateGraphicsContext(textStyle, stateSaver);
|
| + paintInternal<PaintText>(startOffset, endOffset, length);
|
| +
|
| + if (!m_emphasisMark.isEmpty()) {
|
| + if (textStyle.emphasisMarkColor != textStyle.fillColor)
|
| + m_graphicsContext->setFillColor(textStyle.emphasisMarkColor);
|
| +
|
| + if (m_combinedText)
|
| + paintEmphasisMarkForCombinedText();
|
| + else
|
| + paintInternal<PaintEmphasisMark>(startOffset, endOffset, length);
|
| + }
|
| +}
|
| +
|
| +// static
|
| +void TextPainter::updateGraphicsContext(GraphicsContext* context, const Style& textStyle, bool horizontal, GraphicsContextStateSaver& stateSaver)
|
| +{
|
| + TextDrawingModeFlags mode = context->textDrawingMode();
|
| + if (textStyle.strokeWidth > 0) {
|
| + TextDrawingModeFlags newMode = mode | TextModeStroke;
|
| + if (mode != newMode) {
|
| + if (!stateSaver.saved())
|
| + stateSaver.save();
|
| + context->setTextDrawingMode(newMode);
|
| + mode = newMode;
|
| + }
|
| + }
|
| +
|
| + if (mode & TextModeFill && textStyle.fillColor != context->fillColor())
|
| + context->setFillColor(textStyle.fillColor);
|
| +
|
| + if (mode & TextModeStroke) {
|
| + if (textStyle.strokeColor != context->strokeColor())
|
| + context->setStrokeColor(textStyle.strokeColor);
|
| + if (textStyle.strokeWidth != context->strokeThickness())
|
| + context->setStrokeThickness(textStyle.strokeWidth);
|
| + }
|
| +
|
| + // Text shadows are disabled when printing. http://crbug.com/258321
|
| + if (textStyle.shadow && !context->printing()) {
|
| + if (!stateSaver.saved())
|
| + stateSaver.save();
|
| + context->setDrawLooper(textStyle.shadow->createDrawLooper(DrawLooperBuilder::ShadowIgnoresAlpha, horizontal));
|
| + }
|
| +}
|
| +
|
| +template <TextPainter::PaintInternalStep step>
|
| +void TextPainter::paintInternalRun(TextRunPaintInfo& textRunPaintInfo, int from, int to)
|
| +{
|
| + textRunPaintInfo.from = from;
|
| + textRunPaintInfo.to = to;
|
| + if (step == PaintEmphasisMark)
|
| + m_graphicsContext->drawEmphasisMarks(m_font, textRunPaintInfo, m_emphasisMark, m_textOrigin + IntSize(0, m_emphasisMarkOffset));
|
| + else
|
| + m_graphicsContext->drawText(m_font, textRunPaintInfo, m_textOrigin);
|
| +
|
| +}
|
| +
|
| +template <TextPainter::PaintInternalStep Step>
|
| +void TextPainter::paintInternal(int startOffset, int endOffset, int truncationPoint)
|
| +{
|
| + TextRunPaintInfo textRunPaintInfo(m_run);
|
| + textRunPaintInfo.bounds = m_textBounds;
|
| + if (startOffset <= endOffset) {
|
| + paintInternalRun<Step>(textRunPaintInfo, startOffset, endOffset);
|
| + } else {
|
| + if (endOffset > 0)
|
| + paintInternalRun<Step>(textRunPaintInfo, 0, endOffset);
|
| + if (startOffset < truncationPoint)
|
| + paintInternalRun<Step>(textRunPaintInfo, startOffset, truncationPoint);
|
| + }
|
| +}
|
| +
|
| +void TextPainter::paintEmphasisMarkForCombinedText()
|
| +{
|
| + ASSERT(m_combinedText);
|
| + DEFINE_STATIC_LOCAL(TextRun, objectReplacementCharacterTextRun, (&objectReplacementCharacter, 1));
|
| + FloatPoint emphasisMarkTextOrigin(m_textBounds.x() + m_textBounds.width() / 2, m_textBounds.y() + m_font.fontMetrics().ascent() + m_emphasisMarkOffset);
|
| + TextRunPaintInfo textRunPaintInfo(objectReplacementCharacterTextRun);
|
| + textRunPaintInfo.bounds = m_textBounds;
|
| + m_graphicsContext->concatCTM(InlineTextBox::rotation(m_textBounds, InlineTextBox::Clockwise));
|
| + m_graphicsContext->drawEmphasisMarks(m_combinedText->originalFont(), textRunPaintInfo, m_emphasisMark, emphasisMarkTextOrigin);
|
| + m_graphicsContext->concatCTM(InlineTextBox::rotation(m_textBounds, InlineTextBox::Counterclockwise));
|
| +}
|
| +
|
| +} // namespace blink
|
|
|