OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 #ifndef BaseRenderingContext2D_h | |
6 #define BaseRenderingContext2D_h | |
7 | |
8 #include "bindings/core/v8/UnionTypesCore.h" | |
9 #include "bindings/modules/v8/UnionTypesModules.h" | |
10 #include "core/html/canvas/CanvasRenderingContext.h" | |
11 #include "modules/ModulesExport.h" | |
12 #include "modules/canvas2d/CanvasGradient.h" | |
13 #include "modules/canvas2d/CanvasPathMethods.h" | |
14 #include "modules/canvas2d/CanvasRenderingContext2DState.h" | |
15 #include "modules/canvas2d/CanvasStyle.h" | |
16 #include "third_party/skia/include/core/SkCanvas.h" | |
17 | |
18 namespace blink { | |
19 | |
20 class CanvasImageSource; | |
21 class Color; | |
22 class Image; | |
23 class ImageBuffer; | |
24 class Path2D; | |
25 class SVGMatrixTearOff; | |
26 | |
27 typedef HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrImageBitmap Canva
sImageSourceUnion; | |
28 | |
29 class MODULES_EXPORT BaseRenderingContext2D : public WillBeGarbageCollectedMixin
, public CanvasPathMethods { | |
30 public: | |
31 ~BaseRenderingContext2D() override; | |
32 | |
33 void strokeStyle(StringOrCanvasGradientOrCanvasPattern&) const; | |
34 void setStrokeStyle(const StringOrCanvasGradientOrCanvasPattern&); | |
35 | |
36 void fillStyle(StringOrCanvasGradientOrCanvasPattern&) const; | |
37 void setFillStyle(const StringOrCanvasGradientOrCanvasPattern&); | |
38 | |
39 double lineWidth() const; | |
40 void setLineWidth(double); | |
41 | |
42 String lineCap() const; | |
43 void setLineCap(const String&); | |
44 | |
45 String lineJoin() const; | |
46 void setLineJoin(const String&); | |
47 | |
48 double miterLimit() const; | |
49 void setMiterLimit(double); | |
50 | |
51 const Vector<double>& getLineDash() const; | |
52 void setLineDash(const Vector<double>&); | |
53 | |
54 double lineDashOffset() const; | |
55 void setLineDashOffset(double); | |
56 | |
57 double shadowOffsetX() const; | |
58 void setShadowOffsetX(double); | |
59 | |
60 double shadowOffsetY() const; | |
61 void setShadowOffsetY(double); | |
62 | |
63 double shadowBlur() const; | |
64 void setShadowBlur(double); | |
65 | |
66 String shadowColor() const; | |
67 void setShadowColor(const String&); | |
68 | |
69 double globalAlpha() const; | |
70 void setGlobalAlpha(double); | |
71 | |
72 String globalCompositeOperation() const; | |
73 void setGlobalCompositeOperation(const String&); | |
74 | |
75 String filter() const; | |
76 void setFilter(const String&); | |
77 | |
78 void save(); | |
79 void restore(); | |
80 | |
81 PassRefPtrWillBeRawPtr<SVGMatrixTearOff> currentTransform() const; | |
82 void setCurrentTransform(PassRefPtrWillBeRawPtr<SVGMatrixTearOff>); | |
83 | |
84 void scale(double sx, double sy); | |
85 void rotate(double angleInRadians); | |
86 void translate(double tx, double ty); | |
87 void transform(double m11, double m12, double m21, double m22, double dx, do
uble dy); | |
88 void setTransform(double m11, double m12, double m21, double m22, double dx,
double dy); | |
89 void resetTransform(); | |
90 | |
91 void beginPath(); | |
92 | |
93 void fill(const String& winding = "nonzero"); | |
94 void fill(Path2D*, const String& winding = "nonzero"); | |
95 void stroke(); | |
96 void stroke(Path2D*); | |
97 void clip(const String& winding = "nonzero"); | |
98 void clip(Path2D*, const String& winding = "nonzero"); | |
99 | |
100 bool isPointInPath(const double x, const double y, const String& winding = "
nonzero"); | |
101 bool isPointInPath(Path2D*, const double x, const double y, const String& wi
nding = "nonzero"); | |
102 bool isPointInStroke(const double x, const double y); | |
103 bool isPointInStroke(Path2D*, const double x, const double y); | |
104 | |
105 void clearRect(double x, double y, double width, double height); | |
106 void fillRect(double x, double y, double width, double height); | |
107 void strokeRect(double x, double y, double width, double height); | |
108 | |
109 void drawImage(const CanvasImageSourceUnion&, double x, double y, ExceptionS
tate&); | |
110 void drawImage(const CanvasImageSourceUnion&, double x, double y, double wid
th, double height, ExceptionState&); | |
111 void drawImage(const CanvasImageSourceUnion&, double sx, double sy, double s
w, double sh, double dx, double dy, double dw, double dh, ExceptionState&); | |
112 void drawImage(CanvasImageSource*, double sx, double sy, double sw, double s
h, double dx, double dy, double dw, double dh, ExceptionState&); | |
113 | |
114 CanvasGradient* createLinearGradient(double x0, double y0, double x1, double
y1); | |
115 CanvasGradient* createRadialGradient(double x0, double y0, double r0, double
x1, double y1, double r1, ExceptionState&); | |
116 CanvasPattern* createPattern(const CanvasImageSourceUnion&, const String& re
petitionType, ExceptionState&); | |
117 | |
118 ImageData* createImageData(ImageData*) const; | |
119 ImageData* createImageData(double width, double height, ExceptionState&) con
st; | |
120 ImageData* getImageData(double sx, double sy, double sw, double sh, Exceptio
nState&) const; | |
121 void putImageData(ImageData*, double dx, double dy, ExceptionState&); | |
122 void putImageData(ImageData*, double dx, double dy, double dirtyX, double di
rtyY, double dirtyWidth, double dirtyHeight, ExceptionState&); | |
123 | |
124 bool imageSmoothingEnabled() const; | |
125 void setImageSmoothingEnabled(bool); | |
126 String imageSmoothingQuality() const; | |
127 void setImageSmoothingQuality(const String&); | |
128 | |
129 virtual bool originClean() const = 0; | |
130 virtual void setOriginTainted() = 0; | |
131 virtual bool wouldTaintOrigin(CanvasImageSource*) = 0; | |
132 | |
133 virtual int width() const = 0; | |
134 virtual int height() const = 0; | |
135 | |
136 virtual bool hasImageBuffer() const = 0; | |
137 virtual ImageBuffer* imageBuffer() const = 0; | |
138 | |
139 virtual bool parseColorOrCurrentColor(Color&, const String& colorString) con
st = 0; | |
140 | |
141 virtual SkCanvas* drawingCanvas() const = 0; | |
142 virtual SkCanvas* existingDrawingCanvas() const = 0; | |
143 virtual void disableDeferral(DisableDeferralReason) = 0; | |
144 | |
145 virtual AffineTransform baseTransform() const = 0; | |
146 | |
147 virtual void didDraw(const SkIRect& dirtyRect) = 0; | |
148 | |
149 virtual bool stateHasFilter() = 0; | |
150 virtual SkImageFilter* stateGetFilter() = 0; | |
151 | |
152 virtual void validateStateStack() = 0; | |
153 | |
154 virtual bool hasAlpha() const = 0; | |
155 | |
156 virtual bool isContextLost() const = 0; | |
157 | |
158 DECLARE_VIRTUAL_TRACE(); | |
159 | |
160 protected: | |
161 BaseRenderingContext2D(); | |
162 | |
163 CanvasRenderingContext2DState& modifiableState(); | |
164 const CanvasRenderingContext2DState& state() const { return *m_stateStack.la
st(); } | |
165 | |
166 bool computeDirtyRect(const FloatRect& localBounds, SkIRect*); | |
167 bool computeDirtyRect(const FloatRect& localBounds, const SkIRect& transform
edClipBounds, SkIRect*); | |
168 | |
169 template<typename DrawFunc, typename ContainsFunc> | |
170 bool draw(const DrawFunc&, const ContainsFunc&, const SkRect& bounds, Canvas
RenderingContext2DState::PaintType, CanvasRenderingContext2DState::ImageType = C
anvasRenderingContext2DState::NoImage); | |
171 | |
172 void inflateStrokeRect(FloatRect&) const; | |
173 | |
174 enum DrawType { | |
175 ClipFill, // Fill that is already known to cover the current clip | |
176 UntransformedUnclippedFill | |
177 }; | |
178 | |
179 void checkOverdraw(const SkRect&, const SkPaint*, CanvasRenderingContext2DSt
ate::ImageType, DrawType); | |
180 | |
181 WillBeHeapVector<OwnPtrWillBeMember<CanvasRenderingContext2DState>> m_stateS
tack; | |
182 AntiAliasingMode m_clipAntialiasing; | |
183 | |
184 private: | |
185 void realizeSaves(); | |
186 | |
187 bool shouldDrawImageAntialiased(const FloatRect& destRect) const; | |
188 | |
189 void drawPathInternal(const Path&, CanvasRenderingContext2DState::PaintType,
SkPath::FillType = SkPath::kWinding_FillType); | |
190 void drawImageInternal(SkCanvas*, CanvasImageSource*, Image*, const FloatRec
t& srcRect, const FloatRect& dstRect, const SkPaint*); | |
191 void clipInternal(const Path&, const String& windingRuleString); | |
192 | |
193 bool isPointInPathInternal(const Path&, const double x, const double y, cons
t String& windingRuleString); | |
194 bool isPointInStrokeInternal(const Path&, const double x, const double y); | |
195 | |
196 static bool isFullCanvasCompositeMode(SkXfermode::Mode); | |
197 | |
198 template<typename DrawFunc> | |
199 void compositedDraw(const DrawFunc&, SkCanvas*, CanvasRenderingContext2DStat
e::PaintType, CanvasRenderingContext2DState::ImageType); | |
200 | |
201 void clearCanvas(); | |
202 bool rectContainsTransformedRect(const FloatRect&, const SkIRect&) const; | |
203 }; | |
204 | |
205 template<typename DrawFunc, typename ContainsFunc> | |
206 bool BaseRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc&
drawCoversClipBounds, const SkRect& bounds, CanvasRenderingContext2DState::Paint
Type paintType, CanvasRenderingContext2DState::ImageType imageType) | |
207 { | |
208 if (!state().isTransformInvertible()) | |
209 return false; | |
210 | |
211 SkIRect clipBounds; | |
212 if (!drawingCanvas() || !drawingCanvas()->getClipDeviceBounds(&clipBounds)) | |
213 return false; | |
214 | |
215 // If gradient size is zero, then paint nothing. | |
216 CanvasStyle* style = state().style(paintType); | |
217 if (style) { | |
218 CanvasGradient* gradient = style->canvasGradient(); | |
219 if (gradient && gradient->gradient()->isZeroSize()) | |
220 return false; | |
221 } | |
222 | |
223 if (isFullCanvasCompositeMode(state().globalComposite()) || stateHasFilter()
) { | |
224 compositedDraw(drawFunc, drawingCanvas(), paintType, imageType); | |
225 didDraw(clipBounds); | |
226 } else if (state().globalComposite() == SkXfermode::kSrc_Mode) { | |
227 clearCanvas(); // takes care of checkOverdraw() | |
228 const SkPaint* paint = state().getPaint(paintType, DrawForegroundOnly, i
mageType); | |
229 drawFunc(drawingCanvas(), paint); | |
230 didDraw(clipBounds); | |
231 } else { | |
232 SkIRect dirtyRect; | |
233 if (computeDirtyRect(bounds, clipBounds, &dirtyRect)) { | |
234 const SkPaint* paint = state().getPaint(paintType, DrawShadowAndFore
ground, imageType); | |
235 if (paintType != CanvasRenderingContext2DState::StrokePaintType && d
rawCoversClipBounds(clipBounds)) | |
236 checkOverdraw(bounds, paint, imageType, ClipFill); | |
237 drawFunc(drawingCanvas(), paint); | |
238 didDraw(dirtyRect); | |
239 } | |
240 } | |
241 return true; | |
242 } | |
243 | |
244 template<typename DrawFunc> | |
245 void BaseRenderingContext2D::compositedDraw(const DrawFunc& drawFunc, SkCanvas*
c, CanvasRenderingContext2DState::PaintType paintType, CanvasRenderingContext2DS
tate::ImageType imageType) | |
246 { | |
247 SkImageFilter* filter = stateGetFilter(); | |
248 ASSERT(isFullCanvasCompositeMode(state().globalComposite()) || filter); | |
249 SkMatrix ctm = c->getTotalMatrix(); | |
250 c->resetMatrix(); | |
251 SkPaint compositePaint; | |
252 compositePaint.setXfermodeMode(state().globalComposite()); | |
253 if (state().shouldDrawShadows()) { | |
254 // unroll into two independently composited passes if drawing shadows | |
255 SkPaint shadowPaint = *state().getPaint(paintType, DrawShadowOnly, image
Type); | |
256 int saveCount = c->getSaveCount(); | |
257 if (filter) { | |
258 SkPaint filterPaint; | |
259 filterPaint.setImageFilter(filter); | |
260 // TODO(junov): crbug.com/502921 We could use primitive bounds if we
knew that the filter | |
261 // does not affect transparent black regions. | |
262 c->saveLayer(nullptr, &shadowPaint); | |
263 c->saveLayer(nullptr, &filterPaint); | |
264 SkPaint foregroundPaint = *state().getPaint(paintType, DrawForegroun
dOnly, imageType); | |
265 c->setMatrix(ctm); | |
266 drawFunc(c, &foregroundPaint); | |
267 } else { | |
268 ASSERT(isFullCanvasCompositeMode(state().globalComposite())); | |
269 c->saveLayer(nullptr, &compositePaint); | |
270 shadowPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode); | |
271 c->setMatrix(ctm); | |
272 drawFunc(c, &shadowPaint); | |
273 } | |
274 c->restoreToCount(saveCount); | |
275 } | |
276 | |
277 compositePaint.setImageFilter(filter); | |
278 // TODO(junov): crbug.com/502921 We could use primitive bounds if we knew th
at the filter | |
279 // does not affect transparent black regions *and* !isFullCanvasCompositeMod
e | |
280 c->saveLayer(nullptr, &compositePaint); | |
281 SkPaint foregroundPaint = *state().getPaint(paintType, DrawForegroundOnly, i
mageType); | |
282 foregroundPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode); | |
283 c->setMatrix(ctm); | |
284 drawFunc(c, &foregroundPaint); | |
285 c->restore(); | |
286 c->setMatrix(ctm); | |
287 } | |
288 | |
289 } // namespace blink | |
290 | |
291 #endif // BaseRenderingContext2D_h | |
OLD | NEW |