1 /* 2 * Copyright 2015 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/gm.h" 9 #include "include/core/SkCanvas.h" 10 #include "include/core/SkColor.h" 11 #include "include/core/SkFilterQuality.h" 12 #include "include/core/SkImage.h" 13 #include "include/core/SkPaint.h" 14 #include "include/core/SkPoint.h" 15 #include "include/core/SkRect.h" 16 #include "include/core/SkRefCnt.h" 17 #include "include/core/SkScalar.h" 18 #include "include/core/SkSize.h" 19 #include "include/core/SkString.h" 20 #include "include/core/SkSurface.h" 21 #include "include/core/SkTypes.h" 22 #include "include/private/SkTArray.h" 23 24 class ImageScaleAlignedGM : public skiagm::GM { 25 protected: onOnceBeforeDraw()26 void onOnceBeforeDraw() override { 27 const SkVector vectors[] = { { 1, 0 }, { 0, 1 } }; 28 29 for (size_t i = 0; i < SK_ARRAY_COUNT(vectors); ++i) { 30 auto& set = fSets.push_back(); 31 32 set.fVector = vectors[i]; 33 set.fImages.push_back() = MakeImage(vectors[i], SK_ColorGREEN); 34 set.fScales.push_back() = 1; 35 set.fImages.push_back() = MakeImage(vectors[i], SK_ColorRED); 36 set.fScales.push_back() = kStretchFactor; 37 set.fImages.push_back() = MakeImage(vectors[i], SK_ColorGREEN); 38 set.fScales.push_back() = 1; 39 } 40 } 41 onShortName()42 SkString onShortName() override { 43 return SkString("image_scale_aligned"); 44 } 45 onISize()46 SkISize onISize() override { 47 return SkISize::Make(580, 780); 48 } 49 onDraw(SkCanvas * canvas)50 void onDraw(SkCanvas* canvas) override { 51 struct { 52 SkPoint offset; 53 SkVector scale; 54 } cfgs[] = { 55 {{ 10, 10 }, { 1, 1 }}, 56 {{ 300.5f, 10 }, { 1, 1 }}, 57 {{ 10, 200.5f }, { 1, 1 }}, 58 {{ 300.5f, 200.5f }, { 1, 1 }}, 59 60 {{ 10.5f, 400.5f }, { 1, 1 }}, 61 {{ 550.5f, 400.5f }, { -1, 1 }}, 62 {{ 10.5f, 750.5f }, { 1, -1 }}, 63 {{ 550.5f, 750.5f }, { -1, -1 }}, 64 }; 65 66 for (size_t i = 0; i < SK_ARRAY_COUNT(cfgs); ++i) { 67 SkAutoCanvasRestore acr(canvas, true); 68 canvas->translate(cfgs[i].offset.x(), cfgs[i].offset.y()); 69 canvas->scale(cfgs[i].scale.x(), cfgs[i].scale.y()); 70 drawSets(canvas); 71 } 72 } 73 74 private: 75 struct ImageSet { 76 SkSTArray<3, sk_sp<SkImage>, true> fImages; 77 SkSTArray<3, SkScalar> fScales; 78 SkVector fVector; 79 }; 80 MakeImage(const SkVector & vec,SkColor color)81 static sk_sp<SkImage> MakeImage(const SkVector& vec, SkColor color) { 82 const SkPoint start = SkPoint::Make(vec.y() * kSegLen / 2, vec.x() * kSegLen / 2); 83 const SkPoint end = SkPoint::Make(start.x() + vec.x() * (kSegLen - 1), 84 start.y() + vec.y() * (kSegLen - 1)); 85 86 auto surface(SkSurface::MakeRasterN32Premul(kSegLen, kSegLen)); 87 surface->getCanvas()->clear(SK_ColorTRANSPARENT); 88 89 SkPaint paint; 90 paint.setAntiAlias(true); 91 const SkRect border = SkRect::MakeIWH(kSegLen, kSegLen).makeInset(.5f, .5f); 92 paint.setColor(SK_ColorBLUE); 93 paint.setStyle(SkPaint::kStroke_Style); 94 surface->getCanvas()->drawRect(border, paint); 95 96 paint.setColor(SK_ColorBLACK); 97 surface->getCanvas()->drawLine(start, end, paint); 98 99 paint.reset(); 100 paint.setColor(color); 101 const SkPoint pts[] = { start, end }; 102 surface->getCanvas()->drawPoints(SkCanvas::kPoints_PointMode, 2, pts, paint); 103 104 return surface->makeImageSnapshot(); 105 } 106 drawSets(SkCanvas * canvas) const107 void drawSets(SkCanvas* canvas) const { 108 SkAutoCanvasRestore acr(canvas, true); 109 110 const SkFilterQuality filters[] = { 111 kNone_SkFilterQuality, 112 kLow_SkFilterQuality, 113 kMedium_SkFilterQuality, 114 kHigh_SkFilterQuality 115 }; 116 const bool AAs[] = { false, true }; 117 118 SkPaint paint; 119 for (int i = 0; i < fSets.count(); ++i) { 120 auto& set = fSets[i]; 121 SkPoint lastPt; 122 for (size_t j = 0; j < SK_ARRAY_COUNT(AAs); ++j) { 123 paint.setAntiAlias(AAs[j]); 124 for (size_t k = 0; k < SK_ARRAY_COUNT(filters); ++k) { 125 paint.setFilterQuality(filters[k]); 126 lastPt = drawSet(canvas, set, paint); 127 canvas->translate((kSegLen + 4) * set.fVector.y(), 128 (kSegLen + 4) * set.fVector.x()); 129 } 130 } 131 canvas->translate(lastPt.x() + kSegLen, 132 - SkIntToScalar(kSegLen + 4) * SK_ARRAY_COUNT(filters) * SK_ARRAY_COUNT(AAs)); 133 } 134 } 135 drawSet(SkCanvas * canvas,const ImageSet & set,const SkPaint & paint) const136 SkPoint drawSet(SkCanvas* canvas, const ImageSet& set, const SkPaint& paint) const { 137 SkASSERT(set.fImages.count() == set.fScales.count()); 138 139 SkPoint pt = SkPoint::Make(0, 0); 140 for (int i = 0; i < set.fImages.count(); ++i) { 141 auto& img = set.fImages[i]; 142 const SkRect dst = 143 SkRect::MakeXYWH(pt.x(), pt.y(), 144 img->width() * (1 + (set.fScales[i] - 1) * set.fVector.x()), 145 img->height() * (1 + (set.fScales[i] - 1) * set.fVector.y())); 146 147 canvas->drawImageRect(img.get(), dst, &paint); 148 pt.offset(dst.width() * set.fVector.x(), dst.height() * set.fVector.y()); 149 } 150 151 return pt; 152 } 153 154 static constexpr unsigned kSegLen = 15; 155 static constexpr unsigned kStretchFactor = 4; 156 SkSTArray<2, ImageSet> fSets; 157 158 typedef GM INHERITED; 159 }; 160 161 DEF_GM(return new ImageScaleAlignedGM();) 162