Coverage Report

Created: 2026-03-31 11:00

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/BitmapColor.hxx>
28
#include <vcl/BitmapPalette.hxx>
29
#include <vcl/bitmap.hxx>
30
#include <vcl/outdev.hxx>
31
32
#include <svdata.hxx>
33
#include <salinst.hxx>
34
35
class ImplBitmapPalette
36
{
37
public:
38
    ImplBitmapPalette(std::initializer_list<BitmapColor> aBitmapColor)
39
3.52k
        : maBitmapColor(aBitmapColor)
40
3.52k
    {
41
3.52k
    }
42
    ImplBitmapPalette(const BitmapColor* first, const BitmapColor* last)
43
13
        : maBitmapColor(first, last)
44
13
    {
45
13
    }
46
29
    ImplBitmapPalette() {}
47
    ImplBitmapPalette(sal_uInt16 nCount)
48
10.0k
        : maBitmapColor(nCount)
49
10.0k
    {
50
10.0k
    }
51
4.98M
    std::vector<BitmapColor>& GetBitmapData() { return maBitmapColor; }
52
1.14G
    const std::vector<BitmapColor>& GetBitmapData() const { return maBitmapColor; }
53
    bool operator==(const ImplBitmapPalette& rBitmapPalette) const
54
1.57k
    {
55
1.57k
        return maBitmapColor == rBitmapPalette.maBitmapColor;
56
1.57k
    }
57
58
private:
59
    std::vector<BitmapColor> maBitmapColor;
60
};
61
62
namespace
63
{
64
BitmapPalette::ImplType& GetGlobalDefault()
65
700k
{
66
700k
    static BitmapPalette::ImplType gDefault;
67
700k
    return gDefault;
68
700k
}
69
}
70
71
BitmapPalette::BitmapPalette()
72
700k
    : mpImpl(GetGlobalDefault())
73
700k
{
74
700k
}
75
76
BitmapPalette::BitmapPalette(const BitmapPalette& rOther)
77
136k
    : mpImpl(rOther.mpImpl)
78
136k
{
79
136k
}
80
81
BitmapPalette::BitmapPalette(BitmapPalette&& rOther) noexcept
82
1.19M
    : mpImpl(std::move(rOther.mpImpl))
83
1.19M
{
84
1.19M
}
85
86
BitmapPalette::BitmapPalette(std::initializer_list<BitmapColor> aBitmapColor)
87
3.52k
    : mpImpl(aBitmapColor)
88
3.52k
{
89
3.52k
}
90
91
BitmapPalette::BitmapPalette(const BitmapColor* first, const BitmapColor* last)
92
13
    : mpImpl({ first, last })
93
13
{
94
13
}
95
96
BitmapPalette::BitmapPalette(sal_uInt16 nCount)
97
10.0k
    : mpImpl(nCount)
98
10.0k
{
99
10.0k
}
100
101
2.04M
BitmapPalette::~BitmapPalette() {}
102
103
BitmapPalette& BitmapPalette::operator=(const BitmapPalette& rOther)
104
171k
{
105
171k
    mpImpl = rOther.mpImpl;
106
171k
    return *this;
107
171k
}
108
109
BitmapPalette& BitmapPalette::operator=(BitmapPalette&& rOther) noexcept
110
0
{
111
0
    mpImpl = std::move(rOther.mpImpl);
112
0
    return *this;
113
0
}
114
115
const BitmapColor* BitmapPalette::ImplGetColorBuffer() const
116
9.08k
{
117
9.08k
    return mpImpl->GetBitmapData().data();
118
9.08k
}
119
120
0
BitmapColor* BitmapPalette::ImplGetColorBuffer() { return mpImpl->GetBitmapData().data(); }
121
122
BitmapChecksum BitmapPalette::GetChecksum() const
123
6.62k
{
124
6.62k
    auto const& rBitmapData = mpImpl->GetBitmapData();
125
6.62k
    return rtl_crc32(0, rBitmapData.data(), rBitmapData.size() * sizeof(BitmapColor));
126
6.62k
}
127
128
bool BitmapPalette::operator==(const BitmapPalette& rOther) const
129
1.57k
{
130
1.57k
    return mpImpl == rOther.mpImpl;
131
1.57k
}
132
133
38.4M
bool BitmapPalette::operator!() const { return mpImpl->GetBitmapData().empty(); }
134
135
176M
sal_uInt16 BitmapPalette::GetEntryCount() const { return mpImpl->GetBitmapData().size(); }
136
137
215k
void BitmapPalette::SetEntryCount(sal_uInt16 nCount) { mpImpl->GetBitmapData().resize(nCount); }
138
139
const BitmapColor& BitmapPalette::operator[](sal_uInt16 nIndex) const
140
929M
{
141
929M
    assert(nIndex < mpImpl->GetBitmapData().size() && "Palette index is out of range");
142
929M
    return mpImpl->GetBitmapData()[nIndex];
143
929M
}
144
145
BitmapColor& BitmapPalette::operator[](sal_uInt16 nIndex)
146
4.77M
{
147
4.77M
    assert(nIndex < mpImpl->GetBitmapData().size() && "Palette index is out of range");
148
4.77M
    return mpImpl->GetBitmapData()[nIndex];
149
4.77M
}
150
151
/// Returns the BitmapColor (i.e. palette index) that is either an exact match
152
/// of the required color, or failing that, the entry that is the closest i.e. least error
153
/// as measured by Color::GetColorError.
154
sal_uInt16 BitmapPalette::GetBestIndex(const BitmapColor& rCol) const
155
135k
{
156
135k
    auto const& rBitmapColor = mpImpl->GetBitmapData();
157
135k
    sal_uInt16 nRetIndex = 0;
158
159
135k
    if (!rBitmapColor.empty())
160
135k
    {
161
20.2M
        for (size_t j = 0; j < rBitmapColor.size(); ++j)
162
20.1M
        {
163
20.1M
            if (rCol == rBitmapColor[j])
164
104k
            {
165
104k
                return j;
166
104k
            }
167
20.1M
        }
168
169
30.7k
        sal_uInt16 nLastErr = SAL_MAX_UINT16;
170
7.91M
        for (size_t i = 0; i < rBitmapColor.size(); ++i)
171
7.87M
        {
172
7.87M
            const sal_uInt16 nActErr = rCol.GetColorError(rBitmapColor[i]);
173
7.87M
            if (nActErr < nLastErr)
174
51.0k
            {
175
51.0k
                nLastErr = nActErr;
176
51.0k
                nRetIndex = i;
177
51.0k
            }
178
7.87M
        }
179
30.7k
    }
180
181
30.7k
    return nRetIndex;
182
135k
}
183
184
/// Returns the BitmapColor (i.e. palette index) that is an exact match
185
/// of the required color. Returns SAL_MAX_UINT16 if nothing found.
186
sal_uInt16 BitmapPalette::GetMatchingIndex(const BitmapColor& rCol) const
187
0
{
188
0
    auto const& rBitmapColor = mpImpl->GetBitmapData();
189
190
0
    for (size_t j = 0; j < rBitmapColor.size(); ++j)
191
0
    {
192
0
        if (rCol == rBitmapColor[j])
193
0
        {
194
0
            return j;
195
0
        }
196
0
    }
197
198
0
    return SAL_MAX_UINT16;
199
0
}
200
201
bool BitmapPalette::IsGreyPaletteAny() const
202
1.57k
{
203
1.57k
    auto const& rBitmapColor = mpImpl->GetBitmapData();
204
1.57k
    const int nEntryCount = GetEntryCount();
205
1.57k
    if (!nEntryCount) // NOTE: an empty palette means 1:1 mapping
206
0
        return true;
207
    // See above: only certain entry values will result in a valid call to GetGreyPalette
208
1.57k
    if (nEntryCount == 2 || nEntryCount == 4 || nEntryCount == 16 || nEntryCount == 256)
209
1.57k
    {
210
1.57k
        const BitmapPalette& rGreyPalette = Bitmap::GetGreyPalette(nEntryCount);
211
1.57k
        if (rGreyPalette == *this)
212
0
            return true;
213
1.57k
    }
214
215
1.57k
    bool bRet = false;
216
    // TODO: is it worth to compare the entries for the general case?
217
1.57k
    if (nEntryCount == 2)
218
0
    {
219
0
        const BitmapColor& rCol0(rBitmapColor[0]);
220
0
        const BitmapColor& rCol1(rBitmapColor[1]);
221
0
        bRet = rCol0.GetRed() == rCol0.GetGreen() && rCol0.GetRed() == rCol0.GetBlue()
222
0
               && rCol1.GetRed() == rCol1.GetGreen() && rCol1.GetRed() == rCol1.GetBlue();
223
0
    }
224
1.57k
    return bRet;
225
1.57k
}
226
227
bool BitmapPalette::IsGreyPalette8Bit() const
228
61.2k
{
229
61.2k
    auto const& rBitmapColor = mpImpl->GetBitmapData();
230
61.2k
    const int nEntryCount = GetEntryCount();
231
61.2k
    if (!nEntryCount) // NOTE: an empty palette means 1:1 mapping
232
0
        return true;
233
61.2k
    if (nEntryCount != 256)
234
980
        return false;
235
9.56M
    for (sal_uInt16 i = 0; i < 256; ++i)
236
9.52M
    {
237
9.52M
        if (rBitmapColor[i] != BitmapColor(i, i, i))
238
23.1k
            return false;
239
9.52M
    }
240
37.1k
    return true;
241
60.2k
}
242
243
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */