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     SkPictureStateTree::Draw* draw = fStateTree->appendDraw(this->writeStream().bytesWritten());
     24     fBoundingHierarchy->insert(draw, bounds, true);
     25 }
     26 
     27 void SkBBoxHierarchyRecord::willSave() {
     28     fStateTree->appendSave();
     29     this->INHERITED::willSave();
     30 }
     31 
     32 SkCanvas::SaveLayerStrategy SkBBoxHierarchyRecord::willSaveLayer(const SkRect* bounds,
     33                                                                  const SkPaint* paint,
     34                                                                  SaveFlags flags) {
     35     // For now, assume all filters affect transparent black.
     36     // FIXME: This could be made less conservative as an optimization.
     37     bool paintAffectsTransparentBlack = paint &&
     38         ((paint->getImageFilter()) ||
     39          (paint->getColorFilter()));
     40     bool needToHandleBBox = paintAffectsTransparentBlack;
     41     if (!needToHandleBBox && paint) {
     42       // Unusual Xfermodes require us to process a saved layer
     43       // even with operations outisde the clip.
     44       // For example, DstIn is used by masking layers.
     45       // https://code.google.com/p/skia/issues/detail?id=1291
     46       SkXfermode* xfermode = paint->getXfermode();
     47       SkXfermode::Mode mode;
     48       // SrcOver is the common case with a NULL xfermode, so we should
     49       // make that the fast path and bypass the mode extraction and test.
     50       if (xfermode && xfermode->asMode(&mode)) {
     51         switch (mode) {
     52           case SkXfermode::kClear_Mode:
     53           case SkXfermode::kSrc_Mode:
     54           case SkXfermode::kSrcIn_Mode:
     55           case SkXfermode::kDstIn_Mode:
     56           case SkXfermode::kSrcOut_Mode:
     57           case SkXfermode::kDstATop_Mode:
     58           case SkXfermode::kModulate_Mode:
     59             needToHandleBBox = true;
     60             break;
     61           default:
     62             break;
     63         }
     64       }
     65     }
     66 
     67     SkRect drawBounds;
     68     if (needToHandleBBox) {
     69         SkIRect deviceBounds;
     70         this->getClipDeviceBounds(&deviceBounds);
     71         drawBounds.set(deviceBounds);
     72     }
     73     fStateTree->appendSaveLayer(this->writeStream().bytesWritten());
     74     SkCanvas::SaveLayerStrategy strategy = this->INHERITED::willSaveLayer(bounds, paint, flags);
     75     if (needToHandleBBox) {
     76         this->handleBBox(drawBounds);
     77         this->addNoOp();
     78     }
     79     return strategy;
     80 }
     81 
     82 void SkBBoxHierarchyRecord::willRestore() {
     83     fStateTree->appendRestore();
     84     this->INHERITED::willRestore();
     85 }
     86 
     87 void SkBBoxHierarchyRecord::didConcat(const SkMatrix& matrix) {
     88     fStateTree->appendTransform(getTotalMatrix());
     89     INHERITED::didConcat(matrix);
     90 }
     91 
     92 void SkBBoxHierarchyRecord::didSetMatrix(const SkMatrix& matrix) {
     93     fStateTree->appendTransform(getTotalMatrix());
     94     INHERITED::didSetMatrix(matrix);
     95 }
     96 
     97 void SkBBoxHierarchyRecord::onClipRect(const SkRect& rect,
     98                                        SkRegion::Op op,
     99                                        ClipEdgeStyle edgeStyle) {
    100     fStateTree->appendClip(this->writeStream().bytesWritten());
    101     this->INHERITED::onClipRect(rect, op, edgeStyle);
    102 }
    103 
    104 void SkBBoxHierarchyRecord::onClipRegion(const SkRegion& region,
    105                                          SkRegion::Op op) {
    106     fStateTree->appendClip(this->writeStream().bytesWritten());
    107     this->INHERITED::onClipRegion(region, op);
    108 }
    109 
    110 void SkBBoxHierarchyRecord::onClipPath(const SkPath& path,
    111                                        SkRegion::Op op,
    112                                        ClipEdgeStyle edgeStyle) {
    113     fStateTree->appendClip(this->writeStream().bytesWritten());
    114     this->INHERITED::onClipPath(path, op, edgeStyle);
    115 }
    116 
    117 void SkBBoxHierarchyRecord::onClipRRect(const SkRRect& rrect,
    118                                         SkRegion::Op op,
    119                                         ClipEdgeStyle edgeStyle) {
    120     fStateTree->appendClip(this->writeStream().bytesWritten());
    121     this->INHERITED::onClipRRect(rrect, op, edgeStyle);
    122 }
    123 
    124 bool SkBBoxHierarchyRecord::shouldRewind(void* data) {
    125     // SkBBoxHierarchy::rewindInserts is called by SkPicture after the
    126     // SkPicture has rewound its command stream.  To match that rewind in the
    127     // BBH, we rewind all draws that reference commands that were recorded
    128     // past the point to which the SkPicture has rewound, which is given by
    129     // writeStream().bytesWritten().
    130     SkPictureStateTree::Draw* draw = static_cast<SkPictureStateTree::Draw*>(data);
    131     return draw->fOffset >= writeStream().bytesWritten();
    132 }
    133