C++程序  |  205行  |  5.95 KB

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

#include "SampleCode.h"
#include "SkDumpCanvas.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkOSFile.h"
#include "SkPath.h"
#include "SkPicture.h"
#include "SkPictureRecorder.h"
#include "SkRandom.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "SkColorPriv.h"
#include "SkColorFilter.h"
#include "SkTime.h"
#include "SkTypeface.h"
#include "SkXfermode.h"

#include "SkStream.h"
#include "SkSurface.h"
#include "SkXMLParser.h"

class PictFileView : public SampleView {
public:
    PictFileView(const char name[] = NULL)
        : fFilename(name)
        , fBBox(kNo_BBoxType)
        , fTileSize(SkSize::Make(0, 0)) {
        for (int i = 0; i < kBBoxTypeCount; ++i) {
            fPictures[i] = NULL;
        }
    }

    virtual ~PictFileView() {
        for (int i = 0; i < kBBoxTypeCount; ++i) {
            SkSafeUnref(fPictures[i]);
        }
    }

    virtual void onTileSizeChanged(const SkSize &tileSize) SK_OVERRIDE {
        if (tileSize != fTileSize) {
            fTileSize = tileSize;
            SkSafeSetNull(fPictures[kTileGrid_BBoxType]);
        }
    }

protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) SK_OVERRIDE {
        if (SampleCode::TitleQ(*evt)) {
            SkString name("P:");
            const char* basename = strrchr(fFilename.c_str(), SkPATH_SEPARATOR);
            name.append(basename ? basename+1: fFilename.c_str());
            switch (fBBox) {
            case kNo_BBoxType:
                // No name appended
                break;
            case kRTree_BBoxType:
                name.append(" <bbox: R>");
                break;
            case kQuadTree_BBoxType:
                name.append(" <bbox: Q>");
                break;
            case kTileGrid_BBoxType:
                name.append(" <bbox: T>");
                break;
            default:
                SkASSERT(false);
                break;
            }
            SampleCode::TitleR(evt, name.c_str());
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    virtual bool onEvent(const SkEvent& evt) SK_OVERRIDE {
        if (evt.isType("PictFileView::toggleBBox")) {
            fBBox = (BBoxType)((fBBox + 1) % kBBoxTypeCount);
            return true;
        }
        return this->INHERITED::onEvent(evt);
    }

    virtual void onDrawContent(SkCanvas* canvas) SK_OVERRIDE {
        SkASSERT(static_cast<int>(fBBox) < kBBoxTypeCount);
        SkPicture** picture = fPictures + fBBox;

        if (!*picture) {
            *picture = LoadPicture(fFilename.c_str(), fBBox);
        }
        if (*picture) {
            canvas->drawPicture(*picture);
        }
    }

private:
    enum BBoxType {
        kNo_BBoxType,
        kQuadTree_BBoxType,
        kRTree_BBoxType,
        kTileGrid_BBoxType,

        kLast_BBoxType = kTileGrid_BBoxType
    };
    static const int kBBoxTypeCount = kLast_BBoxType + 1;

    SkString    fFilename;
    SkPicture*  fPictures[kBBoxTypeCount];
    BBoxType    fBBox;
    SkSize      fTileSize;

    SkPicture* LoadPicture(const char path[], BBoxType bbox) {
        SkAutoTUnref<SkPicture> pic;

        SkBitmap bm;
        if (SkImageDecoder::DecodeFile(path, &bm)) {
            bm.setImmutable();
            SkPictureRecorder recorder;
            SkCanvas* can = recorder.beginRecording(bm.width(), bm.height(), NULL, 0);
            can->drawBitmap(bm, 0, 0, NULL);
            pic.reset(recorder.endRecording());
        } else {
            SkFILEStream stream(path);
            if (stream.isValid()) {
                pic.reset(SkPicture::CreateFromStream(&stream));
            } else {
                SkDebugf("coun't load picture at \"path\"\n", path);
            }

            if (false) {
                SkSurface* surf = SkSurface::NewRasterPMColor(pic->width(), pic->height());
                surf->getCanvas()->drawPicture(pic);
                surf->unref();
            }
            if (false) { // re-record
                SkPictureRecorder recorder;
                pic->draw(recorder.beginRecording(pic->width(), pic->height(), NULL, 0));
                SkAutoTUnref<SkPicture> p2(recorder.endRecording());

                SkString path2(path);
                path2.append(".new.skp");
                SkFILEWStream writer(path2.c_str());
                p2->serialize(&writer);
            }
        }

        if (NULL == pic) {
            return NULL;
        }

        SkAutoTDelete<SkBBHFactory> factory;
        switch (bbox) {
        case kNo_BBoxType:
            // no bbox playback necessary
            return pic.detach();
        case kRTree_BBoxType:
            factory.reset(SkNEW(SkRTreeFactory));
            break;
        case kQuadTree_BBoxType:
            factory.reset(SkNEW(SkQuadTreeFactory));
            break;
        case kTileGrid_BBoxType: {
            SkASSERT(!fTileSize.isEmpty());
            SkTileGridFactory::TileGridInfo gridInfo;
            gridInfo.fMargin = SkISize::Make(0, 0);
            gridInfo.fOffset = SkIPoint::Make(0, 0);
            gridInfo.fTileInterval = fTileSize.toRound();
            factory.reset(SkNEW_ARGS(SkTileGridFactory, (gridInfo)));
            break;
        }
        default:
            SkASSERT(false);
        }

        SkPictureRecorder recorder;
        pic->draw(recorder.beginRecording(pic->width(), pic->height(), factory.get(), 0));
        return recorder.endRecording();
    }

    typedef SampleView INHERITED;
};

SampleView* CreateSamplePictFileView(const char filename[]);
SampleView* CreateSamplePictFileView(const char filename[]) {
    return new PictFileView(filename);
}

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

#if 0
static SkView* MyFactory() { return new PictFileView; }
static SkViewRegister reg(MyFactory);
#endif