Home | History | Annotate | Download | only in gm
      1 /*
      2  * Copyright 2011 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.h"
      9 #include "sk_tool_utils.h"
     10 #include "SkArithmeticImageFilter.h"
     11 #include "SkCanvas.h"
     12 #include "SkColorPriv.h"
     13 #include "SkGradientShader.h"
     14 #include "SkImage.h"
     15 #include "SkImageSource.h"
     16 #include "SkShader.h"
     17 #include "SkSurface.h"
     18 
     19 #define WW  100
     20 #define HH  32
     21 
     22 static sk_sp<SkImage> make_src() {
     23     sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(WW, HH));
     24     SkCanvas* canvas = surface->getCanvas();
     25 
     26     SkPaint paint;
     27     SkPoint pts[] = { {0, 0}, {SkIntToScalar(WW), SkIntToScalar(HH)} };
     28     SkColor colors[] = {
     29         SK_ColorTRANSPARENT, SK_ColorGREEN, SK_ColorCYAN,
     30         SK_ColorRED, SK_ColorMAGENTA, SK_ColorWHITE,
     31     };
     32     paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
     33                                                  SkShader::kClamp_TileMode));
     34     canvas->drawPaint(paint);
     35     return surface->makeImageSnapshot();
     36 }
     37 
     38 static sk_sp<SkImage> make_dst() {
     39     sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(WW, HH));
     40     SkCanvas* canvas = surface->getCanvas();
     41 
     42     SkPaint paint;
     43     SkPoint pts[] = { {0, SkIntToScalar(HH)}, {SkIntToScalar(WW), 0} };
     44     SkColor colors[] = {
     45         SK_ColorBLUE, SK_ColorYELLOW, SK_ColorBLACK, SK_ColorGREEN,
     46         sk_tool_utils::color_to_565(SK_ColorGRAY)
     47     };
     48     paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
     49                                                  SkShader::kClamp_TileMode));
     50     canvas->drawPaint(paint);
     51     return surface->makeImageSnapshot();
     52 }
     53 
     54 static void show_k_text(SkCanvas* canvas, SkScalar x, SkScalar y, const SkScalar k[]) {
     55     SkPaint paint;
     56     paint.setTextSize(SkIntToScalar(24));
     57     paint.setAntiAlias(true);
     58     sk_tool_utils::set_portable_typeface(&paint);
     59     for (int i = 0; i < 4; ++i) {
     60         SkString str;
     61         str.appendScalar(k[i]);
     62         SkScalar width = paint.measureText(str.c_str(), str.size());
     63         canvas->drawString(str, x, y + paint.getTextSize(), paint);
     64         x += width + SkIntToScalar(10);
     65     }
     66 }
     67 
     68 class ArithmodeGM : public skiagm::GM {
     69 public:
     70     ArithmodeGM () {}
     71 
     72 protected:
     73 
     74     virtual SkString onShortName() {
     75         return SkString("arithmode");
     76     }
     77 
     78     virtual SkISize onISize() { return SkISize::Make(640, 572); }
     79 
     80     virtual void onDraw(SkCanvas* canvas) {
     81         sk_sp<SkImage> src = make_src();
     82         sk_sp<SkImage> dst = make_dst();
     83         sk_sp<SkImageFilter> srcFilter = SkImageSource::Make(src);
     84         sk_sp<SkImageFilter> dstFilter = SkImageSource::Make(dst);
     85 
     86         constexpr SkScalar one = SK_Scalar1;
     87         constexpr SkScalar K[] = {
     88             0, 0, 0, 0,
     89             0, 0, 0, one,
     90             0, one, 0, 0,
     91             0, 0, one, 0,
     92             0, one, one, 0,
     93             0, one, -one, 0,
     94             0, one/2, one/2, 0,
     95             0, one/2, one/2, one/4,
     96             0, one/2, one/2, -one/4,
     97             one/4, one/2, one/2, 0,
     98             -one/4, one/2, one/2, 0,
     99         };
    100 
    101         const SkScalar* k = K;
    102         const SkScalar* stop = k + SK_ARRAY_COUNT(K);
    103         const SkRect rect = SkRect::MakeWH(WW, HH);
    104         SkScalar gap = SkIntToScalar(WW + 20);
    105         while (k < stop) {
    106             {
    107                 SkAutoCanvasRestore acr(canvas, true);
    108                 canvas->drawImage(src, 0, 0);
    109                 canvas->translate(gap, 0);
    110                 canvas->drawImage(dst, 0, 0);
    111                 canvas->translate(gap, 0);
    112                 SkPaint paint;
    113                 paint.setImageFilter(SkArithmeticImageFilter::Make(k[0], k[1], k[2], k[3], true,
    114                                                                    dstFilter, srcFilter, nullptr));
    115                 canvas->saveLayer(&rect, &paint);
    116                 canvas->restore();
    117 
    118                 canvas->translate(gap, 0);
    119                 show_k_text(canvas, 0, 0, k);
    120             }
    121 
    122             k += 4;
    123             canvas->translate(0, HH + 12);
    124         }
    125 
    126         // Draw two special cases to test enforcePMColor. In these cases, we
    127         // draw the dst bitmap twice, the first time it is halved and inverted,
    128         // leading to invalid premultiplied colors. If we enforcePMColor, these
    129         // invalid values should be clamped, and will not contribute to the
    130         // second draw.
    131         for (int i = 0; i < 2; i++) {
    132             const bool enforcePMColor = (i == 0);
    133 
    134             {
    135                 SkAutoCanvasRestore acr(canvas, true);
    136                 canvas->translate(gap, 0);
    137                 canvas->drawImage(dst, 0, 0);
    138                 canvas->translate(gap, 0);
    139 
    140                 sk_sp<SkImageFilter> bg =
    141                         SkArithmeticImageFilter::Make(0, 0, -one / 2, 1, enforcePMColor, dstFilter,
    142                                                       nullptr, nullptr);
    143                 SkPaint p;
    144                 p.setImageFilter(SkArithmeticImageFilter::Make(0, one / 2, -one, 1, true,
    145                                                                std::move(bg), dstFilter, nullptr));
    146                 canvas->saveLayer(&rect, &p);
    147                 canvas->restore();
    148                 canvas->translate(gap, 0);
    149 
    150                 // Label
    151                 SkPaint paint;
    152                 paint.setTextSize(SkIntToScalar(24));
    153                 paint.setAntiAlias(true);
    154                 sk_tool_utils::set_portable_typeface(&paint);
    155                 SkString str(enforcePMColor ? "enforcePM" : "no enforcePM");
    156                 canvas->drawString(str, 0, paint.getTextSize(), paint);
    157             }
    158             canvas->translate(0, HH + 12);
    159         }
    160     }
    161 
    162 private:
    163     typedef GM INHERITED;
    164 };
    165 
    166 ///////////////////////////////////////////////////////////////////////////////
    167 
    168 DEF_GM( return new ArithmodeGM; )
    169