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.
8 #include "core/CoreExport.h"
9 #include "core/style/ComputedStyleConstants.h"
10 #include "platform/fonts/TextBlob.h"
11 #include "platform/geometry/FloatPoint.h"
12 #include "platform/geometry/FloatRect.h"
13 #include "platform/geometry/LayoutRect.h"
14 #include "platform/graphics/Color.h"
15 #include "platform/transforms/AffineTransform.h"
16 #include "wtf/Allocator.h"
17 #include "wtf/text/AtomicString.h"
23 class GraphicsContext
;
24 class GraphicsContextStateSaver
;
25 class LayoutTextCombine
;
30 struct TextRunPaintInfo
;
32 class CORE_EXPORT TextPainter
{
37 TextPainter(GraphicsContext
*, const Font
&, const TextRun
&, const LayoutPoint
& textOrigin
, const LayoutRect
& textBounds
, bool horizontal
);
40 void setEmphasisMark(const AtomicString
&, TextEmphasisPosition
);
41 void setCombinedText(LayoutTextCombine
* combinedText
) { m_combinedText
= combinedText
; }
43 static void updateGraphicsContext(GraphicsContext
*, const Style
&, bool horizontal
, GraphicsContextStateSaver
&);
45 void paint(int startOffset
, int endOffset
, int length
, const Style
&, TextBlobPtr
* cachedTextBlob
= 0);
52 Color emphasisMarkColor
;
54 const ShadowList
* shadow
;
56 bool operator==(const Style
& other
)
58 return currentColor
== other
.currentColor
59 && fillColor
== other
.fillColor
60 && strokeColor
== other
.strokeColor
61 && emphasisMarkColor
== other
.emphasisMarkColor
62 && strokeWidth
== other
.strokeWidth
63 && shadow
== other
.shadow
;
65 bool operator!=(const Style
& other
) { return !(*this == other
); }
67 static Style
textPaintingStyle(LayoutObject
&, const ComputedStyle
&, const PaintInfo
&);
68 static Style
selectionPaintingStyle(LayoutObject
&, bool haveSelection
, const PaintInfo
&, const Style
& textStyle
);
70 enum RotationDirection
{ Counterclockwise
, Clockwise
};
71 static AffineTransform
rotation(const LayoutRect
& boxRect
, RotationDirection
);
74 void updateGraphicsContext(const Style
& style
, GraphicsContextStateSaver
& saver
)
76 updateGraphicsContext(m_graphicsContext
, style
, m_horizontal
, saver
);
79 enum PaintInternalStep
{ PaintText
, PaintEmphasisMark
};
81 template <PaintInternalStep step
>
82 void paintInternalRun(TextRunPaintInfo
&, int from
, int to
);
84 template <PaintInternalStep step
>
85 void paintInternal(int startOffset
, int endOffset
, int truncationPoint
, TextBlobPtr
* cachedTextBlob
= 0);
87 void paintEmphasisMarkForCombinedText();
89 GraphicsContext
* m_graphicsContext
;
92 LayoutPoint m_textOrigin
;
93 LayoutRect m_textBounds
;
95 AtomicString m_emphasisMark
;
96 int m_emphasisMarkOffset
;
97 LayoutTextCombine
* m_combinedText
;
100 inline AffineTransform
TextPainter::rotation(const LayoutRect
& boxRect
, RotationDirection rotationDirection
)
102 // Why this matrix is correct: consider the case of a clockwise rotation.
104 // Let the corner points that define |boxRect| be ABCD, where A is top-left and B is bottom-left.
106 // 1. We want B to end up at the same pixel position after rotation as A is before rotation.
107 // 2. Before rotation, B is at (x(), maxY())
108 // 3. Rotating clockwise by 90 degrees places B at the coordinates (-maxY(), x()).
109 // 4. Point A before rotation is at (x(), y())
110 // 5. Therefore the translation from (3) to (4) is (x(), y()) - (-maxY(), x()) = (x() + maxY(), y() - x())
112 // A similar argument derives the counter-clockwise case.
113 return rotationDirection
== Clockwise
? AffineTransform(0, 1, -1, 0, boxRect
.x() + boxRect
.maxY(), boxRect
.y() - boxRect
.x())
114 : AffineTransform(0, -1, 1, 0, boxRect
.x() - boxRect
.y(), boxRect
.x() + boxRect
.maxY());
119 #endif // TextPainter_h