1/*
2 * Copyright 2018 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
8in uniform sampler2D src;
9layout(ctype=SkIRect) in int4 bounds;
10uniform float4 boundsUniform;
11layout(ctype=SkRect) in float4 srcRect;
12in uniform float xInvZoom;
13in uniform float yInvZoom;
14in uniform float xInvInset;
15in uniform float yInvInset;
16
17uniform half2 offset;
18
19@coordTransform(src) {
20    SkMatrix::I()
21}
22
23void main() {
24    float2 coord = sk_TransformedCoords2D[0];
25    float2 zoom_coord = offset + coord * half2(xInvZoom, yInvZoom);
26    float2 delta = (coord - boundsUniform.xy) * boundsUniform.zw;
27    delta = min(delta, half2(1.0, 1.0) - delta);
28    delta *= half2(xInvInset, yInvInset);
29
30    half weight = 0.0;
31    if (delta.s < 2.0 && delta.t < 2.0) {
32        delta = half2(2.0, 2.0) - delta;
33        half dist = length(delta);
34        dist = max(2.0 - dist, 0.0);
35        weight = min(dist * dist, 1.0);
36    } else {
37        float2 delta_squared = delta * delta;
38        weight = min(min(delta_squared.x, delta_squared.y), 1.0);
39    }
40
41    sk_OutColor = texture(src, mix(coord, zoom_coord, weight));
42}
43
44@setData(pdman) {
45    SkScalar invW = 1.0f / src.width();
46    SkScalar invH = 1.0f / src.height();
47
48    {
49        SkScalar y = srcRect.y() * invH;
50        if (srcProxy.origin() != kTopLeft_GrSurfaceOrigin) {
51            y = 1.0f - (srcRect.height() / bounds.height()) - y;
52        }
53
54        pdman.set2f(offset, srcRect.x() * invW, y);
55    }
56
57    {
58        SkScalar y = bounds.y() * invH;
59        if (srcProxy.origin() != kTopLeft_GrSurfaceOrigin) {
60            y = 1.0f - bounds.height() * invH;
61        }
62
63        pdman.set4f(boundsUniform,
64                    bounds.x() * invW,
65                    y,
66                    SkIntToScalar(src.width()) / bounds.width(),
67                    SkIntToScalar(src.height()) / bounds.height());
68    }
69}
70
71@test(d) {
72    sk_sp<GrTextureProxy> proxy = d->textureProxy(0);
73    const int kMaxWidth = 200;
74    const int kMaxHeight = 200;
75    const SkScalar kMaxInset = 20.0f;
76    uint32_t width = d->fRandom->nextULessThan(kMaxWidth);
77    uint32_t height = d->fRandom->nextULessThan(kMaxHeight);
78    SkScalar inset = d->fRandom->nextRangeScalar(1.0f, kMaxInset);
79
80    SkIRect bounds = SkIRect::MakeWH(SkIntToScalar(kMaxWidth), SkIntToScalar(kMaxHeight));
81    SkRect srcRect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
82
83    auto effect = GrMagnifierEffect::Make(std::move(proxy),
84                                          bounds,
85                                          srcRect,
86                                          srcRect.width() / bounds.width(),
87                                          srcRect.height() / bounds.height(),
88                                          bounds.width() / inset,
89                                          bounds.height() / inset);
90    SkASSERT(effect);
91    return effect;
92}
93