aboutsummaryrefslogtreecommitdiffhomepage
path: root/gm/buggy_blend_modes.cpp
blob: 21a6798fe07d083a3b5e54ed455fa4d962e43de0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "gm.h"

// This GM reproduces what I think are overflow bugs in the CPU implementations of a
// couple xfermodes.  I've marked non-obvious keys to reproducing the bug // Essential!
DEF_SIMPLE_GM(buggy_blend_modes, canvas, 800, 200) {
    const auto tiling = SkShader::kClamp_TileMode;
    const auto flags = SkGradientShader::kInterpolateColorsInPremul_Flag;  // Essential!

    SkAutoTUnref<SkShader> cyanH, magentaV;
    {
        SkPoint    pts[] = { {0,0}, {200, 0} };
        SkColor colors[] = { 0x00000000, 0xFF00FFFF };
        cyanH.reset(
                SkGradientShader::CreateLinear(pts, colors, nullptr, 2, tiling, flags, nullptr));
    }
    {
        SkPoint    pts[] = { {0,0}, {0, 200} };
        SkColor colors[] = { 0x00000000, 0xFFFF00FF };
        magentaV.reset(
                SkGradientShader::CreateLinear(pts, colors, nullptr, 2, tiling, flags, nullptr));
    }

    SkXfermode::Mode modes[] = {
        SkXfermode::kDarken_Mode,       // Looks ok?
        SkXfermode::kHardLight_Mode,    // Definitely wrong.
        SkXfermode::kLighten_Mode,      // Definitely wrong.
        SkXfermode::kOverlay_Mode,      // Same code as kHardLight_Mode.
    };

    canvas->clear(SK_ColorWHITE);
    for (auto mode : modes) {
        canvas->saveLayer(nullptr, nullptr);  // Essential!
            SkPaint h, v;
            h.setShader(cyanH);
            v.setShader(magentaV);
            v.setXfermodeMode(mode);
            canvas->drawRect(SkRect::MakeWH(200,200), h);
            canvas->drawRect(SkRect::MakeWH(200,200), v);
        canvas->restore();

        canvas->translate(200, 0);
    }
}