/* * 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 "gm.h" #include "Resources.h" #include "SampleCode.h" #include "SkCanvas.h" #include "SkColorFilter.h" #include "SkColorPriv.h" #include "SkData.h" #include "SkDecodingImageGenerator.h" #include "SkDumpCanvas.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 "SkStream.h" #include "SkTime.h" #include "SkTypeface.h" #include "SkUtils.h" #include "SkView.h" #include "SkXMLParser.h" #include "SkXfermode.h" /////////////////////////////////////////////////////////////////////////////// static SkBitmap load_bitmap() { SkBitmap bm; SkString resourcePath = GetResourcePath(); SkString path = SkOSPath::SkPathJoin(resourcePath.c_str(), "mandrill_512.png"); SkAutoDataUnref data(SkData::NewFromFileName(path.c_str())); if (data.get() != NULL) { SkInstallDiscardablePixelRef(SkDecodingImageGenerator::Create( data, SkDecodingImageGenerator::Options()), &bm); } return bm; } static void drawCircle(SkCanvas* canvas, int r, SkColor color) { SkPaint paint; paint.setAntiAlias(true); paint.setColor(color); canvas->drawCircle(SkIntToScalar(r), SkIntToScalar(r), SkIntToScalar(r), paint); } class PictureView : public SampleView { SkBitmap fBitmap; public: PictureView() { fBitmap = load_bitmap(); SkPictureRecorder recorder; recorder.beginRecording(100, 100, NULL, 0); fSubPicture = recorder.endRecording(); SkCanvas* canvas = recorder.beginRecording(100, 100, NULL, 0); SkPaint paint; paint.setAntiAlias(true); canvas->drawBitmap(fBitmap, 0, 0, NULL); drawCircle(canvas, 50, SK_ColorBLACK); canvas->drawPicture(fSubPicture); canvas->translate(SkIntToScalar(50), 0); canvas->drawPicture(fSubPicture); canvas->translate(0, SkIntToScalar(50)); canvas->drawPicture(fSubPicture); canvas->translate(SkIntToScalar(-50), 0); canvas->drawPicture(fSubPicture); fPicture = recorder.endRecording(); // fPicture now has (4) references to fSubPicture. We can release our ref, // and just unref fPicture in our destructor, and it will in turn take care of // the other references to fSubPicture fSubPicture->unref(); } virtual ~PictureView() { fPicture->unref(); } protected: // overrides from SkEventSink virtual bool onQuery(SkEvent* evt) { if (SampleCode::TitleQ(*evt)) { SampleCode::TitleR(evt, "Picture"); return true; } return this->INHERITED::onQuery(evt); } void drawSomething(SkCanvas* canvas) { SkPaint paint; canvas->save(); canvas->scale(0.5f, 0.5f); canvas->drawBitmap(fBitmap, 0, 0, NULL); canvas->restore(); const char beforeStr[] = "before circle"; const char afterStr[] = "after circle"; paint.setAntiAlias(true); paint.setColor(SK_ColorRED); canvas->drawData(beforeStr, sizeof(beforeStr)); canvas->drawCircle(SkIntToScalar(50), SkIntToScalar(50), SkIntToScalar(40), paint); canvas->drawData(afterStr, sizeof(afterStr)); paint.setColor(SK_ColorBLACK); paint.setTextSize(SkIntToScalar(40)); canvas->drawText("Picture", 7, SkIntToScalar(50), SkIntToScalar(62), paint); } virtual void onDrawContent(SkCanvas* canvas) { this->drawSomething(canvas); SkPictureRecorder recorder; this->drawSomething(recorder.beginRecording(100, 100, NULL, 0)); SkAutoTUnref<SkPicture> pict(recorder.endRecording()); canvas->save(); canvas->translate(SkIntToScalar(300), SkIntToScalar(50)); canvas->scale(-SK_Scalar1, -SK_Scalar1); canvas->translate(-SkIntToScalar(100), -SkIntToScalar(50)); canvas->drawPicture(pict); canvas->restore(); canvas->save(); canvas->translate(SkIntToScalar(200), SkIntToScalar(150)); canvas->scale(SK_Scalar1, -SK_Scalar1); canvas->translate(0, -SkIntToScalar(50)); canvas->drawPicture(pict); canvas->restore(); canvas->save(); canvas->translate(SkIntToScalar(100), SkIntToScalar(100)); canvas->scale(-SK_Scalar1, SK_Scalar1); canvas->translate(-SkIntToScalar(100), 0); canvas->drawPicture(pict); canvas->restore(); #ifdef SK_DEVELOPER if (false) { SkDebugfDumper dumper; SkDumpCanvas dumpCanvas(&dumper); dumpCanvas.drawPicture(pict); } #endif // This used to re-record the sub-picture and redraw the parent // A capability that is now forbidden! SkRandom rand(SampleCode::GetAnimTime()); canvas->translate(SkIntToScalar(10), SkIntToScalar(250)); canvas->drawPicture(fPicture); delayInval(500); } private: #define INVAL_ALL_TYPE "inval-all" void delayInval(SkMSec delay) { (new SkEvent(INVAL_ALL_TYPE, this->getSinkID()))->postDelay(delay); } virtual bool onEvent(const SkEvent& evt) { if (evt.isType(INVAL_ALL_TYPE)) { this->inval(NULL); return true; } return this->INHERITED::onEvent(evt); } SkPicture* fPicture; SkPicture* fSubPicture; typedef SampleView INHERITED; }; ////////////////////////////////////////////////////////////////////////////// static SkView* MyFactory() { return new PictureView; } static SkViewRegister reg(MyFactory);