123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- /*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "gm/gm.h"
- #include "include/core/SkBitmap.h"
- #include "include/core/SkCanvas.h"
- #include "include/core/SkColor.h"
- #include "include/core/SkFont.h"
- #include "include/core/SkFontTypes.h"
- #include "include/core/SkImage.h"
- #include "include/core/SkImageInfo.h"
- #include "include/core/SkMatrix.h"
- #include "include/core/SkPaint.h"
- #include "include/core/SkPoint.h"
- #include "include/core/SkRect.h"
- #include "include/core/SkRefCnt.h"
- #include "include/core/SkSize.h"
- #include "include/core/SkString.h"
- #include "include/core/SkSurface.h"
- #include "include/core/SkTypeface.h"
- #include "include/core/SkTypes.h"
- #include "include/gpu/GrContext.h"
- #include "include/gpu/GrTypes.h"
- #include "include/private/SkTArray.h"
- #include "src/image/SkImage_Base.h"
- #include "src/image/SkImage_Gpu.h"
- #include "tools/ToolUtils.h"
- #include "tools/gpu/ProxyUtils.h"
- #include <string.h>
- #include <utility>
- class GrRenderTargetContext;
- static const int kNumMatrices = 6;
- static const int kImageSize = 128;
- static const int kLabelSize = 32;
- static const int kNumLabels = 4;
- static const int kInset = 16;
- static const int kCellSize = kImageSize+2*kLabelSize;
- static const int kGMWidth = kNumMatrices*kCellSize;
- static const int kGMHeight = 4*kCellSize;
- static const SkPoint kPoints[kNumLabels] = {
- { 0, kImageSize }, // LL
- { kImageSize, kImageSize }, // LR
- { 0, 0 }, // UL
- { kImageSize, 0 }, // UR
- };
- static const SkMatrix kUVMatrices[kNumMatrices] = {
- SkMatrix::MakeAll( 0, -1, 1,
- -1, 0, 1,
- 0, 0, 1),
- SkMatrix::MakeAll( 1, 0, 0,
- 0, -1, 1,
- 0, 0, 1),
- // flip x
- SkMatrix::MakeAll(-1, 0, 1,
- 0, 1, 0,
- 0, 0, 1),
- SkMatrix::MakeAll( 0, 1, 0,
- -1, 0, 1,
- 0, 0, 1),
- // flip both x & y == rotate 180
- SkMatrix::MakeAll(-1, 0, 1,
- 0, -1, 1,
- 0, 0, 1),
- // identity
- SkMatrix::MakeAll(1, 0, 0,
- 0, 1, 0,
- 0, 0, 1)
- };
- // Create a fixed size text label like "LL" or "LR".
- static sk_sp<SkImage> make_text_image(GrContext* context, const char* text, SkColor color) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setColor(color);
- SkFont font;
- font.setEdging(SkFont::Edging::kAntiAlias);
- font.setTypeface(ToolUtils::create_portable_typeface());
- font.setSize(32);
- SkRect bounds;
- font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
- const SkMatrix mat = SkMatrix::MakeRectToRect(bounds, SkRect::MakeWH(kLabelSize, kLabelSize),
- SkMatrix::kFill_ScaleToFit);
- const SkImageInfo ii = SkImageInfo::MakeN32Premul(kLabelSize, kLabelSize);
- sk_sp<SkSurface> surf = SkSurface::MakeRaster(ii);
- SkCanvas* canvas = surf->getCanvas();
- canvas->clear(SK_ColorWHITE);
- canvas->concat(mat);
- canvas->drawSimpleText(text, strlen(text), SkTextEncoding::kUTF8, 0, 0, font, paint);
- sk_sp<SkImage> image = surf->makeImageSnapshot();
- return image->makeTextureImage(context, nullptr);
- }
- // Create an image with each corner marked w/ "LL", "LR", etc., with the origin either bottom-left
- // or top-left.
- static sk_sp<SkImage> make_reference_image(GrContext* context,
- const SkTArray<sk_sp<SkImage>>& labels,
- bool bottomLeftOrigin) {
- SkASSERT(kNumLabels == labels.count());
- SkImageInfo ii =
- SkImageInfo::Make(kImageSize, kImageSize, kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
- SkBitmap bm;
- bm.allocPixels(ii);
- SkCanvas canvas(bm);
- canvas.clear(SK_ColorWHITE);
- for (int i = 0; i < kNumLabels; ++i) {
- canvas.drawImage(labels[i],
- 0.0 != kPoints[i].fX ? kPoints[i].fX-kLabelSize-kInset : kInset,
- 0.0 != kPoints[i].fY ? kPoints[i].fY-kLabelSize-kInset : kInset);
- }
- auto origin = bottomLeftOrigin ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
- auto proxy = sk_gpu_test::MakeTextureProxyFromData(context, GrRenderable::kNo, kImageSize,
- kImageSize, bm.colorType(), bm.alphaType(),
- origin, bm.getPixels(), bm.rowBytes());
- if (!proxy) {
- return nullptr;
- }
- return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, kOpaque_SkAlphaType,
- std::move(proxy), nullptr);
- }
- // Here we're converting from a matrix that is intended for UVs to a matrix that is intended
- // for rect geometry used for a drawImage call. They are, in some sense, inverses of each
- // other but we also need a scale to map from the [0..1] uv range to the actual size of
- // image.
- static bool UVMatToGeomMatForImage(SkMatrix* geomMat, const SkMatrix& uvMat) {
- const SkMatrix yFlip = SkMatrix::MakeAll(1, 0, 0, 0, -1, 1, 0, 0, 1);
- SkMatrix tmp = uvMat;
- tmp.preConcat(yFlip);
- tmp.preScale(1.0f/kImageSize, 1.0f/kImageSize);
- tmp.postConcat(yFlip);
- tmp.postScale(kImageSize, kImageSize);
- return tmp.invert(geomMat);
- }
- // This GM exercises drawImage with a set of matrices that use an unusual amount of flips and
- // rotates.
- class FlippityGM : public skiagm::GpuGM {
- public:
- FlippityGM() {
- this->setBGColor(0xFFCCCCCC);
- }
- protected:
- SkString onShortName() override {
- return SkString("flippity");
- }
- SkISize onISize() override {
- return SkISize::Make(kGMWidth, kGMHeight);
- }
- // Draw the reference image and the four corner labels in the matrix's coordinate space
- void drawImageWithMatrixAndLabels(SkCanvas* canvas, SkImage* image, int matIndex,
- bool drawSubset, bool drawScaled) {
- static const SkRect kSubsets[kNumMatrices] = {
- SkRect::MakeXYWH(kInset, 0, kImageSize-kInset, kImageSize),
- SkRect::MakeXYWH(0, kInset, kImageSize, kImageSize-kInset),
- SkRect::MakeXYWH(0, 0, kImageSize-kInset, kImageSize),
- SkRect::MakeXYWH(0, 0, kImageSize, kImageSize-kInset),
- SkRect::MakeXYWH(kInset/2, kInset/2, kImageSize-kInset, kImageSize-kInset),
- SkRect::MakeXYWH(kInset, kInset, kImageSize-2*kInset, kImageSize-2*kInset),
- };
- SkMatrix imageGeomMat;
- SkAssertResult(UVMatToGeomMatForImage(&imageGeomMat, kUVMatrices[matIndex]));
- canvas->save();
- // draw the reference image
- canvas->concat(imageGeomMat);
- if (drawSubset) {
- canvas->drawImageRect(image, kSubsets[matIndex],
- drawScaled ? SkRect::MakeWH(kImageSize, kImageSize)
- : kSubsets[matIndex],
- nullptr, SkCanvas::kFast_SrcRectConstraint);
- } else {
- canvas->drawImage(image, 0, 0);
- }
- // draw the labels
- for (int i = 0; i < kNumLabels; ++i) {
- canvas->drawImage(fLabels[i],
- 0.0f == kPoints[i].fX ? -kLabelSize : kPoints[i].fX,
- 0.0f == kPoints[i].fY ? -kLabelSize : kPoints[i].fY);
- }
- canvas->restore();
- }
- void drawRow(GrContext* context, SkCanvas* canvas,
- bool bottomLeftImage, bool drawSubset, bool drawScaled) {
- sk_sp<SkImage> referenceImage = make_reference_image(context, fLabels, bottomLeftImage);
- canvas->save();
- canvas->translate(kLabelSize, kLabelSize);
- for (int i = 0; i < kNumMatrices; ++i) {
- this->drawImageWithMatrixAndLabels(canvas, referenceImage.get(), i,
- drawSubset, drawScaled);
- canvas->translate(kCellSize, 0);
- }
- canvas->restore();
- }
- void makeLabels(GrContext* context) {
- static const char* kLabelText[kNumLabels] = { "LL", "LR", "UL", "UR" };
- static const SkColor kLabelColors[kNumLabels] = {
- SK_ColorRED,
- SK_ColorGREEN,
- SK_ColorBLUE,
- SK_ColorCYAN
- };
- SkASSERT(!fLabels.count());
- for (int i = 0; i < kNumLabels; ++i) {
- fLabels.push_back(make_text_image(context, kLabelText[i], kLabelColors[i]));
- }
- SkASSERT(kNumLabels == fLabels.count());
- }
- void onDraw(GrContext* context, GrRenderTargetContext*, SkCanvas* canvas) override {
- this->makeLabels(context);
- canvas->save();
- // Top row gets TL image
- this->drawRow(context, canvas, false, false, false);
- canvas->translate(0, kCellSize);
- // Bottom row gets BL image
- this->drawRow(context, canvas, true, false, false);
- canvas->translate(0, kCellSize);
- // Third row gets subsets of BL images
- this->drawRow(context, canvas, true, true, false);
- canvas->translate(0, kCellSize);
- // Fourth row gets scaled subsets of BL images
- this->drawRow(context, canvas, true, true, true);
- canvas->restore();
- // separator grid
- for (int i = 0; i < 4; ++i) {
- canvas->drawLine(0, i * kCellSize, kGMWidth, i * kCellSize, SkPaint());
- }
- for (int i = 0; i < kNumMatrices; ++i) {
- canvas->drawLine(i * kCellSize, 0, i * kCellSize, kGMHeight, SkPaint());
- }
- }
- private:
- SkTArray<sk_sp<SkImage>> fLabels;
- typedef GM INHERITED;
- };
- DEF_GM(return new FlippityGM;)
|