1 /* 2 * Copyright 2011 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 #include "gm.h" 8 #include "SkCanvas.h" 9 #include "SkGradientShader.h" 10 #include "SkUnitMappers.h" 11 12 namespace skiagm { 13 14 static void makebm(SkBitmap* bm, SkBitmap::Config config, int w, int h) { 15 bm->setConfig(config, w, h); 16 bm->allocPixels(); 17 bm->eraseColor(SK_ColorTRANSPARENT); 18 19 SkCanvas canvas(*bm); 20 SkScalar s = SkIntToScalar(SkMin32(w, h)); 21 static const SkPoint kPts0[] = { { 0, 0 }, { s, s } }; 22 static const SkPoint kPts1[] = { { s, 0 }, { 0, s } }; 23 static const SkScalar kPos[] = { 0, SK_Scalar1/2, SK_Scalar1 }; 24 static const SkColor kColors0[] = {0x40FF00FF, 0xF0FFFF00, 0x4000FFFF }; 25 static const SkColor kColors1[] = {0xF0FF00FF, 0x80FFFF00, 0xF000FFFF }; 26 27 28 SkPaint paint; 29 30 SkUnitMapper* um = NULL; 31 32 um = new SkCosineMapper; 33 34 SkAutoUnref au(um); 35 36 paint.setShader(SkGradientShader::CreateLinear(kPts0, kColors0, kPos, 37 SK_ARRAY_COUNT(kColors0), SkShader::kClamp_TileMode, um))->unref(); 38 canvas.drawPaint(paint); 39 paint.setShader(SkGradientShader::CreateLinear(kPts1, kColors1, kPos, 40 SK_ARRAY_COUNT(kColors1), SkShader::kClamp_TileMode))->unref(); 41 canvas.drawPaint(paint); 42 } 43 44 /////////////////////////////////////////////////////////////////////////////// 45 46 struct LabeledMatrix { 47 SkMatrix fMatrix; 48 const char* fLabel; 49 }; 50 51 class ShaderText2GM : public GM { 52 public: 53 ShaderText2GM() { 54 this->setBGColor(0xFFDDDDDD); 55 } 56 57 protected: 58 59 SkString onShortName() { 60 return SkString("shadertext2"); 61 } 62 63 SkISize onISize() { return make_isize(1800, 900); } 64 65 virtual void onDraw(SkCanvas* canvas) { 66 static const char kText[] = "SKIA"; 67 static const int kTextLen = SK_ARRAY_COUNT(kText) - 1; 68 static const int kPointSize = 55; 69 70 SkTDArray<LabeledMatrix> matrices; 71 matrices.append()->fMatrix.reset(); 72 matrices.top().fLabel = "Identity"; 73 matrices.append()->fMatrix.setScale(1.2f, 0.8f); 74 matrices.top().fLabel = "Scale"; 75 matrices.append()->fMatrix.setRotate(10.f); 76 matrices.top().fLabel = "Rotate"; 77 matrices.append()->fMatrix.reset(); 78 matrices.top().fMatrix.setPerspX(-0.0015f); 79 matrices.top().fMatrix.setPerspY(+0.0015f); 80 matrices.top().fLabel = "Persp"; 81 82 SkTDArray<LabeledMatrix> localMatrices; 83 localMatrices.append()->fMatrix.reset(); 84 localMatrices.top().fLabel = "Identity"; 85 localMatrices.append()->fMatrix.setScale(2.5f, 0.2f); 86 localMatrices.top().fLabel = "Scale"; 87 localMatrices.append()->fMatrix.setRotate(45.f); 88 localMatrices.top().fLabel = "Rotate"; 89 localMatrices.append()->fMatrix.reset(); 90 localMatrices.top().fMatrix.setPerspX(-0.007f); 91 localMatrices.top().fMatrix.setPerspY(+0.008f); 92 localMatrices.top().fLabel = "Persp"; 93 94 static SkBitmap bmp; 95 if (bmp.isNull()) { 96 makebm(&bmp, SkBitmap::kARGB_8888_Config, kPointSize / 2, kPointSize / 2); 97 } 98 99 SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(bmp, 100 SkShader::kMirror_TileMode, 101 SkShader::kRepeat_TileMode)); 102 SkPaint fillPaint; 103 fillPaint.setAntiAlias(true); 104 fillPaint.setTextSize(SkIntToScalar(kPointSize)); 105 fillPaint.setFilterBitmap(true); 106 fillPaint.setShader(shader); 107 108 SkPaint outlinePaint; 109 outlinePaint.setAntiAlias(true); 110 outlinePaint.setTextSize(SkIntToScalar(kPointSize)); 111 outlinePaint.setStyle(SkPaint::kStroke_Style); 112 outlinePaint.setStrokeWidth(0.f); 113 114 SkScalar w = fillPaint.measureText(kText, kTextLen); 115 static SkScalar kPadY = 0.5f * kPointSize; 116 static SkScalar kPadX = 1.5f * kPointSize; 117 118 SkPaint strokePaint(fillPaint); 119 strokePaint.setStyle(SkPaint::kStroke_Style); 120 strokePaint.setStrokeWidth(kPointSize * 0.1f); 121 122 SkPaint labelPaint; 123 labelPaint.setColor(0xff000000); 124 labelPaint.setAntiAlias(true); 125 labelPaint.setTextSize(12.f); 126 127 canvas->translate(15.f, 15.f); 128 canvas->drawBitmap(bmp, 0, 0); 129 canvas->translate(0, bmp.height() + labelPaint.getTextSize() + 15.f); 130 131 static const char kLabelLabel[] = "localM / canvasM"; 132 canvas->drawText(kLabelLabel, strlen(kLabelLabel), 0, 0, labelPaint); 133 canvas->translate(0, 15.f); 134 135 canvas->save(); 136 SkScalar maxLabelW = 0; 137 canvas->translate(0, kPadY / 2 + kPointSize); 138 for (int lm = 0; lm < localMatrices.count(); ++lm) { 139 canvas->drawText(matrices[lm].fLabel, strlen(matrices[lm].fLabel), 140 0, labelPaint.getTextSize() - 1, labelPaint); 141 SkScalar labelW = labelPaint.measureText(matrices[lm].fLabel, 142 strlen(matrices[lm].fLabel)); 143 maxLabelW = SkMaxScalar(maxLabelW, labelW); 144 canvas->translate(0.f, 2 * kPointSize + 2.5f * kPadY); 145 } 146 canvas->restore(); 147 148 canvas->translate(maxLabelW + kPadX / 2.f, 0.f); 149 150 for (int s = 0; s < 2; ++s) { 151 SkPaint& paint = s ? strokePaint : fillPaint; 152 153 SkScalar columnH; 154 for (int m = 0; m < matrices.count(); ++m) { 155 columnH = 0; 156 canvas->save(); 157 canvas->drawText(matrices[m].fLabel, strlen(matrices[m].fLabel), 158 0, labelPaint.getTextSize() - 1, labelPaint); 159 canvas->translate(0, kPadY / 2 + kPointSize); 160 columnH += kPadY / 2 + kPointSize; 161 for (int lm = 0; lm < localMatrices.count(); ++lm) { 162 shader->setLocalMatrix(localMatrices[lm].fMatrix); 163 164 canvas->save(); 165 canvas->concat(matrices[m].fMatrix); 166 canvas->drawText(kText, kTextLen, 0, 0, paint); 167 canvas->drawText(kText, kTextLen, 0, 0, outlinePaint); 168 canvas->restore(); 169 170 SkPath path; 171 path.arcTo(SkRect::MakeXYWH(-0.1f * w, 0.f, 172 1.2f * w, 2.f * kPointSize), 173 225.f, 359.f, 174 false); 175 path.close(); 176 177 canvas->translate(0.f, kPointSize + kPadY); 178 columnH += kPointSize + kPadY; 179 180 canvas->save(); 181 canvas->concat(matrices[m].fMatrix); 182 canvas->drawTextOnPath(kText, kTextLen, path, NULL, paint); 183 canvas->drawTextOnPath(kText, kTextLen, path, NULL, outlinePaint); 184 canvas->restore(); 185 SkPaint stroke; 186 stroke.setStyle(SkPaint::kStroke_Style); 187 canvas->translate(0.f, kPointSize + kPadY); 188 columnH += kPointSize + kPadY; 189 } 190 canvas->restore(); 191 canvas->translate(w + kPadX, 0.f); 192 } 193 if (0 == s) { 194 canvas->drawLine(0.f, -kPadY, 0.f, columnH + kPadY, outlinePaint); 195 canvas->translate(kPadX / 2, 0.f); 196 static const char kFillLabel[] = "Filled"; 197 static const char kStrokeLabel[] = "Stroked"; 198 SkScalar y = columnH + kPadY / 2; 199 SkScalar fillX = -outlinePaint.measureText(kFillLabel, strlen(kFillLabel)) - kPadX; 200 SkScalar strokeX = kPadX; 201 canvas->drawText(kFillLabel, strlen(kFillLabel), fillX, y, labelPaint); 202 canvas->drawText(kStrokeLabel, strlen(kStrokeLabel), strokeX, y, labelPaint); 203 } 204 } 205 } 206 207 virtual uint32_t onGetFlags() const SK_OVERRIDE { 208 // disable 565 for now, til mike fixes the debug assert 209 return this->INHERITED::onGetFlags() | kSkip565_Flag; 210 } 211 212 private: 213 typedef GM INHERITED; 214 }; 215 216 /////////////////////////////////////////////////////////////////////////////// 217 218 #ifndef SK_BUILD_FOR_ANDROID 219 static GM* MyFactory(void*) { return new ShaderText2GM; } 220 static GMRegistry reg(MyFactory); 221 #endif 222 } 223