1// Copyright (c) 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 "platform/graphics/GraphicsContextState.h"
7
8#include "platform/graphics/skia/SkiaUtils.h"
9
10namespace blink {
11
12GraphicsContextState::GraphicsContextState()
13    : m_strokeColor(Color::black)
14    , m_fillColor(Color::black)
15    , m_fillRule(RULE_NONZERO)
16    , m_textDrawingMode(TextModeFill)
17    , m_alpha(256)
18    , m_compositeOperator(CompositeSourceOver)
19    , m_blendMode(WebBlendModeNormal)
20    , m_interpolationQuality(InterpolationDefault)
21    , m_saveCount(0)
22    , m_shouldAntialias(true)
23    , m_shouldClampToSourceRect(true)
24{
25    m_strokePaint.setStyle(SkPaint::kStroke_Style);
26    m_strokePaint.setStrokeWidth(SkFloatToScalar(m_strokeData.thickness()));
27    m_strokePaint.setColor(applyAlpha(m_strokeColor.rgb()));
28    m_strokePaint.setStrokeCap(SkPaint::kDefault_Cap);
29    m_strokePaint.setStrokeJoin(SkPaint::kDefault_Join);
30    m_strokePaint.setStrokeMiter(SkFloatToScalar(m_strokeData.miterLimit()));
31    m_strokePaint.setFilterLevel(WebCoreInterpolationQualityToSkFilterLevel(m_interpolationQuality));
32    m_strokePaint.setAntiAlias(m_shouldAntialias);
33    m_fillPaint.setColor(applyAlpha(m_fillColor.rgb()));
34    m_fillPaint.setFilterLevel(WebCoreInterpolationQualityToSkFilterLevel(m_interpolationQuality));
35    m_fillPaint.setAntiAlias(m_shouldAntialias);
36}
37
38GraphicsContextState::GraphicsContextState(const GraphicsContextState& other)
39    : m_strokePaint(other.m_strokePaint)
40    , m_fillPaint(other.m_fillPaint)
41    , m_strokeData(other.m_strokeData)
42    , m_strokeColor(other.m_strokeColor)
43    , m_strokeGradient(other.m_strokeGradient)
44    , m_strokePattern(other.m_strokePattern)
45    , m_fillColor(other.m_fillColor)
46    , m_fillRule(other.m_fillRule)
47    , m_fillGradient(other.m_fillGradient)
48    , m_fillPattern(other.m_fillPattern)
49    , m_looper(other.m_looper)
50    , m_textDrawingMode(other.m_textDrawingMode)
51    , m_alpha(other.m_alpha)
52    , m_colorFilter(other.m_colorFilter)
53    , m_compositeOperator(other.m_compositeOperator)
54    , m_blendMode(other.m_blendMode)
55    , m_interpolationQuality(other.m_interpolationQuality)
56    , m_saveCount(0)
57    , m_shouldAntialias(other.m_shouldAntialias)
58    , m_shouldClampToSourceRect(other.m_shouldClampToSourceRect) { }
59
60void GraphicsContextState::copy(const GraphicsContextState& source)
61{
62    this->~GraphicsContextState();
63    new (this) GraphicsContextState(source);
64}
65
66const SkPaint& GraphicsContextState::strokePaint(int strokedPathLength) const
67{
68    if (m_strokeGradient && m_strokeGradient->shaderChanged())
69        m_strokePaint.setShader(m_strokeGradient->shader());
70    m_strokeData.setupPaintDashPathEffect(&m_strokePaint, strokedPathLength);
71    return m_strokePaint;
72}
73
74const SkPaint& GraphicsContextState::fillPaint() const
75{
76    if (m_fillGradient && m_fillGradient->shaderChanged())
77        m_fillPaint.setShader(m_fillGradient->shader());
78    return m_fillPaint;
79}
80
81void GraphicsContextState::setStrokeStyle(StrokeStyle style)
82{
83    m_strokeData.setStyle(style);
84}
85
86void GraphicsContextState::setStrokeThickness(float thickness)
87{
88    m_strokeData.setThickness(thickness);
89    m_strokePaint.setStrokeWidth(SkFloatToScalar(thickness));
90}
91
92void GraphicsContextState::setStrokeColor(const Color& color)
93{
94    m_strokeGradient.clear();
95    m_strokePattern.clear();
96    m_strokeColor = color;
97    m_strokePaint.setColor(applyAlpha(color.rgb()));
98    m_strokePaint.setShader(0);
99}
100
101void GraphicsContextState::setStrokeGradient(const PassRefPtr<Gradient> gradient)
102{
103    m_strokeColor = Color::black;
104    m_strokePattern.clear();
105    m_strokeGradient = gradient;
106    m_strokePaint.setColor(applyAlpha(SK_ColorBLACK));
107    m_strokePaint.setShader(m_strokeGradient->shader());
108}
109
110void GraphicsContextState::clearStrokeGradient()
111{
112    m_strokeGradient.clear();
113    ASSERT(!m_strokePattern);
114    m_strokePaint.setColor(applyAlpha(m_strokeColor.rgb()));
115}
116
117void GraphicsContextState::setStrokePattern(const PassRefPtr<Pattern> pattern)
118{
119    m_strokeColor = Color::black;
120    m_strokeGradient.clear();
121    m_strokePattern = pattern;
122    m_strokePaint.setColor(applyAlpha(SK_ColorBLACK));
123    m_strokePaint.setShader(m_strokePattern->shader());
124}
125
126void GraphicsContextState::clearStrokePattern()
127{
128    m_strokePattern.clear();
129    ASSERT(!m_strokeGradient);
130    m_strokePaint.setColor(applyAlpha(m_strokeColor.rgb()));
131}
132
133void GraphicsContextState::setLineCap(LineCap cap)
134{
135    m_strokeData.setLineCap(cap);
136    m_strokePaint.setStrokeCap((SkPaint::Cap)cap);
137}
138
139void GraphicsContextState::setLineJoin(LineJoin join)
140{
141    m_strokeData.setLineJoin(join);
142    m_strokePaint.setStrokeJoin((SkPaint::Join)join);
143}
144
145void GraphicsContextState::setMiterLimit(float miterLimit)
146{
147    m_strokeData.setMiterLimit(miterLimit);
148    m_strokePaint.setStrokeMiter(SkFloatToScalar(miterLimit));
149}
150
151void GraphicsContextState::setFillColor(const Color& color)
152{
153    m_fillColor = color;
154    m_fillGradient.clear();
155    m_fillPattern.clear();
156    m_fillPaint.setColor(applyAlpha(color.rgb()));
157    m_fillPaint.setShader(0);
158}
159
160void GraphicsContextState::setFillGradient(const PassRefPtr<Gradient> gradient)
161{
162    m_fillColor = Color::black;
163    m_fillPattern.clear();
164    m_fillGradient = gradient;
165    m_fillPaint.setColor(applyAlpha(SK_ColorBLACK));
166    m_fillPaint.setShader(m_fillGradient->shader());
167}
168
169void GraphicsContextState::clearFillGradient()
170{
171    m_fillGradient.clear();
172    ASSERT(!m_fillPattern);
173    m_fillPaint.setColor(applyAlpha(m_fillColor.rgb()));
174}
175
176void GraphicsContextState::setFillPattern(const PassRefPtr<Pattern> pattern)
177{
178    m_fillColor = Color::black;
179    m_fillGradient.clear();
180    m_fillPattern = pattern;
181    m_fillPaint.setColor(applyAlpha(SK_ColorBLACK));
182    m_fillPaint.setShader(m_fillPattern->shader());
183}
184
185void GraphicsContextState::clearFillPattern()
186{
187    m_fillPattern.clear();
188    ASSERT(!m_fillGradient);
189    m_fillPaint.setColor(applyAlpha(m_fillColor.rgb()));
190}
191
192// Shadow. (This will need tweaking if we use draw loopers for other things.)
193void GraphicsContextState::setDrawLooper(PassRefPtr<SkDrawLooper> drawLooper)
194{
195    m_looper = drawLooper;
196    m_strokePaint.setLooper(m_looper.get());
197    m_fillPaint.setLooper(m_looper.get());
198}
199
200void GraphicsContextState::clearDrawLooper()
201{
202    m_looper.clear();
203    m_strokePaint.setLooper(0);
204    m_fillPaint.setLooper(0);
205}
206
207void GraphicsContextState::setAlphaAsFloat(float alpha)
208{
209    if (alpha < 0) {
210        m_alpha = 0;
211    } else {
212        m_alpha = roundf(alpha * 256);
213        if (m_alpha > 256)
214            m_alpha = 256;
215    }
216    m_strokePaint.setColor(applyAlpha(m_strokeColor.rgb()));
217    m_fillPaint.setColor(applyAlpha(m_fillColor.rgb()));
218}
219
220void GraphicsContextState::setLineDash(const DashArray& dashes, float dashOffset)
221{
222    m_strokeData.setLineDash(dashes, dashOffset);
223}
224
225void GraphicsContextState::setColorFilter(PassRefPtr<SkColorFilter> colorFilter)
226{
227    m_colorFilter = colorFilter;
228    m_strokePaint.setColorFilter(m_colorFilter.get());
229    m_fillPaint.setColorFilter(m_colorFilter.get());
230}
231
232void GraphicsContextState::setCompositeOperation(CompositeOperator compositeOperation, WebBlendMode blendMode)
233{
234    m_compositeOperator = compositeOperation;
235    m_blendMode = blendMode;
236    SkXfermode::Mode xferMode = WebCoreCompositeToSkiaComposite(compositeOperation, blendMode);
237    m_strokePaint.setXfermodeMode(xferMode);
238    m_fillPaint.setXfermodeMode(xferMode);
239}
240
241void GraphicsContextState::setInterpolationQuality(InterpolationQuality quality)
242{
243    m_interpolationQuality = quality;
244    m_strokePaint.setFilterLevel(WebCoreInterpolationQualityToSkFilterLevel(quality));
245    m_fillPaint.setFilterLevel(WebCoreInterpolationQualityToSkFilterLevel(quality));
246}
247
248void GraphicsContextState::setShouldAntialias(bool shouldAntialias)
249{
250    m_shouldAntialias = shouldAntialias;
251    m_strokePaint.setAntiAlias(shouldAntialias);
252    m_fillPaint.setAntiAlias(shouldAntialias);
253}
254
255
256} // namespace blink
257