Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/unotools/source/misc/fontdefs.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 <o3tl/safeint.hxx>
21
#include <o3tl/string_view.hxx>
22
#include <unotools/fontdefs.hxx>
23
#include <unotools/fontcfg.hxx>
24
#include <rtl/ustrbuf.hxx>
25
26
#include <string_view>
27
#include <unordered_map>
28
29
OUString StripScriptFromName(const OUString& _aName)
30
0
{
31
    // I worry that someone will have a font which *does* have
32
    // e.g. "Greek" legitimately at the end of its name :-(
33
0
    const char*const suffixes[] = { " baltic",
34
0
                              " ce",
35
0
                              " cyr",
36
0
                              " greek",
37
0
                              " tur",
38
0
                              " (arabic)",
39
0
                              " (hebrew)",
40
0
                              " (thai)",
41
0
                              " (vietnamese)"
42
0
                            };
43
44
0
    OUString aName = _aName;
45
    // These can be crazily piled up, e.g. Times New Roman CYR Greek
46
0
    bool bFinished = false;
47
0
    while (!bFinished)
48
0
    {
49
0
        bFinished = true;
50
0
        for (const char* suffix : suffixes)
51
0
        {
52
0
            size_t nLen = strlen(suffix);
53
0
            if (aName.endsWithIgnoreAsciiCaseAsciiL(suffix, nLen))
54
0
            {
55
0
                bFinished = false;
56
0
                aName = aName.copy(0, aName.getLength() - nLen);
57
0
            }
58
0
        }
59
0
    }
60
0
    return aName;
61
0
}
62
63
//return true if the character is stripped from the string
64
static bool toOnlyLowerAsciiOrStrip(sal_Unicode c, OUStringBuffer &rName, sal_Int32 nIndex, sal_Int32& rLen)
65
8.37M
{
66
    // not lowercase Ascii
67
8.37M
    if (c < 'a' || c > 'z')
68
1.61M
    {
69
        // To Lowercase-Ascii
70
1.61M
        if ( (c >= 'A') && (c <= 'Z') )
71
1.09M
        {
72
1.09M
            c += 'a' - 'A';
73
1.09M
            rName[nIndex] = c;
74
1.09M
        }
75
528k
        else if( ((c < '0') || (c > '9')) && (c != ';') && (c != '(') && (c != ')') ) // not 0-9, semicolon, or brackets
76
526k
        {
77
            // Remove white spaces and special characters
78
526k
            rName.remove(nIndex, 1);
79
526k
            rLen--;
80
526k
            return true;
81
526k
        }
82
1.61M
    }
83
7.85M
    return false;
84
8.37M
}
85
86
OUString GetEnglishSearchFontName(std::u16string_view rInName)
87
584k
{
88
584k
    OUStringBuffer rName(rInName);
89
584k
    bool        bNeedTranslation = false;
90
584k
    sal_Int32  nLen = rName.getLength();
91
92
    // Remove trailing whitespaces
93
584k
    sal_Int32 i = nLen;
94
584k
    while ( i && (rName[ i-1 ] < 32) )
95
163
        i--;
96
584k
    if ( i != nLen )
97
106
         rName.truncate(i);
98
99
584k
    nLen = rName.getLength();
100
101
    // remove all whitespaces and converts to lower case ASCII
102
    // TODO: better transliteration to ASCII e.g. all digits
103
584k
    i = 0;
104
9.01M
    while ( i < nLen )
105
8.42M
    {
106
8.42M
        sal_Unicode c = rName[ i ];
107
8.42M
        if ( c > 127 )
108
55.4k
        {
109
            // Translate to Lowercase-ASCII
110
            // FullWidth-ASCII to half ASCII
111
55.4k
            if ( (c >= 0xFF00) && (c <= 0xFF5E) )
112
4.23k
            {
113
4.23k
                c -= 0xFF00-0x0020;
114
4.23k
                rName[ i ] = c;
115
4.23k
                if (toOnlyLowerAsciiOrStrip(c, rName, i, nLen))
116
2.34k
                   continue;
117
4.23k
            }
118
51.2k
            else
119
51.2k
            {
120
                // Only Fontnames with None-Ascii-Characters must be translated
121
51.2k
                bNeedTranslation = true;
122
51.2k
            }
123
55.4k
        }
124
8.37M
        else if (toOnlyLowerAsciiOrStrip(c, rName, i, nLen))
125
524k
            continue;
126
127
7.90M
        i++;
128
7.90M
    }
129
584k
    OUString rNameStr = rName.makeStringAndClear();
130
    // translate normalized localized name to its normalized English ASCII name
131
584k
    if( bNeedTranslation )
132
12.0k
    {
133
12.0k
        typedef std::unordered_map<OUString, OUString> FontNameDictionary;
134
12.0k
        static FontNameDictionary const aDictionary = {
135
12.0k
            {u"\uBC14\uD0D5"_ustr, "batang"},
136
12.0k
            {u"\uBC14\uD0D5\uCCB4"_ustr, "batangche"},
137
12.0k
            {u"\uAD81\uC11C"_ustr, "gungshu"},
138
12.0k
            {u"\uAD81\uC11C\uCCB4"_ustr, "gungshuche"},
139
12.0k
            {u"\uAD74\uB9BC"_ustr, "gulim"},
140
12.0k
            {u"\uAD74\uB9BC\uCCB4"_ustr, "gulimche"},
141
12.0k
            {u"\uB3CB\uC6C0"_ustr, "dotum"},
142
12.0k
            {u"\uB3CB\uC6C0\uCCB4"_ustr, "dotumche"},
143
12.0k
            {u"\u5B8B\u4F53"_ustr, "simsun"},
144
12.0k
            {u"\u65B0\u5B8B\u4F53"_ustr, "nsimsun"},
145
12.0k
            {u"\u9ED1\u4F53"_ustr, "simhei"},
146
12.0k
            {u"\u6977\u4F53"_ustr, "simkai"},
147
12.0k
            {u"\u4E2D\u6613\u5B8B\u4F53"_ustr, "zycjksun"},
148
12.0k
            {u"\u4E2D\u6613\u9ED1\u4F53"_ustr, "zycjkhei"},
149
12.0k
            {u"\u4E2D\u6613\u6977\u4F53"_ustr, "zycjkkai"},
150
12.0k
            {u"\u65B9\u6B63\u9ED1\u4F53"_ustr, "fzhei"},
151
12.0k
            {u"\u65B9\u6B63\u6977\u4F53"_ustr, "fzkai"},
152
12.0k
            {u"\u65B9\u6B63\u5B8B\u4E00"_ustr, "fzsong"},
153
12.0k
            {u"\u65B9\u6B63\u4E66\u5B8B"_ustr, "fzshusong"},
154
12.0k
            {u"\u65B9\u6B63\u4EFF\u5B8B"_ustr, "fzfangsong"},
155
            // Attention: this fonts includes the wrong encoding vector - so we double the names with correct and wrong encoding
156
            // First one is the GB-Encoding (we think the correct one), second is the big5 encoded name
157
12.0k
            {u"m\u7B80\u9ED1"_ustr, "mhei"},
158
12.0k
            {u"m\u6F60\u7AAA"_ustr, "mhei"},
159
12.0k
            {u"m\u7B80\u6977\u566C"_ustr, "mkai"},
160
12.0k
            {u"m\u6F60\u7FF1\u628E"_ustr, "mkai"},
161
12.0k
            {u"m\u7B80\u5B8B"_ustr, "msong"},
162
12.0k
            {u"m\u6F60\u51BC"_ustr, "msong"},
163
12.0k
            {u"m\u7B80\u592B\u5B8B"_ustr, "cfangsong"},
164
12.0k
            {u"m\u6F60\u6E98\u51BC"_ustr, "cfangsong"},
165
12.0k
            {u"\u7D30\u660E\u9AD4"_ustr, "mingliu"},
166
12.0k
            {u"\u65B0\u7D30\u660E\u9AD4"_ustr, "pmingliu"},
167
12.0k
            {u"\u6865"_ustr, "hei"},
168
12.0k
            {u"\u6B61"_ustr, "kai"},
169
12.0k
            {u"\u6D69\u6E67"_ustr, "ming"},
170
12.0k
            {u"ms\u30B4\u30B7\u30C3\u30AF"_ustr, "msgothic"},
171
12.0k
            {u"msp\u30B4\u30B7\u30C3\u30AF"_ustr, "mspgothic"},
172
12.0k
            {u"ms\u660E\u671D"_ustr, "msmincho"},
173
12.0k
            {u"msp\u660E\u671D"_ustr, "mspmincho"},
174
12.0k
            {u"\u5FAE\u8EDF\u6B63\u9ED1\u9AD4"_ustr, "microsoftjhenghei"},
175
12.0k
            {u"\u5FAE\u8F6F\u96C5\u9ED1"_ustr, "microsoftyahei"},
176
12.0k
            {u"\u30e1\u30a4\u30ea\u30aa"_ustr, "meiryo"},
177
12.0k
            {u"hg\u660E\u671Dl"_ustr, "hgminchol"},
178
12.0k
            {u"hg\u30B4\u30B7\u30C3\u30AFb"_ustr, "hggothicb"},
179
12.0k
            {u"hgp\u660E\u671Dl"_ustr, "hgpminchol"},
180
12.0k
            {u"hgp\u30B4\u30B7\u30C3\u30AFb"_ustr, "hgpgothicb"},
181
12.0k
            {u"hg\u660E\u671Dlsun"_ustr, "hgmincholsun"},
182
12.0k
            {u"hg\u30B4\u30B7\u30C3\u30AFbsun"_ustr, "hggothicbsun"},
183
12.0k
            {u"hgp\u660E\u671Dlsun"_ustr, "hgpmincholsun"},
184
12.0k
            {u"hgp\u30B4\u30B7\u30C3\u30AFbsun"_ustr, "hgpgothicbsun"},
185
12.0k
            {u"hg\u5E73\u6210\u660E\u671D\u4F53"_ustr, "hgheiseimin"},
186
12.0k
            {u"hg\u5E73\u6210\u660E\u671D\u4F53w3x12"_ustr, "hgheiseimin"},
187
12.0k
            {u"ipa\u660E\u671D"_ustr, "ipamincho"},
188
12.0k
            {u"ipap\u660E\u671D"_ustr, "ipapmincho"},
189
12.0k
            {u"ipa\u30B4\u30B7\u30C3\u30AF"_ustr, "ipagothic"},
190
12.0k
            {u"ipap\u30B4\u30B7\u30C3\u30AF"_ustr, "ipapgothic"},
191
12.0k
            {u"ipaui\u30B4\u30B7\u30C3\u30AF"_ustr, "ipauigothic"},
192
12.0k
            {u"takao\u660E\u671D"_ustr, "takaomincho"},
193
12.0k
            {u"takaop\u660E\u671D"_ustr, "takaopmincho"},
194
12.0k
            {u"takao\u30B4\u30B7\u30C3\u30AF"_ustr, "takaogothic"},
195
12.0k
            {u"takaop\u30B4\u30B7\u30C3\u30AF"_ustr, "takaopgothic"},
196
12.0k
            {u"\u3055\u3056\u306A\u307F\u660E\u671D"_ustr, "sazanamimincho"},
197
12.0k
            {u"\u3055\u3056\u306A\u307F\u30B4\u30B7\u30C3\u30AF"_ustr, "sazanamigothic"},
198
12.0k
            {u"\u6771\u98A8\u660E\u671D"_ustr, "kochimincho"},
199
12.0k
            {u"\u6771\u98A8\u30B4\u30B7\u30C3\u30AF"_ustr, "kochigothic"},
200
12.0k
            {u"\uC36C\uB3CB\uC6C0"_ustr, "sundotum"},
201
12.0k
            {u"\uC36C\uAD74\uB9BC"_ustr, "sungulim"},
202
12.0k
            {u"\uC36C\uBC14\uD0D5"_ustr, "sunbatang"},
203
12.0k
            {u"\uBC31\uBB35\uB3CB\uC6C0"_ustr, "baekmukdotum"},
204
12.0k
            {u"\uBC31\uBB35\uAD74\uB9BC"_ustr, "baekmukgulim"},
205
12.0k
            {u"\uBC31\uBB35\uBC14\uD0D5"_ustr, "baekmukbatang"},
206
12.0k
            {u"\u65B9\u6B63\u9ED1\u4F53"_ustr, "fzheiti"},
207
12.0k
            {u"\u65B9\u6B63\u9ED1\u9AD4"_ustr, "fzheiti"},
208
12.0k
            {u"\u65B9\u6B63\u6977\u4F53"_ustr, "fzkaiti"},
209
12.0k
            {u"\u65B9\u6B63\u6977\u9AD4"_ustr, "fzkaitib"},
210
12.0k
            {u"\u65B9\u6B63\u660E\u9AD4"_ustr, "fzmingtib"},
211
12.0k
            {u"\u65B9\u6B63\u5B8B\u4F53"_ustr, "fzsongti"},
212
12.0k
            {u"hy\uACAC\uBA85\uC870"_ustr, "hymyeongjoextra"},
213
12.0k
            {u"hy\uC2E0\uBA85\uC870"_ustr, "hysinmyeongjomedium"},
214
12.0k
            {u"hy\uC911\uACE0\uB515"_ustr, "hygothicmedium"},
215
12.0k
            {u"hy\uADF8\uB798\uD53Dm"_ustr, "hygraphicmedium"},
216
12.0k
            {u"hy\uADF8\uB798\uD53D"_ustr, "hygraphic"},
217
12.0k
            {u"\uC0C8\uAD74\uB9BC"_ustr, "newgulim"},
218
12.0k
            {u"\uC36C\uAD81\uC11C"_ustr, "sungungseo"},
219
12.0k
            {u"hy\uAD81\uC11Cb"_ustr, "hygungsobold"},
220
12.0k
            {u"hy\uAD81\uC11C"_ustr, "hygungso"},
221
12.0k
            {u"\uC36C\uD5E4\uB4DC\uB77C\uC778"_ustr, "sunheadline"},
222
12.0k
            {u"hy\uD5E4\uB4DC\uB77C\uC778m"_ustr, "hyheadlinemedium"},
223
12.0k
            {u"hy\uD5E4\uB4DC\uB77C\uC778"_ustr, "hyheadline"},
224
12.0k
            {u"\uD734\uBA3C\uC61B\uCCB4"_ustr, "yetr"},
225
12.0k
            {u"hy\uACAC\uACE0\uB515"_ustr, "hygothicextra"},
226
12.0k
            {u"\uC36C\uBAA9\uD310"_ustr, "sunmokpan"},
227
12.0k
            {u"\uC36C\uC5FD\uC11C"_ustr, "sunyeopseo"},
228
12.0k
            {u"\uC36C\uBC31\uC1A1"_ustr, "sunbaeksong"},
229
12.0k
            {u"hy\uC5FD\uC11Cl"_ustr, "hypostlight"},
230
12.0k
            {u"hy\uC5FD\uC11C"_ustr, "hypost"},
231
12.0k
            {u"\uD734\uBA3C\uB9E4\uC9C1\uCCB4"_ustr, "magicr"},
232
12.0k
            {u"\uC36C\uD06C\uB9AC\uC2A4\uD0C8"_ustr, "suncrystal"},
233
12.0k
            {u"\uC36C\uC0D8\uBB3C"_ustr, "sunsaemmul"},
234
12.0k
            {u"hy\uC595\uC740\uC0D8\uBB3Cm"_ustr, "hyshortsamulmedium"},
235
12.0k
            {u"hy\uC595\uC740\uC0D8\uBB3C"_ustr, "hyshortsamul"},
236
12.0k
            {u"\uD55C\uCEF4\uBC14\uD0D5"_ustr, "haansoftbatang"},
237
12.0k
            {u"\uD55C\uCEF4\uB3CB\uC6C0"_ustr, "haansoftdotum"},
238
12.0k
            {u"\uD55C\uC591\uD574\uC11C"_ustr, "hyhaeseo"},
239
12.0k
            {u"md\uC194\uCCB4"_ustr, "mdsol"},
240
12.0k
            {u"md\uAC1C\uC131\uCCB4"_ustr, "mdgaesung"},
241
12.0k
            {u"md\uC544\uD2B8\uCCB4"_ustr, "mdart"},
242
12.0k
            {u"md\uC544\uB871\uCCB4"_ustr, "mdalong"},
243
12.0k
            {u"md\uC774\uC19D\uCCB4"_ustr, "mdeasop"},
244
12.0k
            {u"hg\uFF7A\uFF9E\uFF7C\uFF6F\uFF78e"_ustr, "hggothice"},
245
12.0k
            {u"hgp\uFF7A\uFF9E\uFF7C\uFF6F\uFF78e"_ustr, "hgpgothice"},
246
12.0k
            {u"hgs\uFF7A\uFF9E\uFF7C\uFF6F\uFF78e"_ustr, "hgsgothice"},
247
12.0k
            {u"hg\uFF7A\uFF9E\uFF7C\uFF6F\uFF78m"_ustr, "hggothicm"},
248
12.0k
            {u"hgp\uFF7A\uFF9E\uFF7C\uFF6F\uFF78m"_ustr, "hgpgothicm"},
249
12.0k
            {u"hgs\uFF7A\uFF9E\uFF7C\uFF6F\uFF78m"_ustr, "hgsgothicm"},
250
12.0k
            {u"hg\u884C\u66F8\u4F53"_ustr, "hggyoshotai"},
251
12.0k
            {u"hgp\u884C\u66F8\u4F53"_ustr, "hgpgyoshotai"},
252
12.0k
            {u"hgs\u884C\u66F8\u4F53"_ustr, "hgsgyoshotai"},
253
12.0k
            {u"hg\u6559\u79D1\u66F8\u4F53"_ustr, "hgkyokashotai"},
254
12.0k
            {u"hgp\u6559\u79D1\u66F8\u4F53"_ustr, "hgpkyokashotai"},
255
12.0k
            {u"hgs\u6559\u79D1\u66F8\u4F53"_ustr, "hgskyokashotai"},
256
12.0k
            {u"hg\u660E\u671Db"_ustr, "hgminchob"},
257
12.0k
            {u"hgp\u660E\u671Db"_ustr, "hgpminchob"},
258
12.0k
            {u"hgs\u660E\u671Db"_ustr, "hgsminchob"},
259
12.0k
            {u"hg\u660E\u671De"_ustr, "hgminchoe"},
260
12.0k
            {u"hgp\u660E\u671De"_ustr, "hgpminchoe"},
261
12.0k
            {u"hgs\u660E\u671De"_ustr, "hgsminchoe"},
262
12.0k
            {u"hg\u5275\u82F1\u89D2\uFF8E\uFF9F\uFF6F\uFF8C\uFF9F\u4F53"_ustr, "hgsoeikakupoptai"},
263
12.0k
            {u"hgp\u5275\u82F1\u89D2\uFF8E\uFF9F\uFF6F\uFF8C\uFF9F\u4F53"_ustr, "hgpsoeikakupopta"},
264
12.0k
            {u"hgs\u5275\u82F1\u89D2\uFF8E\uFF9F\uFF6F\uFF8C\uFF9F\u4F53"_ustr, "hgssoeikakupopta"},
265
12.0k
            {u"hg\u5275\u82F1\uFF8C\uFF9F\uFF9A\uFF7E\uFF9E\uFF9D\uFF7Deb"_ustr,
266
12.0k
             "hgsoeipresenceeb"},
267
12.0k
            {u"hgp\u5275\u82F1\uFF8C\uFF9F\uFF9A\uFF7E\uFF9E\uFF9D\uFF7Deb"_ustr,
268
12.0k
             "hgpsoeipresenceeb"},
269
12.0k
            {u"hgs\u5275\u82F1\uFF8C\uFF9F\uFF9A\uFF7E\uFF9E\uFF9D\uFF7Deb"_ustr,
270
12.0k
             "hgssoeipresenceeb"},
271
12.0k
            {u"hg\u5275\u82F1\u89D2\uFF7A\uFF9E\uFF7C\uFF6F\uFF78ub"_ustr, "hgsoeikakugothicub"},
272
12.0k
            {u"hgp\u5275\u82F1\u89D2\uFF7A\uFF9E\uFF7C\uFF6F\uFF78ub"_ustr, "hgpsoeikakugothicub"},
273
12.0k
            {u"hgs\u5275\u82F1\u89D2\uFF7A\uFF9E\uFF7C\uFF6F\uFF78ub"_ustr, "hgssoeikakugothicub"},
274
12.0k
            {u"hg\u6B63\u6977\u66F8\u4F53-pro"_ustr, "hgseikaishotaipro"},
275
12.0k
            {u"hg\u4E38\uFF7A\uFF9E\uFF7C\uFF6F\uFF78-pro"_ustr, "hgmarugothicmpro"},
276
12.0k
            {u"\u30D2\u30E9\u30AE\u30CE\u660E\u671Dpro"_ustr, "hiraginominchopro"},
277
12.0k
            {u"\u30D2\u30E9\u30AE\u30CE\u660E\u671Dpron"_ustr, "hiraginominchopron"},
278
12.0k
            {u"\u30D2\u30E9\u30AE\u30CE\u89D2\u30B4\u30B7\u30C3\u30AF"_ustr, "hiraginosans"},
279
12.0k
            {u"\u30D2\u30E9\u30AE\u30CE\u89D2\u30B4pro"_ustr, "hiraginokakugothicpro"},
280
12.0k
            {u"\u30D2\u30E9\u30AE\u30CE\u89D2\u30B4pron"_ustr, "hiraginokakugothicpron"},
281
12.0k
            {u"\u30D2\u30E9\u30AE\u30CE\u4E38\u30B4pro"_ustr, "hiraginomarugothicpro"},
282
12.0k
            {u"\u30D2\u30E9\u30AE\u30CE\u4E38\u30B4pron"_ustr, "hiraginomarugothicpron"},
283
12.0k
            {u"\u6E38\u30B4\u30B7\u30C3\u30AF"_ustr, "yugothic"},
284
12.0k
            {u"\u6E38\u30B4\u30B7\u30C3\u30AF\u4F53"_ustr, "yugothictai"},
285
12.0k
            {u"\u6E38\u660E\u671D"_ustr, "yumincho"},
286
12.0k
            {u"\u6E38\u660E\u671D\u4F53"_ustr, "yuminchotai"},
287
12.0k
            {u"\u6E90\u30CE\u89D2\u30B4\u30B7\u30C3\u30AF"_ustr, "sourcehansans"},
288
12.0k
            {u"\u6E90\u30CE\u89D2\u30B4\u30B7\u30C3\u30AFjp"_ustr, "sourcehansansjp"},
289
12.0k
            {u"\u6E90\u30CE\u89D2\u30B4\u30B7\u30C3\u30AFhw"_ustr, "sourcehansanshw"},
290
12.0k
            {u"\u6E90\u30CE\u660E\u671D"_ustr, "sourcehanserif"},
291
12.0k
            {u"\u6E90\u30CE\u660E\u671Djp"_ustr, "sourcehanserifjp"},
292
12.0k
            {u"ipamj\u660E\u671D"_ustr, "ipamjmincho"},
293
12.0k
            {u"ipaex\u30B4\u30B7\u30C3\u30AF"_ustr, "ipaexgothic"},
294
12.0k
            {u"ipaex\u660E\u671D"_ustr, "ipaexmimcho"}};
295
296
12.0k
        FontNameDictionary::const_iterator it = aDictionary.find( rNameStr );
297
12.0k
        if( it != aDictionary.end() )
298
1.40k
            rNameStr = it->second;
299
12.0k
    }
300
301
584k
    return rNameStr;
302
584k
}
303
304
std::u16string_view GetNextFontToken( std::u16string_view rTokenStr, sal_Int32& rIndex )
305
20.5M
{
306
    // check for valid start index
307
20.5M
    size_t nStringLen = rTokenStr.size();
308
20.5M
    if( o3tl::make_unsigned(rIndex) >= nStringLen )
309
4.60M
    {
310
4.60M
        rIndex = -1;
311
4.60M
        return {};
312
4.60M
    }
313
314
    // find the next token delimiter and return the token substring
315
15.9M
    const sal_Unicode* pStr = rTokenStr.data() + rIndex;
316
15.9M
    const sal_Unicode* pEnd = rTokenStr.data() + nStringLen;
317
1.07G
    for(; pStr < pEnd; ++pStr )
318
1.05G
        if( (*pStr == ';') || (*pStr == ',') )
319
70.9k
            break;
320
321
15.9M
    sal_Int32 nTokenStart = rIndex;
322
15.9M
    sal_Int32 nTokenLen;
323
15.9M
    if( pStr < pEnd )
324
70.9k
    {
325
70.9k
        rIndex = sal::static_int_cast<sal_Int32>(pStr - rTokenStr.data());
326
70.9k
        nTokenLen = rIndex - nTokenStart;
327
70.9k
        ++rIndex; // skip over token separator
328
70.9k
    }
329
15.8M
    else
330
15.8M
    {
331
        // no token delimiter found => handle last token
332
15.8M
        rIndex = -1;
333
334
        // optimize if the token string consists of just one token
335
15.8M
        if( !nTokenStart )
336
15.8M
        {
337
15.8M
            return rTokenStr;
338
15.8M
        }
339
0
        else
340
0
        {
341
0
            nTokenLen = nStringLen - nTokenStart;
342
0
        }
343
15.8M
    }
344
345
70.9k
    return rTokenStr.substr( nTokenStart, nTokenLen );
346
15.9M
}
347
348
static bool ImplIsFontToken( std::u16string_view rName, std::u16string_view rToken )
349
0
{
350
0
    sal_Int32  nIndex = 0;
351
0
    do
352
0
    {
353
0
        std::u16string_view aTempName = GetNextFontToken( rName, nIndex );
354
0
        if ( rToken == aTempName )
355
0
            return true;
356
0
    }
357
0
    while ( nIndex != -1 );
358
359
0
    return false;
360
0
}
361
362
static void ImplAppendFontToken( OUString& rName, std::u16string_view rNewToken )
363
0
{
364
0
    if ( !rName.isEmpty() )
365
0
    {
366
0
        rName += ";";
367
0
    }
368
0
    rName += rNewToken;
369
0
}
370
371
void AddTokenFontName( OUString& rName, std::u16string_view rNewToken )
372
0
{
373
0
    if ( !ImplIsFontToken( rName, rNewToken ) )
374
0
        ImplAppendFontToken( rName, rNewToken );
375
0
}
376
377
OUString GetSubsFontName( std::u16string_view rName, SubsFontFlags nFlags )
378
0
{
379
0
    OUString aName;
380
381
0
    sal_Int32 nIndex = 0;
382
0
    OUString aOrgName = GetEnglishSearchFontName(
383
0
                                GetNextFontToken( rName, nIndex ) );
384
385
    // #93662# do not try to replace StarSymbol with MS only font
386
0
    if( nFlags == (SubsFontFlags::MS|SubsFontFlags::ONLYONE)
387
0
    &&  ( aOrgName == "starsymbol"
388
0
      ||  aOrgName == "opensymbol" ) )
389
0
        return aName;
390
391
0
    if (nFlags & SubsFontFlags::MS)
392
0
    {
393
0
        const utl::FontNameAttr* pAttr = utl::FontSubstConfiguration::get().getSubstInfo( aOrgName );
394
0
        if (pAttr)
395
0
            for( const auto& rSubstitution : pAttr->MSSubstitutions )
396
0
                if( ! ImplIsFontToken( rName, rSubstitution ) )
397
0
                {
398
0
                    ImplAppendFontToken( aName, rSubstitution );
399
0
                    if( nFlags & SubsFontFlags::ONLYONE )
400
0
                    {
401
0
                        break;
402
0
                    }
403
0
                }
404
0
    }
405
406
0
    return aName;
407
0
}
408
409
bool IsOpenSymbol(std::u16string_view rFontName)
410
1.38M
{
411
1.38M
    sal_Int32 nIndex = 0;
412
1.38M
    std::u16string_view sFamilyNm(GetNextFontToken(rFontName, nIndex));
413
1.38M
    return (o3tl::equalsIgnoreAsciiCase(sFamilyNm, "starsymbol") ||
414
1.38M
        o3tl::equalsIgnoreAsciiCase(sFamilyNm, "opensymbol"));
415
1.38M
}
416
417
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */