1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "gm.h" 9 #include "SkGradientShader.h" 10 #include "SkBitmapAlphaThresholdShader.h" 11 #include "SkTArray.h" 12 #include "SkParsePath.h" 13 14 class BitmapAlphaThresholdGM : public skiagm::GM { 15 public: 16 BitmapAlphaThresholdGM() { 17 this->setBGColor(0xFF000000); 18 } 19 20 private: 21 virtual uint32_t onGetFlags() const SK_OVERRIDE { 22 // narrow this flags when the shader has a CPU implementation and 23 // when it serializes. 24 return 25 kSkipPDF_Flag | 26 kSkipPicture_Flag | 27 kSkipPipe_Flag | 28 kSkipPipeCrossProcess_Flag | 29 kSkipTiled_Flag | 30 kSkip565_Flag | 31 kSkipScaledReplay_Flag | 32 kSkipPDFRasterization_Flag | 33 34 kGPUOnly_Flag; 35 } 36 37 virtual void onOnceBeforeDraw() SK_OVERRIDE { 38 fBM.setConfig(SkBitmap::kARGB_8888_Config, 100, 100); 39 if (!fBM.allocPixels()) { 40 return; 41 } 42 SkCanvas canvas(fBM); 43 SkPoint pts[] = { {0, 0}, {SkIntToScalar(fBM.width()), SkIntToScalar(fBM.height())} }; 44 SkColor colors[] = {0x00000000, 0xffffffff}; 45 SkShader* grad = SkGradientShader::CreateLinear(pts, colors, NULL, 2, 46 SkShader::kClamp_TileMode); 47 SkPaint gradPaint; 48 gradPaint.setShader(grad)->unref(); 49 gradPaint.setXfermodeMode(SkXfermode::kSrc_Mode); 50 canvas.drawPaint(gradPaint); 51 52 // Construct the region used as a mask. 53 SkRegion bmpBoundsClip; 54 bmpBoundsClip.setRect(0, 0, fBM.width(), fBM.height()); 55 SkPath circlePath; 56 SkScalar radius = SkScalarSqrt(SkIntToScalar(fBM.width() * fBM.height())) / 2; 57 circlePath.addCircle(SkIntToScalar(fBM.width() / 2), 58 SkIntToScalar(fBM.height() / 2), 59 radius); 60 fMask.setPath(circlePath, bmpBoundsClip); 61 62 SkPath batPath; 63 SkParsePath::FromSVGString( 64 "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" 65 "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" 66 "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" 67 "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" 68 "c0,0,0.985-0.493,3.449-0.493H305.214L305.214,374.779z", 69 &batPath); 70 71 SkMatrix matrix; 72 matrix.setTranslate(-208, -280); 73 matrix.postScale(radius / 100, radius / 100); 74 batPath.transform(matrix, &batPath); 75 SkRegion batRegion; 76 batRegion.setPath(batPath, bmpBoundsClip); 77 78 fMask.op(batRegion, SkRegion::kDifference_Op); 79 } 80 81 virtual SkString onShortName() SK_OVERRIDE { 82 return SkString("bat"); 83 } 84 85 virtual SkISize onISize() SK_OVERRIDE { 86 return SkISize::Make(518, 735); 87 } 88 89 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 90 91 SkTArray<SkMatrix> lms; 92 lms.push_back().reset(); 93 lms.push_back().setScale(SK_Scalar1 / 2, SK_Scalar1); 94 lms.push_back().setScale(SK_Scalar1, 2 * SK_Scalar1); 95 lms.push_back().setRotate(-SK_Scalar1 * 30); 96 lms.push_back().setSkew(0, SK_Scalar1 / 5); 97 98 static const SkScalar kMargin = 5 * SK_Scalar1; 99 canvas->translate(kMargin, kMargin); 100 canvas->save(); 101 102 static const U8CPU kThresholds[] = { 0x0, 0x08, 0x40, 0x80, 0xC0, 0xF0, 0xFF }; 103 104 for (size_t i = 0; i < SK_ARRAY_COUNT(kThresholds); ++i) { 105 for (int j = 0; j < lms.count(); ++j) { 106 SkRect rect; 107 rect.fLeft = 0; 108 rect.fTop = 0; 109 rect.fRight = SkIntToScalar(fBM.width()); 110 rect.fBottom = SkIntToScalar(fBM.height()); 111 112 SkShader* thresh; 113 // This SkShader currently only has a GPU implementation. 114 if (canvas->getDevice()->accessRenderTarget()) { 115 thresh = SkBitmapAlphaThresholdShader::Create(fBM, fMask, kThresholds[i]); 116 } else { 117 thresh = SkShader::CreateBitmapShader(fBM, SkShader::kClamp_TileMode, 118 SkShader::kClamp_TileMode); 119 } 120 121 thresh->setLocalMatrix(lms[j]); 122 123 SkPaint paint; 124 paint.setShader(thresh)->unref(); 125 126 canvas->drawRect(rect, paint); 127 canvas->translate(SkIntToScalar(fBM.width() + kMargin), 0); 128 } 129 canvas->restore(); 130 canvas->translate(0, SkIntToScalar(fBM.height() + kMargin)); 131 canvas->save(); 132 } 133 134 } 135 136 SkBitmap fBM; 137 SkRegion fMask; 138 139 typedef skiagm::GM INHERITED; 140 }; 141 142 ////////////////////////////////////////////////////////////////////////////// 143 144 DEF_GM( return new BitmapAlphaThresholdGM(); ) 145