e4b5b18ccf3ca2613340e0ea4ddadb1bf950bf12
[WebKit-https.git] / Source / WebCore / rendering / TextPainter.h
1 /*
2  * (C) 1999 Lars Knoll (knoll@kde.org)
3  * (C) 2000 Dirk Mueller (mueller@kde.org)
4  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #ifndef TextPainter_h
24 #define TextPainter_h
25
26 #include "AffineTransform.h"
27 #include "FloatRect.h"
28 #include "ShadowData.h"
29 #include "TextFlags.h"
30 #include "TextPaintStyle.h"
31 #include <wtf/text/AtomicString.h>
32
33 namespace WebCore {
34
35 class FontCascade;
36 class RenderCombineText;
37 class TextRun;
38
39 struct TextPaintStyle;
40
41 enum RotationDirection { Counterclockwise, Clockwise };
42
43 static inline AffineTransform rotation(const FloatRect& boxRect, RotationDirection clockwise)
44 {
45     return clockwise ? AffineTransform(0, 1, -1, 0, boxRect.x() + boxRect.maxY(), boxRect.maxY() - boxRect.x())
46         : AffineTransform(0, -1, 1, 0, boxRect.x() - boxRect.maxY(), boxRect.x() + boxRect.maxY());
47 }
48
49 class TextPainter {
50 public:
51     TextPainter(GraphicsContext&);
52     
53     void setTextPaintStyle(const TextPaintStyle& textPaintStyle) { m_textPaintStyle = textPaintStyle; }
54     void setSelectionPaintStyle(const TextPaintStyle& selectionPaintStyle) { m_selectionPaintStyle = selectionPaintStyle; }
55     void setIsHorizontal(bool isHorizontal) { m_textBoxIsHorizontal = isHorizontal; }
56     void setFont(const FontCascade& font) { m_font = &font; }
57     void addEmphasis(const AtomicString& emphasisMark, int emphasisMarkOffset, RenderCombineText*);
58     void addTextShadow(const ShadowData* textShadow, const ShadowData* selectionShadow);
59
60     void paintText(const TextRun&, int length, const FloatRect& boxRect, const FloatPoint& textOrigin,
61         int selectionStart = 0, int selectionEnd = 0, bool paintSelectedTextOnly = false, bool paintSelectedTextSeparately = false);
62
63 private:
64     void drawTextOrEmphasisMarks(const FontCascade&, const TextRun&, const AtomicString& emphasisMark, int emphasisMarkOffset,
65         const FloatPoint& textOrigin, int startOffset, int endOffset);
66     void paintTextWithShadows(const ShadowData*, const FontCascade&, const TextRun&, const FloatRect& boxRect, const FloatPoint& textOrigin,
67         int startOffset, int endOffset, const AtomicString& emphasisMark, int emphasisMarkOffset, bool stroked);
68     void paintTextAndEmphasisMarksIfNeeded(const TextRun&, const FloatRect& boxRect, const FloatPoint& textOrigin, int startOffset, int endOffset,
69         const TextPaintStyle&, const ShadowData*);
70
71     GraphicsContext& m_context;
72     const FontCascade* m_font { nullptr };
73     TextPaintStyle m_textPaintStyle;
74     TextPaintStyle m_selectionPaintStyle;
75     const ShadowData* m_textShadow { nullptr };
76     const ShadowData* m_selectionShadow { nullptr };
77     AtomicString m_emphasisMark;
78     RenderCombineText* m_combinedText { nullptr };
79     int m_emphasisMarkOffset { 0 };
80     bool m_textBoxIsHorizontal { true };
81 };
82
83 inline void TextPainter::addEmphasis(const AtomicString& emphasisMark, int emphasisMarkOffset, RenderCombineText* combinedText)
84 {
85     m_emphasisMark = emphasisMark;
86     m_emphasisMarkOffset = emphasisMarkOffset;
87     m_combinedText = combinedText;
88 }
89
90 inline void TextPainter::addTextShadow(const ShadowData* textShadow, const ShadowData* selectionShadow)
91 {
92     m_textShadow = textShadow;
93     m_selectionShadow = selectionShadow;
94 }
95
96 class ShadowApplier {
97 public:
98     ShadowApplier(GraphicsContext&, const ShadowData*, const FloatRect& textRect, bool lastShadowIterationShouldDrawText = true, bool opaque = false, FontOrientation = Horizontal);
99     FloatSize extraOffset() const { return m_extraOffset; }
100     bool nothingToDraw() const { return m_nothingToDraw; }
101     bool didSaveContext() const { return m_didSaveContext; }
102     ~ShadowApplier();
103
104 private:
105     bool isLastShadowIteration();
106     bool shadowIsCompletelyCoveredByText(bool textIsOpaque);
107
108     FloatSize m_extraOffset;
109     GraphicsContext& m_context;
110     const ShadowData* m_shadow;
111     bool m_onlyDrawsShadow : 1;
112     bool m_avoidDrawingShadow : 1;
113     bool m_nothingToDraw : 1;
114     bool m_didSaveContext : 1;
115 };
116
117 inline bool ShadowApplier::isLastShadowIteration()
118 {
119     return m_shadow && !m_shadow->next();
120 }
121
122 inline bool ShadowApplier::shadowIsCompletelyCoveredByText(bool textIsOpaque)
123 {
124     return textIsOpaque && m_shadow && m_shadow->location() == IntPoint() && !m_shadow->radius();
125 }
126
127 } // namespace WebCore
128
129 #endif // TextPainter_h