gfx/skia/trunk/src/core/SkDeviceLooper.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/core/SkDeviceLooper.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,131 @@
     1.4 +/*
     1.5 + * Copyright 2013 Google Inc.
     1.6 + *
     1.7 + * Use of this source code is governed by a BSD-style license that can be
     1.8 + * found in the LICENSE file.
     1.9 + */
    1.10 +
    1.11 +#include "SkDeviceLooper.h"
    1.12 +
    1.13 +SkDeviceLooper::SkDeviceLooper(const SkBitmap& base,
    1.14 +                               const SkRasterClip& rc,
    1.15 +                               const SkIRect& bounds, bool aa)
    1.16 +: fBaseBitmap(base)
    1.17 +, fBaseRC(rc)
    1.18 +, fDelta(aa ? kAA_Delta : kBW_Delta)
    1.19 +{
    1.20 +    // sentinels that next() has not yet been called, and so our mapper functions
    1.21 +    // should not be called either.
    1.22 +    fCurrBitmap = NULL;
    1.23 +    fCurrRC = NULL;
    1.24 +
    1.25 +    if (!rc.isEmpty()) {
    1.26 +        // clip must be contained by the bitmap
    1.27 +        SkASSERT(SkIRect::MakeWH(base.width(), base.height()).contains(rc.getBounds()));
    1.28 +    }
    1.29 +
    1.30 +    if (rc.isEmpty() || !fClippedBounds.intersect(bounds, rc.getBounds())) {
    1.31 +        fState = kDone_State;
    1.32 +    } else if (this->fitsInDelta(fClippedBounds)) {
    1.33 +        fState = kSimple_State;
    1.34 +    } else {
    1.35 +        // back up by 1 DX, so that next() will put us in a correct starting
    1.36 +        // position.
    1.37 +        fCurrOffset.set(fClippedBounds.left() - fDelta,
    1.38 +                        fClippedBounds.top());
    1.39 +        fState = kComplex_State;
    1.40 +    }
    1.41 +}
    1.42 +
    1.43 +SkDeviceLooper::~SkDeviceLooper() {
    1.44 +}
    1.45 +
    1.46 +void SkDeviceLooper::mapRect(SkRect* dst, const SkRect& src) const {
    1.47 +    SkASSERT(kDone_State != fState);
    1.48 +    SkASSERT(fCurrBitmap);
    1.49 +    SkASSERT(fCurrRC);
    1.50 +
    1.51 +    *dst = src;
    1.52 +    dst->offset(SkIntToScalar(-fCurrOffset.fX),
    1.53 +                SkIntToScalar(-fCurrOffset.fY));
    1.54 +}
    1.55 +
    1.56 +void SkDeviceLooper::mapMatrix(SkMatrix* dst, const SkMatrix& src) const {
    1.57 +    SkASSERT(kDone_State != fState);
    1.58 +    SkASSERT(fCurrBitmap);
    1.59 +    SkASSERT(fCurrRC);
    1.60 +
    1.61 +    *dst = src;
    1.62 +    dst->postTranslate(SkIntToScalar(-fCurrOffset.fX),
    1.63 +                       SkIntToScalar(-fCurrOffset.fY));
    1.64 +}
    1.65 +
    1.66 +bool SkDeviceLooper::computeCurrBitmapAndClip() {
    1.67 +    SkASSERT(kComplex_State == fState);
    1.68 +
    1.69 +    SkIRect r = SkIRect::MakeXYWH(fCurrOffset.x(), fCurrOffset.y(),
    1.70 +                                  fDelta, fDelta);
    1.71 +    if (!fBaseBitmap.extractSubset(&fSubsetBitmap, r)) {
    1.72 +        fSubsetRC.setEmpty();
    1.73 +    } else {
    1.74 +        fSubsetBitmap.lockPixels();
    1.75 +        fBaseRC.translate(-r.left(), -r.top(), &fSubsetRC);
    1.76 +        (void)fSubsetRC.op(SkIRect::MakeWH(fDelta, fDelta),
    1.77 +                           SkRegion::kIntersect_Op);
    1.78 +    }
    1.79 +
    1.80 +    fCurrBitmap = &fSubsetBitmap;
    1.81 +    fCurrRC = &fSubsetRC;
    1.82 +    return !fCurrRC->isEmpty();
    1.83 +}
    1.84 +
    1.85 +static bool next_tile(const SkIRect& boundary, int delta, SkIPoint* offset) {
    1.86 +    // can we move to the right?
    1.87 +    if (offset->x() + delta < boundary.right()) {
    1.88 +        offset->fX += delta;
    1.89 +        return true;
    1.90 +    }
    1.91 +
    1.92 +    // reset to the left, but move down a row
    1.93 +    offset->fX = boundary.left();
    1.94 +    if (offset->y() + delta < boundary.bottom()) {
    1.95 +        offset->fY += delta;
    1.96 +        return true;
    1.97 +    }
    1.98 +
    1.99 +    // offset is now outside of boundary, so we're done
   1.100 +    return false;
   1.101 +}
   1.102 +
   1.103 +bool SkDeviceLooper::next() {
   1.104 +    switch (fState) {
   1.105 +        case kDone_State:
   1.106 +            // in theory, we should not get called here, since we must have
   1.107 +            // previously returned false, but we check anyway.
   1.108 +            break;
   1.109 +
   1.110 +        case kSimple_State:
   1.111 +            // first time for simple
   1.112 +            if (NULL == fCurrBitmap) {
   1.113 +                fCurrBitmap = &fBaseBitmap;
   1.114 +                fCurrRC = &fBaseRC;
   1.115 +                fCurrOffset.set(0, 0);
   1.116 +                return true;
   1.117 +            }
   1.118 +            // 2nd time for simple, we are done
   1.119 +            break;
   1.120 +
   1.121 +        case kComplex_State:
   1.122 +            // need to propogate fCurrOffset through clippedbounds
   1.123 +            // left to right, until we wrap around and move down
   1.124 +
   1.125 +            while (next_tile(fClippedBounds, fDelta, &fCurrOffset)) {
   1.126 +                if (this->computeCurrBitmapAndClip()) {
   1.127 +                    return true;
   1.128 +                }
   1.129 +            }
   1.130 +            break;
   1.131 +    }
   1.132 +    fState = kDone_State;
   1.133 +    return false;
   1.134 +}

mercurial