12880df2609eba09b555ca37be04b6ad89290c765Tom Hudson/* 22880df2609eba09b555ca37be04b6ad89290c765Tom Hudson * Copyright 2015 Google Inc. 32880df2609eba09b555ca37be04b6ad89290c765Tom Hudson * 42880df2609eba09b555ca37be04b6ad89290c765Tom Hudson * Use of this source code is governed by a BSD-style license that can be 52880df2609eba09b555ca37be04b6ad89290c765Tom Hudson * found in the LICENSE file. 62880df2609eba09b555ca37be04b6ad89290c765Tom Hudson */ 72880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 82880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "gm.h" 92880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "SkBitmap.h" 102880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "SkCanvas.h" 112880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "SkGradientShader.h" 122880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "SkImageGenerator.h" 132880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "SkPaint.h" 142880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "SkPathOps.h" 152880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "SkPicture.h" 162880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "SkPictureRecorder.h" 172880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 182880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonstatic void draw_vector_logo(SkCanvas* canvas, const SkRect& viewBox) { 192880df2609eba09b555ca37be04b6ad89290c765Tom Hudson static const char kSkiaStr[] = "SKIA"; 202880df2609eba09b555ca37be04b6ad89290c765Tom Hudson static const SkScalar kGradientPad = .1f; 212880df2609eba09b555ca37be04b6ad89290c765Tom Hudson static const SkScalar kVerticalSpacing = 0.25f; 222880df2609eba09b555ca37be04b6ad89290c765Tom Hudson static const SkScalar kAccentScale = 1.20f; 232880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 242880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkPaint paint; 252880df2609eba09b555ca37be04b6ad89290c765Tom Hudson paint.setAntiAlias(true); 262880df2609eba09b555ca37be04b6ad89290c765Tom Hudson paint.setSubpixelText(true); 272880df2609eba09b555ca37be04b6ad89290c765Tom Hudson paint.setFakeBoldText(true); 282880df2609eba09b555ca37be04b6ad89290c765Tom Hudson sk_tool_utils::set_portable_typeface(&paint); 292880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 302880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkPath path; 312880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkRect iBox, skiBox, skiaBox; 322880df2609eba09b555ca37be04b6ad89290c765Tom Hudson paint.getTextPath("SKI", 3, 0, 0, &path); 332880df2609eba09b555ca37be04b6ad89290c765Tom Hudson TightBounds(path, &skiBox); 342880df2609eba09b555ca37be04b6ad89290c765Tom Hudson paint.getTextPath("I", 1, 0, 0, &path); 352880df2609eba09b555ca37be04b6ad89290c765Tom Hudson TightBounds(path, &iBox); 362880df2609eba09b555ca37be04b6ad89290c765Tom Hudson iBox.offsetTo(skiBox.fRight - iBox.width(), iBox.fTop); 372880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 382880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const size_t textLen = strlen(kSkiaStr); 392880df2609eba09b555ca37be04b6ad89290c765Tom Hudson paint.getTextPath(kSkiaStr, textLen, 0, 0, &path); 402880df2609eba09b555ca37be04b6ad89290c765Tom Hudson TightBounds(path, &skiaBox); 412880df2609eba09b555ca37be04b6ad89290c765Tom Hudson skiaBox.outset(0, 2 * iBox.width() * (kVerticalSpacing + 1)); 422880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 432880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const SkScalar accentSize = iBox.width() * kAccentScale; 442880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const SkScalar underlineY = iBox.bottom() + 452880df2609eba09b555ca37be04b6ad89290c765Tom Hudson (kVerticalSpacing + SkScalarSqrt(3) / 2) * accentSize; 462880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkMatrix m; 472880df2609eba09b555ca37be04b6ad89290c765Tom Hudson m.setRectToRect(skiaBox, viewBox, SkMatrix::kFill_ScaleToFit); 482880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkAutoCanvasRestore acr(canvas, true); 492880df2609eba09b555ca37be04b6ad89290c765Tom Hudson canvas->concat(m); 502880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 512880df2609eba09b555ca37be04b6ad89290c765Tom Hudson canvas->drawCircle(iBox.centerX(), 522880df2609eba09b555ca37be04b6ad89290c765Tom Hudson iBox.y() - (0.5f + kVerticalSpacing) * accentSize, 532880df2609eba09b555ca37be04b6ad89290c765Tom Hudson accentSize / 2, 542880df2609eba09b555ca37be04b6ad89290c765Tom Hudson paint); 552880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 562880df2609eba09b555ca37be04b6ad89290c765Tom Hudson path.reset(); 572880df2609eba09b555ca37be04b6ad89290c765Tom Hudson path.moveTo(iBox.centerX() - accentSize / 2, iBox.bottom() + kVerticalSpacing * accentSize); 582880df2609eba09b555ca37be04b6ad89290c765Tom Hudson path.rLineTo(accentSize, 0); 592880df2609eba09b555ca37be04b6ad89290c765Tom Hudson path.lineTo(iBox.centerX(), underlineY); 602880df2609eba09b555ca37be04b6ad89290c765Tom Hudson canvas->drawPath(path, paint); 612880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 622880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkRect underlineRect = SkRect::MakeLTRB(iBox.centerX() - iBox.width() * accentSize * 3, 632880df2609eba09b555ca37be04b6ad89290c765Tom Hudson underlineY, 642880df2609eba09b555ca37be04b6ad89290c765Tom Hudson iBox.centerX(), 652880df2609eba09b555ca37be04b6ad89290c765Tom Hudson underlineY + accentSize / 10); 662880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const SkPoint pts1[] = { SkPoint::Make(underlineRect.x(), 0), 672880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkPoint::Make(iBox.centerX(), 0) }; 682880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const SkScalar pos1[] = { 0, 0.75f }; 692880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const SkColor colors1[] = { SK_ColorTRANSPARENT, SK_ColorBLACK }; 702880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkASSERT(SK_ARRAY_COUNT(pos1) == SK_ARRAY_COUNT(colors1)); 712880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkAutoTUnref<SkShader> gradient1(SkGradientShader::CreateLinear(pts1, colors1, pos1, 722880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SK_ARRAY_COUNT(pos1), 732880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkShader::kClamp_TileMode)); 742880df2609eba09b555ca37be04b6ad89290c765Tom Hudson paint.setShader(gradient1.get()); 752880df2609eba09b555ca37be04b6ad89290c765Tom Hudson canvas->drawRect(underlineRect, paint); 762880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 772880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const SkPoint pts2[] = { SkPoint::Make(iBox.x() - iBox.width() * kGradientPad, 0), 782880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkPoint::Make(iBox.right() + iBox.width() * kGradientPad, 0) }; 792880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const SkScalar pos2[] = { 0, .01f, 1.0f/3, 1.0f/3, 2.0f/3, 2.0f/3, .99f, 1 }; 802880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const SkColor colors2[] = { 812880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SK_ColorBLACK, 822880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 0xffca5139, 832880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 0xffca5139, 842880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 0xff8dbd53, 852880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 0xff8dbd53, 862880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 0xff5460a5, 872880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 0xff5460a5, 882880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SK_ColorBLACK 892880df2609eba09b555ca37be04b6ad89290c765Tom Hudson }; 902880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkASSERT(SK_ARRAY_COUNT(pos2) == SK_ARRAY_COUNT(colors2)); 912880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkAutoTUnref<SkShader> gradient2(SkGradientShader::CreateLinear(pts2, colors2, pos2, 922880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SK_ARRAY_COUNT(pos2), 932880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkShader::kClamp_TileMode)); 942880df2609eba09b555ca37be04b6ad89290c765Tom Hudson paint.setShader(gradient2.get()); 952880df2609eba09b555ca37be04b6ad89290c765Tom Hudson canvas->drawText(kSkiaStr, textLen, 0, 0, paint); 962880df2609eba09b555ca37be04b6ad89290c765Tom Hudson} 972880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 982880df2609eba09b555ca37be04b6ad89290c765Tom Hudson// This GM exercises SkPictureImageGenerator features 992880df2609eba09b555ca37be04b6ad89290c765Tom Hudson// (in particular its matrix vs. bounds semantics). 1002880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonclass PictureGeneratorGM : public skiagm::GM { 1012880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonprotected: 1022880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkString onShortName() override { 1032880df2609eba09b555ca37be04b6ad89290c765Tom Hudson return SkString("pictureimagegenerator"); 1042880df2609eba09b555ca37be04b6ad89290c765Tom Hudson } 1052880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 1062880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkISize onISize() override { 1072880df2609eba09b555ca37be04b6ad89290c765Tom Hudson return SkISize::Make(1160, 860); 1082880df2609eba09b555ca37be04b6ad89290c765Tom Hudson } 1092880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 1102880df2609eba09b555ca37be04b6ad89290c765Tom Hudson void onOnceBeforeDraw() override { 1112880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const SkRect rect = SkRect::MakeWH(kPictureWidth, kPictureHeight); 1122880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkPictureRecorder recorder; 1132880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkCanvas* canvas = recorder.beginRecording(rect); 1142880df2609eba09b555ca37be04b6ad89290c765Tom Hudson draw_vector_logo(canvas, rect); 1152880df2609eba09b555ca37be04b6ad89290c765Tom Hudson fPicture.reset(recorder.endRecording()); 1162880df2609eba09b555ca37be04b6ad89290c765Tom Hudson } 1172880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 1182880df2609eba09b555ca37be04b6ad89290c765Tom Hudson void onDraw(SkCanvas* canvas) override { 1192880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const struct { 1202880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkISize size; 1212880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkScalar scaleX, scaleY; 1222880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkScalar opacity; 1232880df2609eba09b555ca37be04b6ad89290c765Tom Hudson } configs[] = { 1242880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(200, 100), 1, 1, 1 }, 1252880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(200, 200), 1, 1, 1 }, 1262880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(200, 200), 1, 2, 1 }, 1272880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(400, 200), 2, 2, 1 }, 1282880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 1292880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(200, 100), 1, 1, 0.9f }, 1302880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(200, 200), 1, 1, 0.75f }, 1312880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(200, 200), 1, 2, 0.5f }, 1322880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(400, 200), 2, 2, 0.25f }, 1332880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 1342880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(200, 200), 0.5f, 1, 1 }, 1352880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(200, 200), 1, 0.5f, 1 }, 1362880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(200, 200), 0.5f, 0.5f, 1 }, 1372880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(200, 200), 2, 2, 1 }, 1382880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 1392880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(200, 100), -1, 1, 1 }, 1402880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(200, 100), 1, -1, 1 }, 1412880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(200, 100), -1, -1, 1 }, 1422880df2609eba09b555ca37be04b6ad89290c765Tom Hudson { SkISize::Make(200, 100), -1, -1, 0.5f }, 1432880df2609eba09b555ca37be04b6ad89290c765Tom Hudson }; 1442880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 1452880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const unsigned kDrawsPerRow = 4; 1462880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const SkScalar kDrawSize = 250; 1472880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 1482880df2609eba09b555ca37be04b6ad89290c765Tom Hudson for (size_t i = 0; i < SK_ARRAY_COUNT(configs); ++i) { 1492880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkPaint p; 1502880df2609eba09b555ca37be04b6ad89290c765Tom Hudson p.setAlpha(SkScalarRoundToInt(255 * configs[i].opacity)); 1512880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 1522880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkMatrix m = SkMatrix::MakeScale(configs[i].scaleX, configs[i].scaleY); 1532880df2609eba09b555ca37be04b6ad89290c765Tom Hudson if (configs[i].scaleX < 0) { 1542880df2609eba09b555ca37be04b6ad89290c765Tom Hudson m.postTranslate(SkIntToScalar(configs[i].size.width()), 0); 1552880df2609eba09b555ca37be04b6ad89290c765Tom Hudson } 1562880df2609eba09b555ca37be04b6ad89290c765Tom Hudson if (configs[i].scaleY < 0) { 1572880df2609eba09b555ca37be04b6ad89290c765Tom Hudson m.postTranslate(0, SkIntToScalar(configs[i].size.height())); 1582880df2609eba09b555ca37be04b6ad89290c765Tom Hudson } 1592880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkAutoTDelete<SkImageGenerator> gen( 1602880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkImageGenerator::NewFromPicture(configs[i].size, fPicture.get(), &m, 1612880df2609eba09b555ca37be04b6ad89290c765Tom Hudson p.getAlpha() != 255 ? &p : nullptr)); 1622880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkBitmap bm; 1632880df2609eba09b555ca37be04b6ad89290c765Tom Hudson gen->generateBitmap(&bm); 1642880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 1652880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const SkScalar x = kDrawSize * (i % kDrawsPerRow); 1662880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const SkScalar y = kDrawSize * (i / kDrawsPerRow); 1672880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 1682880df2609eba09b555ca37be04b6ad89290c765Tom Hudson p.setColor(0xfff0f0f0); 1692880df2609eba09b555ca37be04b6ad89290c765Tom Hudson p.setAlpha(255); 1702880df2609eba09b555ca37be04b6ad89290c765Tom Hudson canvas->drawRect(SkRect::MakeXYWH(x, y, 1712880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkIntToScalar(bm.width()), 1722880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkIntToScalar(bm.height())), p); 1732880df2609eba09b555ca37be04b6ad89290c765Tom Hudson canvas->drawBitmap(bm, x, y); 1742880df2609eba09b555ca37be04b6ad89290c765Tom Hudson } 1752880df2609eba09b555ca37be04b6ad89290c765Tom Hudson } 1762880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 1772880df2609eba09b555ca37be04b6ad89290c765Tom Hudsonprivate: 1782880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkAutoTUnref<SkPicture> fPicture; 1792880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 1802880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const SkScalar kPictureWidth = 200; 1812880df2609eba09b555ca37be04b6ad89290c765Tom Hudson const SkScalar kPictureHeight = 100; 1822880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 1832880df2609eba09b555ca37be04b6ad89290c765Tom Hudson typedef skiagm::GM INHERITED; 1842880df2609eba09b555ca37be04b6ad89290c765Tom Hudson}; 1852880df2609eba09b555ca37be04b6ad89290c765Tom Hudson 1862880df2609eba09b555ca37be04b6ad89290c765Tom HudsonDEF_GM(return new PictureGeneratorGM;) 187