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