Home | History | Annotate | Download | only in core
      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 
     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 
     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 
     29 void SkBBoxHierarchyRecord::willSave(SaveFlags flags) {
     30     fStateTree->appendSave();
     31     this->INHERITED::willSave(flags);
     32 }
     33 
     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 
     62 void SkBBoxHierarchyRecord::willRestore() {
     63     fStateTree->appendRestore();
     64     this->INHERITED::willRestore();
     65 }
     66 
     67 void SkBBoxHierarchyRecord::didConcat(const SkMatrix& matrix) {
     68     fStateTree->appendTransform(getTotalMatrix());
     69     INHERITED::didConcat(matrix);
     70 }
     71 
     72 void SkBBoxHierarchyRecord::didSetMatrix(const SkMatrix& matrix) {
     73     fStateTree->appendTransform(getTotalMatrix());
     74     INHERITED::didSetMatrix(matrix);
     75 }
     76 
     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 
     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 
     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 
     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 
    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