aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/opts/SkColorCubeFilter_opts.h
blob: 41d2525b5a387a8df89bf017f0e22a59eb3bbae6 (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
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SkColorCubeFilter_opts_DEFINED
#define SkColorCubeFilter_opts_DEFINED

#include "SkColor.h"
#include "SkPMFloat.h"
#include "SkUnPreMultiply.h"

namespace SK_OPTS_NS {

void color_cube_filter_span(const SkPMColor src[],
                            int count,
                            SkPMColor dst[],
                            const int* colorToIndex[2],
                            const SkScalar* colorToFactors[2],
                            int dim,
                            const SkColor* colorCube) {
    uint8_t* ptr_dst = reinterpret_cast<uint8_t*>(dst);
    uint8_t r, g, b, a;

    for (int i = 0; i < count; ++i) {
        const SkPMColor input = src[i];
        a = input >> SK_A32_SHIFT;

        if (a != 255) {
            const SkColor source = SkUnPreMultiply::PMColorToColor(input);
            r = SkColorGetR(source);
            g = SkColorGetG(source);
            b = SkColorGetB(source);
        } else {
            r = SkGetPackedR32(input);
            g = SkGetPackedG32(input);
            b = SkGetPackedB32(input);
        }

        const SkScalar g0 = colorToFactors[0][g],
                       g1 = colorToFactors[1][g],
                       b0 = colorToFactors[0][b],
                       b1 = colorToFactors[1][b];

        const Sk4f g0b0(g0*b0),
                   g0b1(g0*b1),
                   g1b0(g1*b0),
                   g1b1(g1*b1);

        const int i00 = (colorToIndex[0][g] + colorToIndex[0][b] * dim) * dim;
        const int i01 = (colorToIndex[0][g] + colorToIndex[1][b] * dim) * dim;
        const int i10 = (colorToIndex[1][g] + colorToIndex[0][b] * dim) * dim;
        const int i11 = (colorToIndex[1][g] + colorToIndex[1][b] * dim) * dim;

        SkPMFloat color(0,0,0,0);

        for (int x = 0; x < 2; ++x) {
            const int ix = colorToIndex[x][r];

            const SkColor lutColor00 = colorCube[ix + i00];
            const SkColor lutColor01 = colorCube[ix + i01];
            const SkColor lutColor10 = colorCube[ix + i10];
            const SkColor lutColor11 = colorCube[ix + i11];

            Sk4f  sum = SkPMFloat::FromOpaqueColor(lutColor00) * g0b0;
            sum = sum + SkPMFloat::FromOpaqueColor(lutColor01) * g0b1;
            sum = sum + SkPMFloat::FromOpaqueColor(lutColor10) * g1b0;
            sum = sum + SkPMFloat::FromOpaqueColor(lutColor11) * g1b1;

            color = color + sum * Sk4f((float)colorToFactors[x][r]);
        }

        if (a != 255) {
            color = color * Sk4f(a * 1.0f/255);
        }

        dst[i] = color.round();

        ptr_dst[SK_A32_SHIFT / 8] = a;
        ptr_dst += 4;
    }
}

}  // namespace SK_OPTS NS

#endif  // SkColorCubeFilter_opts_DEFINED