1
2 /*
3 * Copyright 2012 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9 #include "SkBBoxHierarchyRecord.h"
10 #include "SkPictureStateTree.h"
11
SkBBoxHierarchyRecord(const SkISize & size,uint32_t recordFlags,SkBBoxHierarchy * h)12 SkBBoxHierarchyRecord::SkBBoxHierarchyRecord(const SkISize& size,
13 uint32_t recordFlags,
14 SkBBoxHierarchy* h)
15 : INHERITED(size, recordFlags) {
16 fStateTree = SkNEW(SkPictureStateTree);
17 fBoundingHierarchy = h;
18 fBoundingHierarchy->ref();
19 fBoundingHierarchy->setClient(this);
20 }
21
handleBBox(const SkRect & bounds)22 void SkBBoxHierarchyRecord::handleBBox(const SkRect& bounds) {
23 SkIRect r;
24 bounds.roundOut(&r);
25 SkPictureStateTree::Draw* draw = fStateTree->appendDraw(this->writeStream().bytesWritten());
26 fBoundingHierarchy->insert(draw, r, true);
27 }
28
willSave(SaveFlags flags)29 void SkBBoxHierarchyRecord::willSave(SaveFlags flags) {
30 fStateTree->appendSave();
31 this->INHERITED::willSave(flags);
32 }
33
willSaveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags)34 SkCanvas::SaveLayerStrategy SkBBoxHierarchyRecord::willSaveLayer(const SkRect* bounds,
35 const SkPaint* paint,
36 SaveFlags flags) {
37 // For now, assume all filters affect transparent black.
38 // FIXME: This could be made less conservative as an optimization.
39 bool paintAffectsTransparentBlack = NULL != paint &&
40 ((NULL != paint->getImageFilter()) ||
41 (NULL != paint->getColorFilter()));
42 SkRect drawBounds;
43 if (paintAffectsTransparentBlack) {
44 if (bounds) {
45 drawBounds = *bounds;
46 this->getTotalMatrix().mapRect(&drawBounds);
47 } else {
48 SkIRect deviceBounds;
49 this->getClipDeviceBounds(&deviceBounds);
50 drawBounds.set(deviceBounds);
51 }
52 }
53 fStateTree->appendSaveLayer(this->writeStream().bytesWritten());
54 SkCanvas::SaveLayerStrategy strategy = this->INHERITED::willSaveLayer(bounds, paint, flags);
55 if (paintAffectsTransparentBlack) {
56 this->handleBBox(drawBounds);
57 this->addNoOp();
58 }
59 return strategy;
60 }
61
willRestore()62 void SkBBoxHierarchyRecord::willRestore() {
63 fStateTree->appendRestore();
64 this->INHERITED::willRestore();
65 }
66
didConcat(const SkMatrix & matrix)67 void SkBBoxHierarchyRecord::didConcat(const SkMatrix& matrix) {
68 fStateTree->appendTransform(getTotalMatrix());
69 INHERITED::didConcat(matrix);
70 }
71
didSetMatrix(const SkMatrix & matrix)72 void SkBBoxHierarchyRecord::didSetMatrix(const SkMatrix& matrix) {
73 fStateTree->appendTransform(getTotalMatrix());
74 INHERITED::didSetMatrix(matrix);
75 }
76
onClipRect(const SkRect & rect,SkRegion::Op op,ClipEdgeStyle edgeStyle)77 void SkBBoxHierarchyRecord::onClipRect(const SkRect& rect,
78 SkRegion::Op op,
79 ClipEdgeStyle edgeStyle) {
80 fStateTree->appendClip(this->writeStream().bytesWritten());
81 this->INHERITED::onClipRect(rect, op, edgeStyle);
82 }
83
onClipRegion(const SkRegion & region,SkRegion::Op op)84 void SkBBoxHierarchyRecord::onClipRegion(const SkRegion& region,
85 SkRegion::Op op) {
86 fStateTree->appendClip(this->writeStream().bytesWritten());
87 this->INHERITED::onClipRegion(region, op);
88 }
89
onClipPath(const SkPath & path,SkRegion::Op op,ClipEdgeStyle edgeStyle)90 void SkBBoxHierarchyRecord::onClipPath(const SkPath& path,
91 SkRegion::Op op,
92 ClipEdgeStyle edgeStyle) {
93 fStateTree->appendClip(this->writeStream().bytesWritten());
94 this->INHERITED::onClipPath(path, op, edgeStyle);
95 }
96
onClipRRect(const SkRRect & rrect,SkRegion::Op op,ClipEdgeStyle edgeStyle)97 void SkBBoxHierarchyRecord::onClipRRect(const SkRRect& rrect,
98 SkRegion::Op op,
99 ClipEdgeStyle edgeStyle) {
100 fStateTree->appendClip(this->writeStream().bytesWritten());
101 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
102 }
103
shouldRewind(void * data)104 bool SkBBoxHierarchyRecord::shouldRewind(void* data) {
105 // SkBBoxHierarchy::rewindInserts is called by SkPicture after the
106 // SkPicture has rewound its command stream. To match that rewind in the
107 // BBH, we rewind all draws that reference commands that were recorded
108 // past the point to which the SkPicture has rewound, which is given by
109 // writeStream().bytesWritten().
110 SkPictureStateTree::Draw* draw = static_cast<SkPictureStateTree::Draw*>(data);
111 return draw->fOffset >= writeStream().bytesWritten();
112 }
113