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     using INHERITED = GM;
159 };
160 
161 DEF_GM(return new ImageScaleAlignedGM();)
162