OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef CC_PAINT_PAINT_CANVAS_H_ | 5 #ifndef CC_PAINT_PAINT_CANVAS_H_ |
6 #define CC_PAINT_PAINT_CANVAS_H_ | 6 #define CC_PAINT_PAINT_CANVAS_H_ |
7 | 7 |
8 #include <memory> | |
9 | |
10 #include "base/compiler_specific.h" | |
11 #include "base/logging.h" | |
12 #include "base/macros.h" | |
13 #include "build/build_config.h" | 8 #include "build/build_config.h" |
14 #include "cc/paint/paint_export.h" | 9 #include "cc/paint/paint_export.h" |
15 #include "cc/paint/paint_flags.h" | |
16 #include "third_party/skia/include/core/SkCanvas.h" | 10 #include "third_party/skia/include/core/SkCanvas.h" |
| 11 #include "third_party/skia/include/utils/SkNWayCanvas.h" |
17 #include "third_party/skia/include/utils/SkNoDrawCanvas.h" | 12 #include "third_party/skia/include/utils/SkNoDrawCanvas.h" |
18 | 13 |
19 namespace cc { | 14 namespace cc { |
20 | 15 |
21 class PaintFlags; | 16 using PaintCanvas = SkCanvas; |
22 class PaintRecord; | 17 using PaintCanvasNoDraw = SkNoDrawCanvas; |
| 18 using PaintCanvasAutoRestore = SkAutoCanvasRestore; |
23 | 19 |
24 class CC_PAINT_EXPORT PaintCanvas { | 20 class CC_PAINT_EXPORT PaintCanvasPassThrough : public SkNWayCanvas { |
25 public: | 21 public: |
26 // TODO(enne): remove all constructors but the one that takes an SkCanvas | 22 explicit PaintCanvasPassThrough(SkCanvas* canvas); |
27 // and a future one that will take a PaintOpBuffer to build a PaintRecord. | 23 PaintCanvasPassThrough(int width, int height); |
28 explicit PaintCanvas(SkCanvas* canvas); | 24 ~PaintCanvasPassThrough() override; |
29 explicit PaintCanvas(const SkBitmap& bitmap); | |
30 explicit PaintCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props); | |
31 ~PaintCanvas(); | |
32 | |
33 ALWAYS_INLINE SkMetaData& getMetaData() { return canvas_->getMetaData(); } | |
34 ALWAYS_INLINE SkImageInfo imageInfo() const { return canvas_->imageInfo(); } | |
35 ALWAYS_INLINE bool getProps(SkSurfaceProps* props) const { | |
36 return canvas_->getProps(props); | |
37 } | |
38 // TODO(enne): It would be nice to get rid of flush() entirely, as it | |
39 // doesn't really make sense for recording. However, this gets used by | |
40 // SkCanvasVideoRenderer which takes a PaintCanvas to paint both | |
41 // software and hardware video. This is super entangled with ImageBuffer | |
42 // and canvas/video painting in Blink where the same paths are used for | |
43 // both recording and gpu work. | |
44 ALWAYS_INLINE void flush() { canvas_->flush(); } | |
45 | |
46 ALWAYS_INLINE SkISize getBaseLayerSize() const { | |
47 return canvas_->getBaseLayerSize(); | |
48 } | |
49 ALWAYS_INLINE bool peekPixels(SkPixmap* pixmap) { | |
50 return canvas_->peekPixels(pixmap); | |
51 } | |
52 ALWAYS_INLINE bool readPixels(const SkImageInfo& dest_info, | |
53 void* dest_pixels, | |
54 size_t dest_row_bytes, | |
55 int src_x, | |
56 int src_y) { | |
57 return canvas_->readPixels(dest_info, dest_pixels, dest_row_bytes, src_x, | |
58 src_y); | |
59 } | |
60 ALWAYS_INLINE bool readPixels(SkBitmap* bitmap, int src_x, int src_y) { | |
61 return canvas_->readPixels(bitmap, src_x, src_y); | |
62 } | |
63 ALWAYS_INLINE bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { | |
64 return canvas_->readPixels(srcRect, bitmap); | |
65 } | |
66 ALWAYS_INLINE bool writePixels(const SkImageInfo& info, | |
67 const void* pixels, | |
68 size_t row_bytes, | |
69 int x, | |
70 int y) { | |
71 return canvas_->writePixels(info, pixels, row_bytes, x, y); | |
72 } | |
73 ALWAYS_INLINE int save() { return canvas_->save(); } | |
74 ALWAYS_INLINE int saveLayer(const SkRect* bounds, const PaintFlags* flags) { | |
75 return canvas_->saveLayer(bounds, ToSkPaint(flags)); | |
76 } | |
77 ALWAYS_INLINE int saveLayer(const SkRect& bounds, const PaintFlags* flags) { | |
78 return canvas_->saveLayer(bounds, ToSkPaint(flags)); | |
79 } | |
80 ALWAYS_INLINE int saveLayerPreserveLCDTextRequests(const SkRect* bounds, | |
81 const PaintFlags* flags) { | |
82 return canvas_->saveLayerPreserveLCDTextRequests(bounds, ToSkPaint(flags)); | |
83 } | |
84 ALWAYS_INLINE int saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { | |
85 return canvas_->saveLayerAlpha(bounds, alpha); | |
86 } | |
87 | |
88 ALWAYS_INLINE void restore() { canvas_->restore(); } | |
89 ALWAYS_INLINE int getSaveCount() const { return canvas_->getSaveCount(); } | |
90 ALWAYS_INLINE void restoreToCount(int save_count) { | |
91 canvas_->restoreToCount(save_count); | |
92 } | |
93 ALWAYS_INLINE void translate(SkScalar dx, SkScalar dy) { | |
94 canvas_->translate(dx, dy); | |
95 } | |
96 ALWAYS_INLINE void scale(SkScalar sx, SkScalar sy) { canvas_->scale(sx, sy); } | |
97 ALWAYS_INLINE void rotate(SkScalar degrees) { canvas_->rotate(degrees); } | |
98 ALWAYS_INLINE void rotate(SkScalar degrees, SkScalar px, SkScalar py) { | |
99 canvas_->rotate(degrees, px, py); | |
100 } | |
101 ALWAYS_INLINE void skew(SkScalar sx, SkScalar sy) { canvas_->skew(sx, sy); } | |
102 ALWAYS_INLINE void concat(const SkMatrix& matrix) { canvas_->concat(matrix); } | |
103 ALWAYS_INLINE void setMatrix(const SkMatrix& matrix) { | |
104 canvas_->setMatrix(matrix); | |
105 } | |
106 ALWAYS_INLINE void resetMatrix() { canvas_->resetMatrix(); } | |
107 ALWAYS_INLINE void clipRect(const SkRect& rect, | |
108 SkClipOp op, | |
109 bool do_anti_alias = false) { | |
110 canvas_->clipRect(rect, op, do_anti_alias); | |
111 } | |
112 ALWAYS_INLINE void clipRect(const SkRect& rect, bool do_anti_alias = false) { | |
113 canvas_->clipRect(rect, do_anti_alias); | |
114 } | |
115 ALWAYS_INLINE void clipRRect(const SkRRect& rrect, | |
116 SkClipOp op, | |
117 bool do_anti_alias) { | |
118 canvas_->clipRRect(rrect, op, do_anti_alias); | |
119 } | |
120 ALWAYS_INLINE void clipRRect(const SkRRect& rrect, SkClipOp op) { | |
121 canvas_->clipRRect(rrect, op); | |
122 } | |
123 ALWAYS_INLINE void clipRRect(const SkRRect& rrect, | |
124 bool do_anti_alias = false) { | |
125 canvas_->clipRRect(rrect, do_anti_alias); | |
126 } | |
127 ALWAYS_INLINE void clipPath(const SkPath& path, | |
128 SkClipOp op, | |
129 bool do_anti_alias) { | |
130 canvas_->clipPath(path, op, do_anti_alias); | |
131 } | |
132 ALWAYS_INLINE void clipPath(const SkPath& path, SkClipOp op) { | |
133 canvas_->clipPath(path, op); | |
134 } | |
135 ALWAYS_INLINE void clipPath(const SkPath& path, bool do_anti_alias = false) { | |
136 canvas_->clipPath(path, do_anti_alias); | |
137 } | |
138 ALWAYS_INLINE void clipRegion(const SkRegion& device_region, | |
139 SkClipOp op = SkClipOp::kIntersect) { | |
140 canvas_->clipRegion(device_region, op); | |
141 } | |
142 ALWAYS_INLINE bool quickReject(const SkRect& rect) const { | |
143 return canvas_->quickReject(rect); | |
144 } | |
145 ALWAYS_INLINE bool quickReject(const SkPath& path) const { | |
146 return canvas_->quickReject(path); | |
147 } | |
148 ALWAYS_INLINE SkRect getLocalClipBounds() const { | |
149 return canvas_->getLocalClipBounds(); | |
150 } | |
151 ALWAYS_INLINE bool getLocalClipBounds(SkRect* bounds) const { | |
152 return canvas_->getLocalClipBounds(bounds); | |
153 } | |
154 ALWAYS_INLINE SkIRect getDeviceClipBounds() const { | |
155 return canvas_->getDeviceClipBounds(); | |
156 } | |
157 ALWAYS_INLINE bool getDeviceClipBounds(SkIRect* bounds) const { | |
158 return canvas_->getDeviceClipBounds(bounds); | |
159 } | |
160 ALWAYS_INLINE void drawColor(SkColor color, | |
161 SkBlendMode mode = SkBlendMode::kSrcOver) { | |
162 canvas_->drawColor(color, mode); | |
163 } | |
164 ALWAYS_INLINE void clear(SkColor color) { canvas_->clear(color); } | |
165 ALWAYS_INLINE void discard() { canvas_->discard(); } | |
166 | |
167 ALWAYS_INLINE void drawLine(SkScalar x0, | |
168 SkScalar y0, | |
169 SkScalar x1, | |
170 SkScalar y1, | |
171 const PaintFlags& flags) { | |
172 canvas_->drawLine(x0, y0, x1, y1, ToSkPaint(flags)); | |
173 } | |
174 ALWAYS_INLINE void drawRect(const SkRect& rect, const PaintFlags& flags) { | |
175 canvas_->drawRect(rect, ToSkPaint(flags)); | |
176 } | |
177 ALWAYS_INLINE void drawIRect(const SkIRect& rect, const PaintFlags& flags) { | |
178 canvas_->drawIRect(rect, ToSkPaint(flags)); | |
179 } | |
180 ALWAYS_INLINE void drawOval(const SkRect& oval, const PaintFlags& flags) { | |
181 canvas_->drawOval(oval, ToSkPaint(flags)); | |
182 } | |
183 ALWAYS_INLINE void drawRRect(const SkRRect& rrect, const PaintFlags& flags) { | |
184 canvas_->drawRRect(rrect, ToSkPaint(flags)); | |
185 } | |
186 ALWAYS_INLINE void drawDRRect(const SkRRect& outer, | |
187 const SkRRect& inner, | |
188 const PaintFlags& flags) { | |
189 canvas_->drawDRRect(outer, inner, ToSkPaint(flags)); | |
190 } | |
191 ALWAYS_INLINE void drawCircle(SkScalar cx, | |
192 SkScalar cy, | |
193 SkScalar radius, | |
194 const PaintFlags& flags) { | |
195 canvas_->drawCircle(cx, cy, radius, ToSkPaint(flags)); | |
196 } | |
197 ALWAYS_INLINE void drawArc(const SkRect& oval, | |
198 SkScalar start_angle, | |
199 SkScalar sweep_angle, | |
200 bool use_center, | |
201 const PaintFlags& flags) { | |
202 canvas_->drawArc(oval, start_angle, sweep_angle, use_center, | |
203 ToSkPaint(flags)); | |
204 } | |
205 ALWAYS_INLINE void drawRoundRect(const SkRect& rect, | |
206 SkScalar rx, | |
207 SkScalar ry, | |
208 const PaintFlags& flags) { | |
209 canvas_->drawRoundRect(rect, rx, ry, ToSkPaint(flags)); | |
210 } | |
211 ALWAYS_INLINE void drawPath(const SkPath& path, const PaintFlags& flags) { | |
212 canvas_->drawPath(path, ToSkPaint(flags)); | |
213 } | |
214 ALWAYS_INLINE void drawImage(const SkImage* image, | |
215 SkScalar left, | |
216 SkScalar top, | |
217 const PaintFlags* flags = nullptr) { | |
218 canvas_->drawImage(image, left, top, ToSkPaint(flags)); | |
219 } | |
220 ALWAYS_INLINE void drawImage(const sk_sp<SkImage>& image, | |
221 SkScalar left, | |
222 SkScalar top, | |
223 const PaintFlags* flags = nullptr) { | |
224 canvas_->drawImage(image, left, top, ToSkPaint(flags)); | |
225 } | |
226 | |
227 enum SrcRectConstraint { | |
228 kStrict_SrcRectConstraint = SkCanvas::kStrict_SrcRectConstraint, | |
229 kFast_SrcRectConstraint = SkCanvas::kFast_SrcRectConstraint, | |
230 }; | |
231 | |
232 ALWAYS_INLINE void drawImageRect( | |
233 const SkImage* image, | |
234 const SkRect& src, | |
235 const SkRect& dst, | |
236 const PaintFlags* flags, | |
237 SrcRectConstraint constraint = kStrict_SrcRectConstraint) { | |
238 canvas_->drawImageRect( | |
239 image, src, dst, ToSkPaint(flags), | |
240 static_cast<SkCanvas::SrcRectConstraint>(constraint)); | |
241 } | |
242 ALWAYS_INLINE void drawImageRect( | |
243 const SkImage* image, | |
244 const SkIRect& isrc, | |
245 const SkRect& dst, | |
246 const PaintFlags* flags, | |
247 SrcRectConstraint constraint = kStrict_SrcRectConstraint) { | |
248 canvas_->drawImageRect( | |
249 image, isrc, dst, ToSkPaint(flags), | |
250 static_cast<SkCanvas::SrcRectConstraint>(constraint)); | |
251 } | |
252 ALWAYS_INLINE void drawImageRect( | |
253 const SkImage* image, | |
254 const SkRect& dst, | |
255 const PaintFlags* flags, | |
256 SrcRectConstraint constraint = kStrict_SrcRectConstraint) { | |
257 canvas_->drawImageRect( | |
258 image, dst, ToSkPaint(flags), | |
259 static_cast<SkCanvas::SrcRectConstraint>(constraint)); | |
260 } | |
261 ALWAYS_INLINE void drawImageRect( | |
262 const sk_sp<SkImage>& image, | |
263 const SkRect& src, | |
264 const SkRect& dst, | |
265 const PaintFlags* flags, | |
266 SrcRectConstraint constraint = kStrict_SrcRectConstraint) { | |
267 canvas_->drawImageRect( | |
268 image, src, dst, ToSkPaint(flags), | |
269 static_cast<SkCanvas::SrcRectConstraint>(constraint)); | |
270 } | |
271 ALWAYS_INLINE void drawImageRect( | |
272 const sk_sp<SkImage>& image, | |
273 const SkIRect& isrc, | |
274 const SkRect& dst, | |
275 const PaintFlags* flags, | |
276 SrcRectConstraint cons = kStrict_SrcRectConstraint) { | |
277 canvas_->drawImageRect(image, isrc, dst, ToSkPaint(flags), | |
278 static_cast<SkCanvas::SrcRectConstraint>(cons)); | |
279 } | |
280 ALWAYS_INLINE void drawImageRect( | |
281 const sk_sp<SkImage>& image, | |
282 const SkRect& dst, | |
283 const PaintFlags* flags, | |
284 SrcRectConstraint cons = kStrict_SrcRectConstraint) { | |
285 canvas_->drawImageRect(image, dst, ToSkPaint(flags), | |
286 static_cast<SkCanvas::SrcRectConstraint>(cons)); | |
287 } | |
288 ALWAYS_INLINE void drawBitmap(const SkBitmap& bitmap, | |
289 SkScalar left, | |
290 SkScalar top, | |
291 const PaintFlags* flags = nullptr) { | |
292 canvas_->drawBitmap(bitmap, left, top, ToSkPaint(flags)); | |
293 } | |
294 ALWAYS_INLINE void drawBitmapRect( | |
295 const SkBitmap& bitmap, | |
296 const SkRect& src, | |
297 const SkRect& dst, | |
298 const PaintFlags* flags, | |
299 SrcRectConstraint constraint = kStrict_SrcRectConstraint) { | |
300 canvas_->drawBitmapRect( | |
301 bitmap, src, dst, ToSkPaint(flags), | |
302 static_cast<SkCanvas::SrcRectConstraint>(constraint)); | |
303 } | |
304 ALWAYS_INLINE void drawBitmapRect( | |
305 const SkBitmap& bitmap, | |
306 const SkIRect& isrc, | |
307 const SkRect& dst, | |
308 const PaintFlags* flags, | |
309 SrcRectConstraint constraint = kStrict_SrcRectConstraint) { | |
310 canvas_->drawBitmapRect( | |
311 bitmap, isrc, dst, ToSkPaint(flags), | |
312 static_cast<SkCanvas::SrcRectConstraint>(constraint)); | |
313 } | |
314 ALWAYS_INLINE void drawBitmapRect( | |
315 const SkBitmap& bitmap, | |
316 const SkRect& dst, | |
317 const PaintFlags* flags, | |
318 SrcRectConstraint constraint = kStrict_SrcRectConstraint) { | |
319 canvas_->drawBitmapRect( | |
320 bitmap, dst, ToSkPaint(flags), | |
321 static_cast<SkCanvas::SrcRectConstraint>(constraint)); | |
322 } | |
323 | |
324 ALWAYS_INLINE void drawText(const void* text, | |
325 size_t byte_length, | |
326 SkScalar x, | |
327 SkScalar y, | |
328 const PaintFlags& flags) { | |
329 canvas_->drawText(text, byte_length, x, y, ToSkPaint(flags)); | |
330 } | |
331 ALWAYS_INLINE void drawPosText(const void* text, | |
332 size_t byte_length, | |
333 const SkPoint pos[], | |
334 const PaintFlags& flags) { | |
335 canvas_->drawPosText(text, byte_length, pos, ToSkPaint(flags)); | |
336 } | |
337 ALWAYS_INLINE void drawTextBlob(const SkTextBlob* blob, | |
338 SkScalar x, | |
339 SkScalar y, | |
340 const PaintFlags& flags) { | |
341 canvas_->drawTextBlob(blob, x, y, ToSkPaint(flags)); | |
342 } | |
343 ALWAYS_INLINE void drawTextBlob(const sk_sp<SkTextBlob>& blob, | |
344 SkScalar x, | |
345 SkScalar y, | |
346 const PaintFlags& flags) { | |
347 canvas_->drawTextBlob(blob, x, y, ToSkPaint(flags)); | |
348 } | |
349 | |
350 ALWAYS_INLINE void drawPicture(const PaintRecord* record) { | |
351 canvas_->drawPicture(ToSkPicture(record)); | |
352 } | |
353 ALWAYS_INLINE void drawPicture(const PaintRecord* record, | |
354 const SkMatrix* matrix, | |
355 const PaintFlags* flags) { | |
356 canvas_->drawPicture(ToSkPicture(record), matrix, ToSkPaint(flags)); | |
357 } | |
358 ALWAYS_INLINE void drawPicture(sk_sp<PaintRecord> record) { | |
359 drawPicture(record.get()); | |
360 } | |
361 | |
362 ALWAYS_INLINE bool isClipEmpty() const { return canvas_->isClipEmpty(); } | |
363 ALWAYS_INLINE bool isClipRect() const { return canvas_->isClipRect(); } | |
364 ALWAYS_INLINE const SkMatrix& getTotalMatrix() const { | |
365 return canvas_->getTotalMatrix(); | |
366 } | |
367 | |
368 // For GraphicsContextCanvas only. Maybe this could be rewritten? | |
369 ALWAYS_INLINE void temporary_internal_describeTopLayer(SkMatrix* matrix, | |
370 SkIRect* clip_bounds) { | |
371 return canvas_->temporary_internal_describeTopLayer(matrix, clip_bounds); | |
372 } | |
373 | |
374 protected: | |
375 friend class PaintSurface; | |
376 friend class PaintRecord; | |
377 friend class PaintRecorder; | |
378 friend CC_PAINT_EXPORT void PaintCanvasAnnotateRectWithURL( | |
379 PaintCanvas* canvas, | |
380 const SkRect& rect, | |
381 SkData* data); | |
382 friend CC_PAINT_EXPORT void PaintCanvasAnnotateNamedDestination( | |
383 PaintCanvas* canvas, | |
384 const SkPoint& point, | |
385 SkData* data); | |
386 friend CC_PAINT_EXPORT void PaintCanvasAnnotateLinkToDestination( | |
387 PaintCanvas* canvas, | |
388 const SkRect& rect, | |
389 SkData* data); | |
390 friend CC_PAINT_EXPORT bool ToPixmap(PaintCanvas* canvas, SkPixmap* output); | |
391 | |
392 private: | |
393 SkCanvas* canvas_; | |
394 std::unique_ptr<SkCanvas> owned_; | |
395 | |
396 DISALLOW_COPY_AND_ASSIGN(PaintCanvas); | |
397 }; | 25 }; |
398 | 26 |
399 class CC_PAINT_EXPORT PaintCanvasAutoRestore { | 27 // TODO(enne): Move all these functions into PaintCanvas. |
400 public: | |
401 ALWAYS_INLINE PaintCanvasAutoRestore(PaintCanvas* canvas, bool save) | |
402 : canvas_(canvas) { | |
403 if (canvas_) { | |
404 save_count_ = canvas_->getSaveCount(); | |
405 if (save) { | |
406 canvas_->save(); | |
407 } | |
408 } | |
409 } | |
410 | |
411 ALWAYS_INLINE ~PaintCanvasAutoRestore() { | |
412 if (canvas_) { | |
413 canvas_->restoreToCount(save_count_); | |
414 } | |
415 } | |
416 | |
417 ALWAYS_INLINE void restore() { | |
418 if (canvas_) { | |
419 canvas_->restoreToCount(save_count_); | |
420 canvas_ = nullptr; | |
421 } | |
422 } | |
423 | |
424 private: | |
425 PaintCanvas* canvas_ = nullptr; | |
426 int save_count_ = 0; | |
427 }; | |
428 | |
429 // TODO(enne): Move all these functions into PaintCanvas. These are only | |
430 // separate now to make the transition to concrete types easier by keeping | |
431 // the base PaintCanvas type equivalent to the SkCanvas interface and | |
432 // all these helper functions potentially operating on both. | |
433 | 28 |
434 // PaintCanvas equivalent of skia::GetWritablePixels. | 29 // PaintCanvas equivalent of skia::GetWritablePixels. |
435 CC_PAINT_EXPORT bool ToPixmap(PaintCanvas* canvas, SkPixmap* output); | 30 CC_PAINT_EXPORT bool ToPixmap(PaintCanvas* canvas, SkPixmap* output); |
436 | 31 |
437 // Following routines are used in print preview workflow to mark the | 32 // Following routines are used in print preview workflow to mark the |
438 // preview metafile. | 33 // preview metafile. |
439 #if defined(OS_MACOSX) | 34 #if defined(OS_MACOSX) |
440 CC_PAINT_EXPORT void SetIsPreviewMetafile(PaintCanvas* canvas, bool is_preview); | 35 CC_PAINT_EXPORT void SetIsPreviewMetafile(PaintCanvas* canvas, bool is_preview); |
441 CC_PAINT_EXPORT bool IsPreviewMetafile(PaintCanvas* canvas); | 36 CC_PAINT_EXPORT bool IsPreviewMetafile(PaintCanvas* canvas); |
442 #endif | 37 #endif |
443 | 38 |
444 CC_PAINT_EXPORT void PaintCanvasAnnotateRectWithURL(PaintCanvas* canvas, | |
445 const SkRect& rect, | |
446 SkData* data); | |
447 | |
448 CC_PAINT_EXPORT void PaintCanvasAnnotateNamedDestination(PaintCanvas* canvas, | |
449 const SkPoint& point, | |
450 SkData* data); | |
451 | |
452 CC_PAINT_EXPORT void PaintCanvasAnnotateLinkToDestination(PaintCanvas* canvas, | |
453 const SkRect& rect, | |
454 SkData* data); | |
455 | |
456 } // namespace cc | 39 } // namespace cc |
457 | 40 |
458 #endif // CC_PAINT_PAINT_CANVAS_H_ | 41 #endif // CC_PAINT_PAINT_CANVAS_H_ |
OLD | NEW |