Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/bitmap/bitmappalette.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <config_features.h>
21
22
#include <sal/log.hxx>
23
#include <osl/diagnose.h>
24
#include <rtl/crc.h>
25
#include <tools/helpers.hxx>
26
27
#include <vcl/BitmapPalette.hxx>
28
#include <vcl/bitmap.hxx>
29
#include <vcl/outdev.hxx>
30
31
#include <svdata.hxx>
32
#include <salinst.hxx>
33
34
class ImplBitmapPalette
35
{
36
public:
37
    ImplBitmapPalette(std::initializer_list<BitmapColor> aBitmapColor)
38
5.30k
        : maBitmapColor(aBitmapColor)
39
5.30k
    {
40
5.30k
    }
41
    ImplBitmapPalette(const BitmapColor* first, const BitmapColor* last)
42
13
        : maBitmapColor(first, last)
43
13
    {
44
13
    }
45
29
    ImplBitmapPalette() {}
46
    ImplBitmapPalette(sal_uInt16 nCount)
47
10.7k
        : maBitmapColor(nCount)
48
10.7k
    {
49
10.7k
    }
50
7.66M
    std::vector<BitmapColor>& GetBitmapData() { return maBitmapColor; }
51
2.59G
    const std::vector<BitmapColor>& GetBitmapData() const { return maBitmapColor; }
52
    bool operator==(const ImplBitmapPalette& rBitmapPalette) const
53
1.88k
    {
54
1.88k
        return maBitmapColor == rBitmapPalette.maBitmapColor;
55
1.88k
    }
56
57
private:
58
    std::vector<BitmapColor> maBitmapColor;
59
};
60
61
namespace
62
{
63
BitmapPalette::ImplType& GetGlobalDefault()
64
2.01M
{
65
2.01M
    static BitmapPalette::ImplType gDefault;
66
2.01M
    return gDefault;
67
2.01M
}
68
}
69
70
BitmapPalette::BitmapPalette()
71
2.01M
    : mpImpl(GetGlobalDefault())
72
2.01M
{
73
2.01M
}
74
75
BitmapPalette::BitmapPalette(const BitmapPalette& rOther)
76
207k
    : mpImpl(rOther.mpImpl)
77
207k
{
78
207k
}
79
80
BitmapPalette::BitmapPalette(BitmapPalette&& rOther) noexcept
81
3.78M
    : mpImpl(std::move(rOther.mpImpl))
82
3.78M
{
83
3.78M
}
84
85
BitmapPalette::BitmapPalette(std::initializer_list<BitmapColor> aBitmapColor)
86
5.30k
    : mpImpl(aBitmapColor)
87
5.30k
{
88
5.30k
}
89
90
BitmapPalette::BitmapPalette(const BitmapColor* first, const BitmapColor* last)
91
13
    : mpImpl({ first, last })
92
13
{
93
13
}
94
95
BitmapPalette::BitmapPalette(sal_uInt16 nCount)
96
10.7k
    : mpImpl(nCount)
97
10.7k
{
98
10.7k
}
99
100
6.01M
BitmapPalette::~BitmapPalette() {}
101
102
BitmapPalette& BitmapPalette::operator=(const BitmapPalette& rOther)
103
244k
{
104
244k
    mpImpl = rOther.mpImpl;
105
244k
    return *this;
106
244k
}
107
108
BitmapPalette& BitmapPalette::operator=(BitmapPalette&& rOther) noexcept
109
0
{
110
0
    mpImpl = std::move(rOther.mpImpl);
111
0
    return *this;
112
0
}
113
114
const BitmapColor* BitmapPalette::ImplGetColorBuffer() const
115
8.48k
{
116
8.48k
    return mpImpl->GetBitmapData().data();
117
8.48k
}
118
119
0
BitmapColor* BitmapPalette::ImplGetColorBuffer() { return mpImpl->GetBitmapData().data(); }
120
121
BitmapChecksum BitmapPalette::GetChecksum() const
122
6.30k
{
123
6.30k
    auto const& rBitmapData = mpImpl->GetBitmapData();
124
6.30k
    return rtl_crc32(0, rBitmapData.data(), rBitmapData.size() * sizeof(BitmapColor));
125
6.30k
}
126
127
bool BitmapPalette::operator==(const BitmapPalette& rOther) const
128
1.88k
{
129
1.88k
    return mpImpl == rOther.mpImpl;
130
1.88k
}
131
132
80.9M
bool BitmapPalette::operator!() const { return mpImpl->GetBitmapData().empty(); }
133
134
179M
sal_uInt16 BitmapPalette::GetEntryCount() const { return mpImpl->GetBitmapData().size(); }
135
136
295k
void BitmapPalette::SetEntryCount(sal_uInt16 nCount) { mpImpl->GetBitmapData().resize(nCount); }
137
138
const BitmapColor& BitmapPalette::operator[](sal_uInt16 nIndex) const
139
2.33G
{
140
2.33G
    assert(nIndex < mpImpl->GetBitmapData().size() && "Palette index is out of range");
141
2.33G
    return mpImpl->GetBitmapData()[nIndex];
142
2.33G
}
143
144
BitmapColor& BitmapPalette::operator[](sal_uInt16 nIndex)
145
7.37M
{
146
7.37M
    assert(nIndex < mpImpl->GetBitmapData().size() && "Palette index is out of range");
147
7.37M
    return mpImpl->GetBitmapData()[nIndex];
148
7.37M
}
149
150
/// Returns the BitmapColor (i.e. palette index) that is either an exact match
151
/// of the required color, or failing that, the entry that is the closest i.e. least error
152
/// as measured by Color::GetColorError.
153
sal_uInt16 BitmapPalette::GetBestIndex(const BitmapColor& rCol) const
154
206k
{
155
206k
    auto const& rBitmapColor = mpImpl->GetBitmapData();
156
206k
    sal_uInt16 nRetIndex = 0;
157
158
206k
    if (!rBitmapColor.empty())
159
206k
    {
160
34.5M
        for (size_t j = 0; j < rBitmapColor.size(); ++j)
161
34.5M
        {
162
34.5M
            if (rCol == rBitmapColor[j])
163
150k
            {
164
150k
                return j;
165
150k
            }
166
34.5M
        }
167
168
56.3k
        sal_uInt16 nLastErr = SAL_MAX_UINT16;
169
14.4M
        for (size_t i = 0; i < rBitmapColor.size(); ++i)
170
14.4M
        {
171
14.4M
            const sal_uInt16 nActErr = rCol.GetColorError(rBitmapColor[i]);
172
14.4M
            if (nActErr < nLastErr)
173
96.6k
            {
174
96.6k
                nLastErr = nActErr;
175
96.6k
                nRetIndex = i;
176
96.6k
            }
177
14.4M
        }
178
56.3k
    }
179
180
56.3k
    return nRetIndex;
181
206k
}
182
183
/// Returns the BitmapColor (i.e. palette index) that is an exact match
184
/// of the required color. Returns SAL_MAX_UINT16 if nothing found.
185
sal_uInt16 BitmapPalette::GetMatchingIndex(const BitmapColor& rCol) const
186
0
{
187
0
    auto const& rBitmapColor = mpImpl->GetBitmapData();
188
189
0
    for (size_t j = 0; j < rBitmapColor.size(); ++j)
190
0
    {
191
0
        if (rCol == rBitmapColor[j])
192
0
        {
193
0
            return j;
194
0
        }
195
0
    }
196
197
0
    return SAL_MAX_UINT16;
198
0
}
199
200
bool BitmapPalette::IsGreyPaletteAny() const
201
1.88k
{
202
1.88k
    auto const& rBitmapColor = mpImpl->GetBitmapData();
203
1.88k
    const int nEntryCount = GetEntryCount();
204
1.88k
    if (!nEntryCount) // NOTE: an empty palette means 1:1 mapping
205
0
        return true;
206
    // See above: only certain entry values will result in a valid call to GetGreyPalette
207
1.88k
    if (nEntryCount == 2 || nEntryCount == 4 || nEntryCount == 16 || nEntryCount == 256)
208
1.88k
    {
209
1.88k
        const BitmapPalette& rGreyPalette = Bitmap::GetGreyPalette(nEntryCount);
210
1.88k
        if (rGreyPalette == *this)
211
0
            return true;
212
1.88k
    }
213
214
1.88k
    bool bRet = false;
215
    // TODO: is it worth to compare the entries for the general case?
216
1.88k
    if (nEntryCount == 2)
217
0
    {
218
0
        const BitmapColor& rCol0(rBitmapColor[0]);
219
0
        const BitmapColor& rCol1(rBitmapColor[1]);
220
0
        bRet = rCol0.GetRed() == rCol0.GetGreen() && rCol0.GetRed() == rCol0.GetBlue()
221
0
               && rCol1.GetRed() == rCol1.GetGreen() && rCol1.GetRed() == rCol1.GetBlue();
222
0
    }
223
1.88k
    return bRet;
224
1.88k
}
225
226
bool BitmapPalette::IsGreyPalette8Bit() const
227
92.9k
{
228
92.9k
    auto const& rBitmapColor = mpImpl->GetBitmapData();
229
92.9k
    const int nEntryCount = GetEntryCount();
230
92.9k
    if (!nEntryCount) // NOTE: an empty palette means 1:1 mapping
231
0
        return true;
232
92.9k
    if (nEntryCount != 256)
233
1.06k
        return false;
234
15.3M
    for (sal_uInt16 i = 0; i < 256; ++i)
235
15.3M
    {
236
15.3M
        if (rBitmapColor[i] != BitmapColor(i, i, i))
237
32.1k
            return false;
238
15.3M
    }
239
59.7k
    return true;
240
91.8k
}
241
242
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */