Coverage Report

Created: 2021-08-22 09:07

/src/skia/src/codec/SkMasks.cpp
Line
Count
Source
1
/*
2
 * Copyright 2015 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 "include/core/SkTypes.h"
9
#include "src/codec/SkCodecPriv.h"
10
#include "src/codec/SkMasks.h"
11
12
/*
13
 *
14
 * Used to convert 1-7 bit color components into 8-bit color components
15
 *
16
 */
17
static constexpr uint8_t n_bit_to_8_bit_lookup_table[] = {
18
    // 1 bit
19
    0, 255,
20
    // 2 bits
21
    0, 85, 170, 255,
22
    // 3 bits
23
    0, 36, 73, 109, 146, 182, 219, 255,
24
    // 4 bits
25
    0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255,
26
    // 5 bits
27
    0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140,
28
    148, 156, 165, 173, 181, 189, 197, 206, 214, 222, 230, 239, 247, 255,
29
    // 6 bits
30
    0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 45, 49, 53, 57, 61, 65, 69, 73,
31
    77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138,
32
    142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, 194, 198,
33
    202, 206, 210, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255,
34
    // 7 bits
35
    0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38,
36
    40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76,
37
    78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110,
38
    112, 114, 116, 118, 120, 122, 124, 126, 129, 131, 133, 135, 137, 139, 141,
39
    143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171,
40
    173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201,
41
    203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231,
42
    233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255
43
};
44
45
/*
46
 *
47
 * Convert an n bit component to an 8-bit component
48
 *
49
 */
50
54.0k
static uint8_t convert_to_8(uint8_t component, uint32_t n) {
51
54.0k
    if (0 == n) {
52
26.4k
        return 0;
53
27.6k
    } else if (8 > n) {
54
18.0k
        return n_bit_to_8_bit_lookup_table[(1 << n) - 2 + component];
55
9.54k
    } else {
56
9.54k
        SkASSERT(8 == n);
57
9.54k
        return component;
58
9.54k
    }
59
54.0k
}
60
61
static uint8_t get_comp(uint32_t pixel, uint32_t mask, uint32_t shift,
62
54.0k
                        uint32_t size) {
63
54.0k
    return convert_to_8((pixel & mask) >> shift, size);
64
54.0k
}
65
66
/*
67
 *
68
 * Get a color component
69
 *
70
 */
71
15.4k
uint8_t SkMasks::getRed(uint32_t pixel) const {
72
15.4k
    return get_comp(pixel, fRed.mask, fRed.shift, fRed.size);
73
15.4k
}
74
15.4k
uint8_t SkMasks::getGreen(uint32_t pixel) const {
75
15.4k
    return get_comp(pixel, fGreen.mask, fGreen.shift, fGreen.size);
76
15.4k
}
77
15.4k
uint8_t SkMasks::getBlue(uint32_t pixel) const {
78
15.4k
    return get_comp(pixel, fBlue.mask, fBlue.shift, fBlue.size);
79
15.4k
}
80
7.58k
uint8_t SkMasks::getAlpha(uint32_t pixel) const {
81
7.58k
    return get_comp(pixel, fAlpha.mask, fAlpha.shift, fAlpha.size);
82
7.58k
}
83
84
/*
85
 *
86
 * Process an input mask to obtain the necessary information
87
 *
88
 */
89
992
static SkMasks::MaskInfo process_mask(uint32_t mask) {
90
    // Determine properties of the mask
91
992
    uint32_t tempMask = mask;
92
992
    uint32_t shift = 0;
93
992
    uint32_t size = 0;
94
992
    if (tempMask != 0) {
95
        // Count trailing zeros on masks
96
3.66k
        for (; (tempMask & 1) == 0; tempMask >>= 1) {
97
3.17k
            shift++;
98
3.17k
        }
99
        // Count the size of the mask
100
2.00k
        for (; tempMask & 1; tempMask >>= 1) {
101
1.51k
            size++;
102
1.51k
        }
103
        // Verify that the mask is continuous
104
492
        if (tempMask) {
105
248
            SkCodecPrintf("Warning: Bit mask is not continuous.\n");
106
            // Finish processing the mask
107
2.91k
            for (; tempMask; tempMask >>= 1) {
108
2.66k
                size++;
109
2.66k
            }
110
248
        }
111
        // Truncate masks greater than 8 bits
112
492
        if (size > 8) {
113
147
            shift += size - 8;
114
147
            size = 8;
115
147
            mask &= 0xFF << shift;
116
147
        }
117
492
    }
118
119
992
    return { mask, shift, size };
120
992
}
121
122
/*
123
 *
124
 * Create the masks object
125
 *
126
 */
127
259
SkMasks* SkMasks::CreateMasks(InputMasks masks, int bytesPerPixel) {
128
259
    SkASSERT(0 < bytesPerPixel && bytesPerPixel <= 4);
129
130
    // Trim the input masks to match bytesPerPixel.
131
259
    if (bytesPerPixel < 4) {
132
172
        int bitsPerPixel = 8*bytesPerPixel;
133
172
        masks.red   &= (1 << bitsPerPixel) - 1;
134
172
        masks.green &= (1 << bitsPerPixel) - 1;
135
172
        masks.blue  &= (1 << bitsPerPixel) - 1;
136
172
        masks.alpha &= (1 << bitsPerPixel) - 1;
137
172
    }
138
139
    // Check that masks do not overlap.
140
259
    if (((masks.red   & masks.green) |
141
259
         (masks.red   & masks.blue ) |
142
259
         (masks.red   & masks.alpha) |
143
259
         (masks.green & masks.blue ) |
144
259
         (masks.green & masks.alpha) |
145
11
         (masks.blue  & masks.alpha) ) != 0) {
146
11
        return nullptr;
147
11
    }
148
149
248
    return new SkMasks(process_mask(masks.red  ),
150
248
                       process_mask(masks.green),
151
248
                       process_mask(masks.blue ),
152
248
                       process_mask(masks.alpha));
153
248
}
154