Coverage Report

Created: 2026-09-28 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/font/fontcharmap.cxx
Line
Count
Source
1
/*
2
 * This file is part of the LibreOffice project.
3
 *
4
 * This Source Code Form is subject to the terms of the Mozilla Public
5
 * License, v. 2.0. If a copy of the MPL was not distributed with this
6
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
 *
8
 * This file incorporates work covered by the following license notice:
9
 *
10
 *   Licensed to the Apache Software Foundation (ASF) under one or more
11
 *   contributor license agreements. See the NOTICE file distributed
12
 *   with this work for additional information regarding copyright
13
 *   ownership. The ASF licenses this file to you under the Apache
14
 *   License, Version 2.0 (the "License"); you may not use this file
15
 *   except in compliance with the License. You may obtain a copy of
16
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
17
 */
18
#include <utility>
19
#include <vcl/fontcharmap.hxx>
20
#include <impfontcharmap.hxx>
21
#include <sal/log.hxx>
22
23
#include <algorithm>
24
#include <vector>
25
26
static ImplFontCharMapRef g_pDefaultImplFontCharMap;
27
const std::vector<sal_uInt32> aDefaultUnicodeRanges = { 0x0020, 0xD800, 0xE000, 0xFFF0 };
28
const std::vector<sal_uInt32> aDefaultSymbolRanges = { 0x0020, 0x0100, 0xF020, 0xF100 };
29
30
ImplFontCharMap::~ImplFontCharMap()
31
0
{
32
0
}
33
34
ImplFontCharMap::ImplFontCharMap(std::vector<sal_uInt32> aRangeCodes)
35
5
:   maRangeCodes(std::move(aRangeCodes))
36
5
,   mnCharCount( 0 )
37
5
{
38
630
    for (size_t i = 0; i < maRangeCodes.size(); i += 2)
39
625
    {
40
625
        sal_UCS4 cFirst = maRangeCodes[i];
41
625
        sal_UCS4 cLast = maRangeCodes[i + 1];
42
625
        mnCharCount += cLast - cFirst;
43
625
    }
44
5
}
45
46
ImplFontCharMapRef const & ImplFontCharMap::getDefaultMap(bool bMicrosoftSymbolMap)
47
0
{
48
0
    const auto& rRanges = bMicrosoftSymbolMap ? aDefaultSymbolRanges : aDefaultUnicodeRanges;
49
0
    g_pDefaultImplFontCharMap = ImplFontCharMapRef(new ImplFontCharMap(rRanges));
50
0
    return g_pDefaultImplFontCharMap;
51
0
}
52
53
bool ImplFontCharMap::isDefaultMap() const
54
199k
{
55
199k
    const bool bIsDefault = (maRangeCodes == aDefaultUnicodeRanges) || (maRangeCodes == aDefaultSymbolRanges);
56
199k
    return bIsDefault;
57
199k
}
58
59
FontCharMap::FontCharMap()
60
0
    : mpImplFontCharMap( ImplFontCharMap::getDefaultMap() )
61
0
{
62
0
}
63
64
FontCharMap::FontCharMap( ImplFontCharMapRef pIFCMap )
65
0
    : mpImplFontCharMap(std::move( pIFCMap ))
66
0
{
67
0
}
68
69
FontCharMap::FontCharMap(std::vector<sal_uInt32> aRangeCodes)
70
5
    : mpImplFontCharMap(new ImplFontCharMap(std::move(aRangeCodes)))
71
5
{
72
5
}
73
74
FontCharMap::~FontCharMap()
75
0
{
76
0
    mpImplFontCharMap = nullptr;
77
0
}
78
79
FontCharMapRef FontCharMap::GetDefaultMap(bool bMicrosoftSymbolMap)
80
0
{
81
0
    FontCharMapRef xFontCharMap( new FontCharMap( ImplFontCharMap::getDefaultMap(bMicrosoftSymbolMap) ) );
82
0
    return xFontCharMap;
83
0
}
84
85
bool FontCharMap::IsDefaultMap() const
86
199k
{
87
199k
    return mpImplFontCharMap->isDefaultMap();
88
199k
}
89
90
int FontCharMap::GetCharCount() const
91
0
{
92
0
    return mpImplFontCharMap->mnCharCount;
93
0
}
94
95
int FontCharMap::CountCharsInRange( sal_UCS4 cMin, sal_UCS4 cMax ) const
96
0
{
97
0
    const auto& rRanges = mpImplFontCharMap->maRangeCodes;
98
0
    int nCount = 0;
99
100
    // find and adjust range and char count for cMin
101
0
    int nRangeMin = findRangeIndex( cMin );
102
0
    if( nRangeMin & 1 )
103
0
        ++nRangeMin;
104
0
    else if (cMin > rRanges[nRangeMin])
105
0
        nCount -= cMin - rRanges[nRangeMin];
106
107
    // find and adjust range and char count for cMax
108
0
    int nRangeMax = findRangeIndex( cMax );
109
0
    if( nRangeMax & 1 )
110
0
        --nRangeMax;
111
0
    else
112
0
        nCount -= rRanges[nRangeMax + 1] - cMax - 1;
113
114
    // count chars in complete ranges between cMin and cMax
115
0
    for( int i = nRangeMin; i <= nRangeMax; i+=2 )
116
0
        nCount += rRanges[i + 1] - rRanges[i];
117
118
0
    return nCount;
119
0
}
120
121
bool FontCharMap::HasChar( sal_UCS4 cChar ) const
122
1.19M
{
123
1.19M
    const int nRange = findRangeIndex( cChar );
124
1.19M
    if (nRange==0 && cChar < mpImplFontCharMap->maRangeCodes[0])
125
0
        return false;
126
1.19M
    return ((nRange & 1) == 0); // inside a range
127
1.19M
}
128
129
sal_UCS4 FontCharMap::GetFirstChar() const
130
0
{
131
0
    return mpImplFontCharMap->maRangeCodes.front();
132
0
}
133
134
sal_UCS4 FontCharMap::GetLastChar() const
135
0
{
136
0
    return mpImplFontCharMap->maRangeCodes.back() - 1;
137
0
}
138
139
sal_UCS4 FontCharMap::GetNextChar( sal_UCS4 cChar ) const
140
0
{
141
0
    if( cChar < GetFirstChar() )
142
0
        return GetFirstChar();
143
0
    if( cChar >= GetLastChar() )
144
0
        return GetLastChar();
145
146
0
    int nRange = findRangeIndex( cChar + 1 );
147
0
    if( nRange & 1 )                       // outside of range?
148
0
        return mpImplFontCharMap->maRangeCodes[nRange + 1]; // => first in next range
149
0
    return (cChar + 1);
150
0
}
151
152
sal_UCS4 FontCharMap::GetPrevChar( sal_UCS4 cChar ) const
153
0
{
154
0
    if( cChar <= GetFirstChar() )
155
0
        return GetFirstChar();
156
0
    if( cChar > GetLastChar() )
157
0
        return GetLastChar();
158
159
0
    int nRange = findRangeIndex( cChar - 1 );
160
0
    if( nRange & 1 )                            // outside a range?
161
0
        return mpImplFontCharMap->maRangeCodes[nRange] - 1;    // => last in prev range
162
0
    return (cChar - 1);
163
0
}
164
165
int FontCharMap::GetIndexFromChar( sal_UCS4 cChar ) const
166
0
{
167
    // TODO: improve linear walk?
168
0
    int nCharIndex = 0;
169
0
    const auto& rRanges = mpImplFontCharMap->maRangeCodes;
170
0
    for (size_t i = 0; i < rRanges.size(); i += 2)
171
0
    {
172
0
        sal_UCS4 cFirst = rRanges[i];
173
0
        sal_UCS4 cLast = rRanges[i + 1];
174
0
        if( cChar >= cLast )
175
0
            nCharIndex += cLast - cFirst;
176
0
        else if( cChar >= cFirst )
177
0
            return nCharIndex + (cChar - cFirst);
178
0
        else
179
0
            break;
180
0
    }
181
182
0
    return -1;
183
0
}
184
185
sal_UCS4 FontCharMap::GetCharFromIndex( int nIndex ) const
186
0
{
187
    // TODO: improve linear walk?
188
0
    const auto& rRanges = mpImplFontCharMap->maRangeCodes;
189
0
    for (size_t i = 0; i < rRanges.size(); i += 2)
190
0
    {
191
0
        sal_UCS4 cFirst = rRanges[i];
192
0
        sal_UCS4 cLast = rRanges[i + 1];
193
0
        nIndex -= cLast - cFirst;
194
0
        if( nIndex < 0 )
195
0
            return (cLast + nIndex);
196
0
    }
197
198
    // we can only get here with an out-of-bounds charindex
199
0
    return mpImplFontCharMap->maRangeCodes.front();
200
0
}
201
202
int FontCharMap::findRangeIndex( sal_UCS4 cChar ) const
203
1.19M
{
204
1.19M
    const auto& rRanges = mpImplFontCharMap->maRangeCodes;
205
1.19M
    int nLower = 0;
206
1.19M
    int nMid = rRanges.size() / 2;
207
1.19M
    int nUpper = rRanges.size() - 1;
208
10.6M
    while( nLower < nUpper )
209
9.45M
    {
210
9.45M
        if (cChar >= rRanges[nMid])
211
5.87M
            nLower = nMid;
212
3.57M
        else
213
3.57M
            nUpper = nMid - 1;
214
9.45M
        nMid = (nLower + nUpper + 1) / 2;
215
9.45M
    }
216
217
1.19M
    return nMid;
218
1.19M
}
219
220
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */