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