OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2016 Google Inc. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 | |
8 #include "SkDeferredCanvas.h" | |
9 #include "SkDrawable.h" | |
10 #include "SkPath.h" | |
11 #include "SkRRect.h" | |
12 #include "SkSurface.h" | |
13 #include "SkTextBlob.h" | |
14 | |
15 bool SkDeferredCanvas::Rec::isConcat(SkMatrix* m) const { | |
16 switch (fType) { | |
17 case kTrans_Type: | |
18 m->setTranslate(fData.fTranslate.x(), fData.fTranslate.y()); | |
19 return true; | |
20 case kScaleTrans_Type: | |
21 m->setScaleTranslate(fData.fScaleTrans.fScale.x(), | |
22 fData.fScaleTrans.fScale.y(), | |
23 fData.fScaleTrans.fTrans.x(), | |
24 fData.fScaleTrans.fTrans.y()); | |
25 return true; | |
26 default: | |
27 break; | |
28 } | |
29 return false; | |
30 } | |
31 | |
32 void SkDeferredCanvas::Rec::setConcat(const SkMatrix& m) { | |
33 SkASSERT(m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) ; | |
34 | |
35 if (m.getType() <= SkMatrix::kTranslate_Mask) { | |
36 fType = kTrans_Type; | |
37 fData.fTranslate.set(m.getTranslateX(), m.getTranslateY()); | |
38 } else { | |
39 fType = kScaleTrans_Type; | |
40 fData.fScaleTrans.fScale.set(m.getScaleX(), m.getScaleY()); | |
41 fData.fScaleTrans.fTrans.set(m.getTranslateX(), m.getTranslateY()); | |
42 } | |
43 } | |
44 | |
45 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
46 | |
47 SkDeferredCanvas::SkDeferredCanvas(SkCanvas* canvas) | |
48 : INHERITED(canvas->getBaseLayerSize().width(), canvas->getBaseLayerSize().h eight()) | |
49 , fCanvas(canvas) | |
50 { | |
51 fSaveCount = 0; | |
52 } | |
53 | |
54 SkDeferredCanvas::~SkDeferredCanvas() { | |
55 } | |
56 | |
57 void SkDeferredCanvas::push_save() { | |
58 Rec* r = fRecs.append(); | |
59 r->fType = kSave_Type; | |
60 r->fData.fSaveCount = ++fSaveCount; | |
61 } | |
62 | |
63 void SkDeferredCanvas::push_cliprect(const SkRect& bounds) { | |
64 int index = fRecs.count() - 1; | |
65 if (index >= 0 && fRecs[index].fType == kClipRect_Type) { | |
66 if (!fRecs[index].fData.fBounds.intersect(bounds)) { | |
67 fRecs[index].fData.fBounds.setEmpty(); | |
68 } | |
69 } else { | |
70 Rec* r = fRecs.append(); | |
71 r->fType = kClipRect_Type; | |
72 r->fData.fBounds = bounds; | |
73 } | |
74 } | |
75 | |
76 bool SkDeferredCanvas::push_concat(const SkMatrix& mat) { | |
77 if (mat.getType() > (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) { | |
78 return false; | |
79 } | |
80 // At the moment, we don't know which ops can scale and which can also flip, so | |
81 // we reject negative scales for now | |
82 if (mat.getScaleX() < 0 || mat.getScaleY() < 0) { | |
83 return false; | |
84 } | |
85 | |
86 int index = fRecs.count() - 1; | |
87 SkMatrix m; | |
88 if (index >= 0 && fRecs[index].isConcat(&m)) { | |
89 m.preConcat(mat); | |
90 fRecs[index].setConcat(m); | |
91 } else { | |
92 fRecs.append()->setConcat(mat); | |
93 } | |
94 return true; | |
95 } | |
96 | |
97 void SkDeferredCanvas::emit(const Rec& rec) { | |
98 switch (rec.fType) { | |
99 case kSave_Type: | |
100 fCanvas->save(); | |
101 this->INHERITED::willSave(); | |
f(malita)
2016/07/07 15:24:07
Do we really want to defer the upcall (as opposed
| |
102 break; | |
103 case kClipRect_Type: | |
104 fCanvas->clipRect(rec.fData.fBounds); | |
105 this->INHERITED::onClipRect(rec.fData.fBounds, | |
106 SkRegion::kIntersect_Op, kHard_ClipEdgeS tyle); | |
107 break; | |
108 case kTrans_Type: | |
109 case kScaleTrans_Type: { | |
110 SkMatrix mat; | |
111 rec.getConcat(&mat); | |
112 fCanvas->concat(mat); | |
113 this->INHERITED::didConcat(mat); | |
114 } break; | |
115 } | |
116 } | |
117 | |
118 void SkDeferredCanvas::flush_le(int index) { | |
119 SkASSERT(index >= -1 && index < fRecs.count()); | |
120 | |
121 int count = index + 1; | |
122 for (int i = 0; i < count; ++i) { | |
123 this->emit(fRecs[i]); | |
124 } | |
125 fRecs.remove(0, count); | |
126 } | |
127 | |
128 void SkDeferredCanvas::flush_all() { | |
129 this->flush_le(fRecs.count() - 1); | |
130 } | |
131 | |
132 void SkDeferredCanvas::flush_before_saves() { | |
133 int i; | |
134 for (i = fRecs.count() - 1; i >= 0; --i) { | |
135 if (kSave_Type != fRecs[i].fType) { | |
136 break; | |
137 } | |
138 } | |
139 this->flush_le(i); | |
140 } | |
141 | |
142 enum Flags { | |
143 kNoTranslate_Flag = 1 << 0, | |
144 kNoClip_Flag = 1 << 1, | |
145 kNoCull_Flag = 1 << 2, | |
146 kNoScale_Flag = 1 << 3, | |
147 }; | |
148 | |
149 void SkDeferredCanvas::flush_check(SkRect* bounds, const SkPaint* paint, unsigne d flags) { | |
150 if (paint) { | |
151 if (paint->getShader() || paint->getImageFilter()) { | |
152 flags |= kNoTranslate_Flag | kNoScale_Flag; | |
153 } | |
154 // TODO: replace these with code to enlarge the bounds conservatively? | |
155 if (paint->getStyle() != SkPaint::kFill_Style || paint->getMaskFilter() || | |
156 paint->getImageFilter() || paint->getPathEffect()) | |
157 { | |
158 flags |= kNoCull_Flag | kNoScale_Flag; | |
159 } | |
160 if (paint->getLooper()) { | |
161 // to be conservative, we disable both, since embedded layers could have shaders | |
162 // or strokes etc. | |
163 flags |= kNoTranslate_Flag | kNoCull_Flag | kNoScale_Flag; | |
164 } | |
165 } | |
166 bool canClip = !(flags & kNoClip_Flag); | |
167 bool canTranslate = !(flags & kNoTranslate_Flag); | |
168 bool canCull = !(flags & kNoCull_Flag); | |
169 bool canScale = !(flags & kNoScale_Flag); | |
170 | |
171 int i; | |
172 for (i = fRecs.count() - 1; i >= 0; --i) { | |
173 const Rec& rec = fRecs[i]; | |
174 switch (rec.fType) { | |
175 case kSave_Type: | |
176 // continue to the next rec | |
177 break; | |
178 case kClipRect_Type: | |
179 if (!canCull) { | |
180 goto STOP; | |
181 } | |
182 if (canClip) { | |
183 if (!bounds->intersect(rec.fData.fBounds)) { | |
184 bounds->setEmpty(); | |
185 return; | |
186 } | |
187 // continue to the next rec | |
188 } else { | |
189 if (rec.fData.fBounds.contains(*bounds)) { | |
190 // continue to the next rec | |
191 } else { | |
192 goto STOP; | |
193 } | |
194 } | |
195 break; | |
196 case kTrans_Type: | |
197 if (canTranslate) { | |
198 bounds->offset(rec.fData.fTranslate.x(), rec.fData.fTranslat e.y()); | |
199 // continue to the next rec | |
200 } else { | |
201 goto STOP; | |
202 } | |
203 break; | |
204 case kScaleTrans_Type: | |
205 if (canScale) { | |
206 SkMatrix m; | |
207 rec.getConcat(&m); | |
208 m.mapRectScaleTranslate(bounds, *bounds); | |
209 } else { | |
210 goto STOP; | |
211 } | |
212 break; | |
213 } | |
214 } | |
215 STOP: | |
216 this->flush_le(i); | |
217 } | |
218 | |
219 void SkDeferredCanvas::flush_translate(SkScalar* x, SkScalar* y, const SkRect& b ounds, | |
220 const SkPaint* paint) { | |
221 SkRect tmp = bounds; | |
222 this->flush_check(&tmp, paint, kNoClip_Flag | kNoScale_Flag); | |
223 *x += tmp.x() - bounds.x(); | |
224 *y += tmp.y() - bounds.y(); | |
225 } | |
226 | |
227 void SkDeferredCanvas::flush_translate(SkScalar* x, SkScalar* y, const SkPaint& paint) { | |
228 SkRect tmp = SkRect::MakeXYWH(*x, *y, 1, 1); | |
229 this->flush_check(&tmp, &paint, kNoClip_Flag | kNoCull_Flag | kNoScale_Flag) ; | |
230 *x = tmp.x(); | |
231 *y = tmp.y(); | |
232 } | |
233 | |
234 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
235 | |
236 void SkDeferredCanvas::willSave() { | |
237 this->push_save(); | |
238 } | |
239 | |
240 SkCanvas::SaveLayerStrategy SkDeferredCanvas::getSaveLayerStrategy(const SaveLay erRec& rec) { | |
241 this->flush_all(); | |
242 fSaveCount += 1; | |
243 fCanvas->saveLayer(rec); | |
244 this->INHERITED::getSaveLayerStrategy(rec); | |
245 // No need for a layer. | |
246 return kNoLayer_SaveLayerStrategy; | |
247 } | |
248 | |
249 void SkDeferredCanvas::willRestore() { | |
250 SkDEBUGCODE(const int restoreCount = fSaveCount--;) | |
251 | |
252 for (int i = fRecs.count() - 1; i >= 0; --i) { | |
253 if (kSave_Type == fRecs[i].fType) { | |
254 SkASSERT(fRecs[i].fData.fSaveCount == restoreCount); | |
255 fRecs.setCount(i); // pop off everything here and later | |
256 return; | |
257 } | |
258 } | |
259 for (int i = 0; i < fRecs.count(); ++i) { | |
260 SkASSERT(kSave_Type != fRecs[i].fType); | |
261 } | |
262 fRecs.setCount(0); | |
263 fCanvas->restore(); | |
264 this->INHERITED::willRestore(); | |
265 } | |
266 | |
267 void SkDeferredCanvas::didConcat(const SkMatrix& matrix) { | |
268 if (matrix.isIdentity()) { | |
269 return; | |
270 } | |
271 if (!this->push_concat(matrix)) { | |
272 this->flush_all(); | |
273 fCanvas->concat(matrix); | |
274 this->INHERITED::didConcat(matrix); | |
275 } | |
276 } | |
277 | |
278 void SkDeferredCanvas::didSetMatrix(const SkMatrix& matrix) { | |
279 this->flush_all(); | |
280 fCanvas->setMatrix(matrix); | |
281 this->INHERITED::didSetMatrix(matrix); | |
282 } | |
283 | |
284 void SkDeferredCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeS tyle edgeStyle) { | |
285 if (SkRegion::kIntersect_Op == op) { | |
286 this->push_cliprect(rect); | |
287 } else { | |
288 this->flush_all(); | |
289 fCanvas->clipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle); | |
290 this->INHERITED::onClipRect(rect, op, edgeStyle); | |
291 } | |
292 } | |
293 | |
294 void SkDeferredCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEd geStyle edgeStyle) { | |
295 this->flush_all(); | |
296 fCanvas->clipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle); | |
297 this->INHERITED::onClipRRect(rrect, op, edgeStyle); | |
298 } | |
299 | |
300 void SkDeferredCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeS tyle edgeStyle) { | |
301 this->flush_all(); | |
302 fCanvas->clipPath(path, op, kSoft_ClipEdgeStyle == edgeStyle); | |
303 this->INHERITED::onClipPath(path, op, edgeStyle); | |
304 } | |
305 | |
306 void SkDeferredCanvas::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) { | |
307 this->flush_all(); | |
308 fCanvas->clipRegion(deviceRgn, op); | |
309 this->INHERITED::onClipRegion(deviceRgn, op); | |
310 } | |
311 | |
312 void SkDeferredCanvas::onDrawPaint(const SkPaint& paint) { | |
313 // TODO: Can we turn this into drawRect? | |
314 this->flush_all(); | |
315 fCanvas->drawPaint(paint); | |
316 } | |
317 | |
318 void SkDeferredCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], | |
319 const SkPaint& paint) { | |
320 this->flush_all(); | |
321 fCanvas->drawPoints(mode, count, pts, paint); | |
322 } | |
323 | |
324 void SkDeferredCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) { | |
325 SkRect modRect = rect; | |
326 this->flush_check(&modRect, &paint); | |
327 fCanvas->drawRect(modRect, paint); | |
328 } | |
329 | |
330 void SkDeferredCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) { | |
331 SkRect modRect = rect; | |
332 this->flush_check(&modRect, &paint, kNoClip_Flag); | |
333 fCanvas->drawOval(modRect, paint); | |
334 } | |
335 | |
336 static SkRRect make_offset(const SkRRect& src, SkScalar dx, SkScalar dy) { | |
337 SkRRect dst = src; | |
338 dst.offset(dx, dy); | |
339 return dst; | |
340 } | |
341 | |
342 void SkDeferredCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { | |
343 SkRect modRect = rrect.getBounds(); | |
344 this->flush_check(&modRect, &paint, kNoClip_Flag); | |
345 fCanvas->drawRRect(make_offset(rrect, | |
346 modRect.x() - rrect.getBounds().x(), | |
347 modRect.y() - rrect.getBounds().y()), paint); | |
348 } | |
349 | |
350 void SkDeferredCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) { | |
351 this->flush_all(); | |
352 fCanvas->drawDRRect(outer, inner, paint); | |
353 } | |
354 | |
355 void SkDeferredCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { | |
356 if (path.isInverseFillType()) { | |
357 this->flush_before_saves(); | |
358 } else { | |
359 SkRect modRect = path.getBounds(); | |
360 this->flush_check(&modRect, &paint, kNoClip_Flag | kNoTranslate_Flag | k NoScale_Flag); | |
361 } | |
362 fCanvas->drawPath(path, paint); | |
363 } | |
364 | |
365 void SkDeferredCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, | |
366 const SkPaint* paint) { | |
367 const SkScalar w = SkIntToScalar(bitmap.width()); | |
368 const SkScalar h = SkIntToScalar(bitmap.height()); | |
369 SkRect bounds = SkRect::MakeXYWH(x, y, w, h); | |
370 this->flush_check(&bounds, paint, kNoClip_Flag); | |
371 if (bounds.width() == w && bounds.height() == h) { | |
372 fCanvas->drawBitmap(bitmap, bounds.x(), bounds.y(), paint); | |
373 } else { | |
374 fCanvas->drawBitmapRect(bitmap, bounds, paint); | |
375 } | |
376 } | |
377 | |
378 void SkDeferredCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* sr c, const SkRect& dst, | |
379 const SkPaint* paint, SrcRectConstraint cons traint) { | |
380 SkRect modRect = dst; | |
381 this->flush_check(&modRect, paint, kNoClip_Flag); | |
382 fCanvas->legacy_drawBitmapRect(bitmap, src, modRect, paint, constraint); | |
383 } | |
384 | |
385 void SkDeferredCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& c enter, | |
386 const SkRect& dst, const SkPaint* paint) { | |
387 SkRect modRect = dst; | |
388 this->flush_check(&modRect, paint, kNoClip_Flag); | |
389 fCanvas->drawBitmapNine(bitmap, center, modRect, paint); | |
390 } | |
391 | |
392 void SkDeferredCanvas::onDrawImageNine(const SkImage* image, const SkIRect& cent er, | |
393 const SkRect& dst, const SkPaint* paint) { | |
394 SkRect modRect = dst; | |
395 this->flush_check(&modRect, paint, kNoClip_Flag); | |
396 fCanvas->drawImageNine(image, center, modRect, paint); | |
397 } | |
398 | |
399 void SkDeferredCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, | |
400 const SkPaint* paint) { | |
401 const SkScalar w = SkIntToScalar(image->width()); | |
402 const SkScalar h = SkIntToScalar(image->height()); | |
403 SkRect bounds = SkRect::MakeXYWH(x, y, w, h); | |
404 this->flush_check(&bounds, paint, kNoClip_Flag); | |
405 if (bounds.width() == w && bounds.height() == h) { | |
406 fCanvas->drawImage(image, bounds.x(), bounds.y(), paint); | |
407 } else { | |
408 fCanvas->drawImageRect(image, bounds, paint); | |
409 } | |
410 } | |
411 | |
412 void SkDeferredCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, | |
413 const SkPaint* paint, SrcRectConstraint const raint) { | |
414 SkRect modRect = dst; | |
415 this->flush_check(&modRect, paint, kNoClip_Flag); | |
416 fCanvas->legacy_drawImageRect(image, src, modRect, paint, constraint); | |
417 } | |
418 | |
419 void SkDeferredCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, | |
420 const SkPaint& paint) { | |
421 this->flush_translate(&x, &y, paint); | |
422 fCanvas->drawText(text, byteLength, x, y, paint); | |
423 } | |
424 | |
425 void SkDeferredCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], | |
426 const SkPaint& paint) { | |
427 this->flush_before_saves(); | |
428 fCanvas->drawPosText(text, byteLength, pos, paint); | |
429 } | |
430 | |
431 void SkDeferredCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], | |
432 SkScalar constY, const SkPaint& paint) { | |
433 this->flush_before_saves(); | |
434 fCanvas->drawPosTextH(text, byteLength, xpos, constY, paint); | |
435 } | |
436 | |
437 void SkDeferredCanvas::onDrawTextOnPath(const void* text, size_t byteLength, con st SkPath& path, | |
438 const SkMatrix* matrix, const SkPaint& paint ) { | |
439 this->flush_before_saves(); | |
440 fCanvas->drawTextOnPath(text, byteLength, path, matrix, paint); | |
441 } | |
442 | |
443 void SkDeferredCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScal ar y, | |
444 const SkPaint &paint) { | |
445 this->flush_translate(&x, &y, blob->bounds(), &paint); | |
446 fCanvas->drawTextBlob(blob, x, y, paint); | |
447 } | |
448 | |
449 #include "SkPicture.h" | |
450 #include "SkCanvasPriv.h" | |
451 void SkDeferredCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* m atrix, | |
452 const SkPaint* paint) { | |
453 #if 1 | |
454 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); | |
455 picture->playback(this); | |
456 #else | |
457 this->flush_before_saves(); | |
458 fCanvas->drawPicture(picture, matrix, paint); | |
459 #endif | |
460 } | |
461 | |
462 void SkDeferredCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matr ix) { | |
463 // TODO: investigate culling and applying concat to the matrix | |
464 #if 1 | |
465 drawable->draw(this, matrix); | |
466 #else | |
467 this->flush_before_saves(); | |
468 fCanvas->drawDrawable(drawable, matrix); | |
469 #endif | |
470 } | |
471 | |
472 void SkDeferredCanvas::onDrawAtlas(const SkImage* image, const SkRSXform xform[] , | |
473 const SkRect rects[], const SkColor colors[], | |
474 int count, SkXfermode::Mode mode, | |
475 const SkRect* cull, const SkPaint* paint) { | |
476 this->flush_before_saves(); | |
477 fCanvas->drawAtlas(image, xform, rects, colors, count, mode, cull, paint); | |
478 } | |
479 | |
480 void SkDeferredCanvas::onDrawVertices(VertexMode vmode, int vertexCount, | |
481 const SkPoint vertices[], const SkPoint texs[] , | |
482 const SkColor colors[], SkXfermode* xmode, | |
483 const uint16_t indices[], int indexCount, | |
484 const SkPaint& paint) { | |
485 this->flush_before_saves(); | |
486 fCanvas->drawVertices(vmode, vertexCount, vertices, texs, colors, xmode, | |
487 indices, indexCount, paint); | |
488 } | |
489 | |
490 void SkDeferredCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor color s[4], | |
491 const SkPoint texCoords[4], SkXfermode* xmode, | |
492 const SkPaint& paint) { | |
493 this->flush_before_saves(); | |
494 fCanvas->drawPatch(cubics, colors, texCoords, xmode, paint); | |
495 } | |
496 | |
497 void SkDeferredCanvas::onDrawAnnotation(const SkRect& rect, const char key[], Sk Data* data) { | |
498 this->flush_all(); | |
499 fCanvas->drawAnnotation(rect, key, data); | |
500 } | |
501 | |
502 #ifdef SK_SUPPORT_LEGACY_DRAWFILTER | |
503 SkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) { | |
504 fCanvas->setDrawFilter(filter); | |
505 return this->INHERITED::setDrawFilter(filter); | |
506 } | |
507 #endif | |
508 | |
509 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
510 | |
511 sk_sp<SkSurface> SkDeferredCanvas::onNewSurface(const SkImageInfo& info, | |
512 const SkSurfaceProps& props) { | |
513 return fCanvas->makeSurface(info, &props); | |
514 } | |
515 SkISize SkDeferredCanvas::getBaseLayerSize() const { return fCanvas->getBaseLaye rSize(); } | |
516 bool SkDeferredCanvas::getClipBounds(SkRect* bounds) const { | |
517 return fCanvas->getClipBounds(bounds); | |
518 } | |
519 bool SkDeferredCanvas::getClipDeviceBounds(SkIRect* bounds) const { | |
520 return fCanvas->getClipDeviceBounds(bounds); | |
521 } | |
522 bool SkDeferredCanvas::isClipEmpty() const { return fCanvas->isClipEmpty(); } | |
523 bool SkDeferredCanvas::isClipRect() const { return fCanvas->isClipRect(); } | |
524 bool SkDeferredCanvas::onPeekPixels(SkPixmap* pixmap) { return fCanvas->peekPixe ls(pixmap); } | |
525 bool SkDeferredCanvas::onAccessTopLayerPixels(SkPixmap* pixmap) { | |
526 SkImageInfo info; | |
527 size_t rowBytes; | |
528 SkIPoint* origin = nullptr; | |
529 void* addr = fCanvas->accessTopLayerPixels(&info, &rowBytes, origin); | |
530 if (addr) { | |
531 *pixmap = SkPixmap(info, addr, rowBytes); | |
532 return true; | |
533 } | |
534 return false; | |
535 } | |
536 SkImageInfo SkDeferredCanvas::onImageInfo() const { return fCanvas->imageInfo(); } | |
537 bool SkDeferredCanvas::onGetProps(SkSurfaceProps* props) const { return fCanvas- >getProps(props); } | |
538 void SkDeferredCanvas::onFlush() { return fCanvas->flush(); } | |
OLD | NEW |