C++程序  |  149行  |  4.66 KB

/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkRRect.h"

namespace skiagm {

///////////////////////////////////////////////////////////////////////////////

class RRectGM : public GM {
public:
    RRectGM(bool doAA, bool doClip) : fDoAA(doAA), fDoClip(doClip) {
        this->setBGColor(0xFFDDDDDD);
        this->setUpRRects();
    }

protected:
    SkString onShortName() {
        SkString name("rrect");
        if (fDoClip) {
            name.append("_clip");
        }
        if (fDoAA) {
            name.append("_aa");
        } else {
            name.append("_bw");
        }

        return name;
    }

    virtual SkISize onISize() { return make_isize(kImageWidth, kImageHeight); }

    virtual void onDraw(SkCanvas* canvas) {

        SkPaint paint;
        // when clipping the AA is pushed into the clip operation
        paint.setAntiAlias(fDoClip ? false : fDoAA);

        static const SkRect kMaxTileBound = SkRect::MakeWH(SkIntToScalar(kTileX), SkIntToScalar(kTileY));

        int curRRect = 0;
        for (int y = 1; y < kImageHeight; y += kTileY) {
            for (int x = 1; x < kImageWidth; x += kTileX) {
                if (curRRect >= kNumRRects) {
                    break;
                }
                SkASSERT(kMaxTileBound.contains(fRRects[curRRect].getBounds()));

                canvas->save();
                    canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
                    if (fDoClip) {
                        canvas->clipRRect(fRRects[curRRect], SkRegion::kReplace_Op, fDoAA);
                        canvas->drawRect(kMaxTileBound, paint);
                    } else {
                        canvas->drawRRect(fRRects[curRRect], paint);
                    }
                    ++curRRect;
                canvas->restore();
            }
        }
    }

    void setUpRRects() {
        // each RRect must fit in a 0x0 -> (kTileX-2)x(kTileY-2) block. These will be tiled across
        // the screen in kTileX x kTileY tiles. The extra empty pixels on each side are for AA.

        // simple cases
        fRRects[0].setRect(SkRect::MakeWH(kTileX-2, kTileY-2));
        fRRects[1].setOval(SkRect::MakeWH(kTileX-2, kTileY-2));
        fRRects[2].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 10);

        // The first complex case needs special handling since it is a square
        fRRects[kNumSimpleCases].setRectRadii(SkRect::MakeWH(kTileY-2, kTileY-2), gRadii[0]);
        for (size_t i = 1; i < SK_ARRAY_COUNT(gRadii); ++i) {
            fRRects[kNumSimpleCases+i].setRectRadii(SkRect::MakeWH(kTileX-2, kTileY-2), gRadii[i]);
        }
    }

private:
    bool fDoAA;
    bool fDoClip;   // use clipRRect & drawRect instead of drawRRect

    static const int kImageWidth = 640;
    static const int kImageHeight = 480;

    static const int kTileX = 80;
    static const int kTileY = 40;

    static const int kNumSimpleCases = 3;
    static const int kNumComplexCases = 19;
    static const SkVector gRadii[kNumComplexCases][4];

    static const int kNumRRects = kNumSimpleCases + kNumComplexCases;
    SkRRect fRRects[kNumRRects];

    typedef GM INHERITED;
};

// Radii for the various test cases. Order is UL, UR, LR, LL
const SkVector RRectGM::gRadii[kNumComplexCases][4] = {
    // a circle
    { { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY } },

    // odd ball cases
    { { 8, 8 }, { 32, 32 }, { 8, 8 }, { 32, 32 } },
    { { 16, 8 }, { 8, 16 }, { 16, 8 }, { 8, 16 } },
    { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 32, 32 } },

    // UL
    { { 30, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
    { { 30, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
    { { 15, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },

    // UR
    { { 0, 0 }, { 30, 30 }, { 0, 0 }, { 0, 0 } },
    { { 0, 0 }, { 30, 15 }, { 0, 0 }, { 0, 0 } },
    { { 0, 0 }, { 15, 30 }, { 0, 0 }, { 0, 0 } },

    // LR
    { { 0, 0 }, { 0, 0 }, { 30, 30 }, { 0, 0 } },
    { { 0, 0 }, { 0, 0 }, { 30, 15 }, { 0, 0 } },
    { { 0, 0 }, { 0, 0 }, { 15, 30 }, { 0, 0 } },

    // LL
    { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 30 } },
    { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 15 } },
    { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 30 } },

    // over-sized radii
    { { 0, 0 }, { 100, 400 }, { 0, 0 }, { 0, 0 } },
    { { 0, 0 }, { 400, 400 }, { 0, 0 }, { 0, 0 } },
    { { 400, 400 }, { 400, 400 }, { 400, 400 }, { 400, 400 } },
};

///////////////////////////////////////////////////////////////////////////////

DEF_GM( return new RRectGM(false, false); )
DEF_GM( return new RRectGM(true, false); )
DEF_GM( return new RRectGM(false, true); )
DEF_GM( return new RRectGM(true, true); )

}