/* * Copyright 2013 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 "SkGradientShader.h" #include "SkBitmapAlphaThresholdShader.h" #include "SkTArray.h" #include "SkParsePath.h" class BitmapAlphaThresholdGM : public skiagm::GM { public: BitmapAlphaThresholdGM() { this->setBGColor(0xFF000000); } private: virtual uint32_t onGetFlags() const SK_OVERRIDE { // narrow this flags when the shader has a CPU implementation and // when it serializes. return kSkipPDF_Flag | kSkipPicture_Flag | kSkipPipe_Flag | kSkipPipeCrossProcess_Flag | kSkipTiled_Flag | kSkip565_Flag | kSkipScaledReplay_Flag | kSkipPDFRasterization_Flag | kGPUOnly_Flag; } virtual void onOnceBeforeDraw() SK_OVERRIDE { fBM.setConfig(SkBitmap::kARGB_8888_Config, 100, 100); if (!fBM.allocPixels()) { return; } SkCanvas canvas(fBM); SkPoint pts[] = { {0, 0}, {SkIntToScalar(fBM.width()), SkIntToScalar(fBM.height())} }; SkColor colors[] = {0x00000000, 0xffffffff}; SkShader* grad = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode); SkPaint gradPaint; gradPaint.setShader(grad)->unref(); gradPaint.setXfermodeMode(SkXfermode::kSrc_Mode); canvas.drawPaint(gradPaint); // Construct the region used as a mask. SkRegion bmpBoundsClip; bmpBoundsClip.setRect(0, 0, fBM.width(), fBM.height()); SkPath circlePath; SkScalar radius = SkScalarSqrt(SkIntToScalar(fBM.width() * fBM.height())) / 2; circlePath.addCircle(SkIntToScalar(fBM.width() / 2), SkIntToScalar(fBM.height() / 2), radius); fMask.setPath(circlePath, bmpBoundsClip); SkPath batPath; SkParsePath::FromSVGString( "M305.214,374.779c2.463,0,3.45,0.493,3.45,0.493l1.478-6.241c0,0,1.15,4.763,1.643,9.034" "c0.493,4.271,8.048,1.479,14.454,0.164c6.405-1.314,7.72-11.662,7.72-11.662h59.294c0,0-35.807,10.841-26.772,34.656" "c0,0-52.889-8.048-61.101,24.967h-0.001c-8.212-33.015-61.101-24.967-61.101-24.967c9.034-23.815-26.772-34.656-26.772-34.656" "h59.294c0,0,1.314,10.348,7.719,11.662c6.406,1.314,13.962,4.106,14.454-0.164c0.493-4.271,1.643-9.034,1.643-9.034l1.479,6.241" "c0,0,0.985-0.493,3.449-0.493H305.214L305.214,374.779z", &batPath); SkMatrix matrix; matrix.setTranslate(-208, -280); matrix.postScale(radius / 100, radius / 100); batPath.transform(matrix, &batPath); SkRegion batRegion; batRegion.setPath(batPath, bmpBoundsClip); fMask.op(batRegion, SkRegion::kDifference_Op); } virtual SkString onShortName() SK_OVERRIDE { return SkString("bat"); } virtual SkISize onISize() SK_OVERRIDE { return SkISize::Make(518, 735); } virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { SkTArray<SkMatrix> lms; lms.push_back().reset(); lms.push_back().setScale(SK_Scalar1 / 2, SK_Scalar1); lms.push_back().setScale(SK_Scalar1, 2 * SK_Scalar1); lms.push_back().setRotate(-SK_Scalar1 * 30); lms.push_back().setSkew(0, SK_Scalar1 / 5); static const SkScalar kMargin = 5 * SK_Scalar1; canvas->translate(kMargin, kMargin); canvas->save(); static const U8CPU kThresholds[] = { 0x0, 0x08, 0x40, 0x80, 0xC0, 0xF0, 0xFF }; for (size_t i = 0; i < SK_ARRAY_COUNT(kThresholds); ++i) { for (int j = 0; j < lms.count(); ++j) { SkRect rect; rect.fLeft = 0; rect.fTop = 0; rect.fRight = SkIntToScalar(fBM.width()); rect.fBottom = SkIntToScalar(fBM.height()); SkShader* thresh; // This SkShader currently only has a GPU implementation. if (canvas->getDevice()->accessRenderTarget()) { thresh = SkBitmapAlphaThresholdShader::Create(fBM, fMask, kThresholds[i]); } else { thresh = SkShader::CreateBitmapShader(fBM, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); } thresh->setLocalMatrix(lms[j]); SkPaint paint; paint.setShader(thresh)->unref(); canvas->drawRect(rect, paint); canvas->translate(SkIntToScalar(fBM.width() + kMargin), 0); } canvas->restore(); canvas->translate(0, SkIntToScalar(fBM.height() + kMargin)); canvas->save(); } } SkBitmap fBM; SkRegion fMask; typedef skiagm::GM INHERITED; }; ////////////////////////////////////////////////////////////////////////////// DEF_GM( return new BitmapAlphaThresholdGM(); )