aboutsummaryrefslogtreecommitdiffhomepage
path: root/gm/xfer4f.cpp
blob: dc7196d399fd91c413f5513ed915f410a8e1bf92 (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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkCanvas.h"
#include "SkImageInfo.h"
#include "SkXfermode.h"
#include "SkPM4f.h"

static void draw_rect(SkCanvas* canvas, const SkRect& r, SkColor c, SkColorProfileType profile,
                      const SkAlpha aa[]) {
    const SkIRect ir = r.round();

    SkBitmap bm;
    bm.allocN32Pixels(ir.width(), ir.height());
    bm.eraseColor(0xFFFFFFFF);
    SkPixmap pm;
    bm.peekPixels(&pm);

    uint32_t flags = 0;
    if (SkColorGetA(c) == 0xFF) {
        flags |= SkXfermode::kSrcIsOpaque_PM4fFlag;
    }
    if (kSRGB_SkColorProfileType == profile) {
        flags |= SkXfermode::kDstIsSRGB_PM4fFlag;
    }

    const SkXfermode::PM4fState state { nullptr, flags };

    const SkPM4f src = SkColor4f::FromColor(c).premul();
    auto proc1 = SkXfermode::GetPM4fProc1(SkXfermode::kSrcOver_Mode, flags);
    for (int y = 0; y < ir.height()/2; ++y) {
        proc1(state, pm.writable_addr32(0, y), src, ir.width(), aa);
    }

    SkPM4f srcRow[1000];
    for (int i = 0; i < ir.width(); ++i) {
        srcRow[i] = src;
    }
    auto procN = SkXfermode::GetPM4fProcN(SkXfermode::kSrcOver_Mode, flags);
    // +1 to skip a row, so we can see the boundary between proc1 and procN
    for (int y = ir.height()/2 + 1; y < ir.height(); ++y) {
        procN(state, pm.writable_addr32(0, y), srcRow, ir.width(), aa);
    }

    canvas->drawBitmap(bm, r.left(), r.top(), nullptr);
}

/*
 *  Test SkXfer4fProcs directly for src-over, comparing them to current SkColor blits.
 */
DEF_SIMPLE_GM(xfer4f_srcover, canvas, 580, 760) {
    const int IW = 50;
    const SkScalar W = IW;
    const SkScalar H = 100;

    const int profiles[] = {
        -1,
        kLinear_SkColorProfileType,
        kSRGB_SkColorProfileType,
    };
    const SkColor colors[] = {
        SK_ColorBLACK, SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
        0x88000000, 0x88FF0000, 0x8800FF00, 0x880000FF
    };
    
    uint8_t aa_scanline[IW];
    for (int i = 0; i < IW; ++i) {
        aa_scanline[i] = i * 255 / (IW - 1);
    }
    uint8_t const* aa_table[] = { nullptr, aa_scanline };

    SkBitmap mask;
    mask.installPixels(SkImageInfo::MakeA8(IW, 1), aa_scanline, IW);

    canvas->translate(20, 20);

    const SkRect r = SkRect::MakeWH(W, H);
    for (const uint8_t* aa : aa_table) {
        canvas->save();
        for (auto profile : profiles) {
            canvas->save();
            for (SkColor c : colors) {
                if (profile < 0) {
                    SkPaint p;
                    p.setColor(c);
                    if (aa) {
                        canvas->drawBitmapRect(mask, r, &p);
                    } else {
                        canvas->drawRect(r, p);
                    }
                } else {
                    draw_rect(canvas, r, c, (SkColorProfileType)profile, aa);
                }
                canvas->translate(W + 20, 0);
            }
            canvas->restore();
            canvas->translate(0, H + 20);
        }
        canvas->restore();
        canvas->translate(0, (H + 20) * SK_ARRAY_COUNT(profiles) + 20);
    }
}