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 <sal/config.h>
21
22 #include <memory>
23 #include <string.h>
24 #include <string_view>
25
26 #include <tools/debug.hxx>
27 #include <i18nlangtag/languagetag.hxx>
28 #include <i18nlangtag/mslangid.hxx>
29 #include <utility>
30 #include <vcl/embeddedfontsmanager.hxx>
31 #include <vcl/outdev.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/settings.hxx>
34 #include <sal/macros.h>
35 #include <svtools/strings.hrc>
36 #include <svtools/svtresid.hxx>
37 #include <svtools/ctrltool.hxx>
38 #include <o3tl/typed_flags_set.hxx>
39 #include <o3tl/string_view.hxx>
40 #include <comphelper/lok.hxx>
41
42 // Standard fontsizes for scalable Fonts
43 const int FontList::aStdSizeAry[] =
44 {
45 60,
46 70,
47 80,
48 90,
49 100,
50 105,
51 110,
52 120,
53 130,
54 140,
55 150,
56 160,
57 180,
58 200,
59 210,
60 220,
61 240,
62 260,
63 280,
64 320,
65 360,
66 400,
67 420,
68 440,
69 480,
70 540,
71 600,
72 660,
73 720,
74 800,
75 880,
76 960,
77 0
78 };
79
80 namespace {
81
82 class ImplFontListFontMetric : public FontMetric
83 {
84 friend FontList;
85
86 private:
87 ImplFontListFontMetric* mpNext;
88
89 public:
ImplFontListFontMetric(const FontMetric & rInfo)90 ImplFontListFontMetric( const FontMetric& rInfo ) :
91 FontMetric( rInfo ), mpNext(nullptr)
92 {
93 }
94
95 };
96
97 enum class FontListFontNameType
98 {
99 NONE = 0x00,
100 PRINTER = 0x01,
101 SCREEN = 0x02,
102 };
103
104 }
105 namespace o3tl
106 {
107 template<> struct typed_flags<FontListFontNameType> : is_typed_flags<FontListFontNameType, 0x3> {};
108 }
109
110 class ImplFontListNameInfo
111 {
112 friend class FontList;
113
114 private:
115 OUString maSearchName;
116 ImplFontListFontMetric* mpFirst;
117 FontListFontNameType mnType;
118
ImplFontListNameInfo(OUString aSearchName)119 explicit ImplFontListNameInfo(OUString aSearchName)
120 : maSearchName(std::move(aSearchName))
121 , mpFirst(nullptr)
122 , mnType(FontListFontNameType::NONE)
123 {
124 }
125 };
126
127 //sort normal to the start
sortWeightValue(FontWeight eWeight)128 static int sortWeightValue(FontWeight eWeight)
129 {
130 if (eWeight < WEIGHT_NORMAL)
131 return eWeight + 1;
132 if (eWeight > WEIGHT_NORMAL)
133 return eWeight - 1;
134 return 0; // eWeight == WEIGHT_NORMAL
135 }
136
ImplCompareFontMetric(const ImplFontListFontMetric * pInfo1,const ImplFontListFontMetric * pInfo2)137 static sal_Int32 ImplCompareFontMetric(const ImplFontListFontMetric* pInfo1,
138 const ImplFontListFontMetric* pInfo2)
139 {
140 //Sort non italic before italics
141 if ( pInfo1->GetItalic() < pInfo2->GetItalic() )
142 return -1;
143 else if ( pInfo1->GetItalic() > pInfo2->GetItalic() )
144 return 1;
145
146 //Sort normal weight to the start, followed by lightest to heaviest weights
147 int nWeight1 = sortWeightValue(pInfo1->GetWeight());
148 int nWeight2 = sortWeightValue(pInfo2->GetWeight());
149
150 if ( nWeight1 < nWeight2 )
151 return -1;
152 else if ( nWeight1 > nWeight2 )
153 return 1;
154
155 return pInfo1->GetStyleName().compareTo( pInfo2->GetStyleName() );
156 }
157
ImplMakeSearchString(const OUString & rStr)158 static OUString ImplMakeSearchString(const OUString& rStr)
159 {
160 return rStr.toAsciiLowerCase();
161 }
162
ImplMakeSearchStringFromName(std::u16string_view rStr)163 static OUString ImplMakeSearchStringFromName(std::u16string_view rStr)
164 {
165 // check for features before alternate font separator
166 if (size_t nColon = rStr.find(':'); nColon != std::u16string_view::npos)
167 if (size_t nSemiColon = rStr.find(';'); nSemiColon == std::u16string_view::npos || nColon < nSemiColon)
168 return ImplMakeSearchString(OUString(o3tl::getToken(rStr, 0, ':' )));
169 return ImplMakeSearchString(OUString(o3tl::getToken(rStr, 0, ';' )));
170 }
171
ImplFind(std::u16string_view rSearchName,sal_uInt32 * pIndex) const172 ImplFontListNameInfo* FontList::ImplFind(std::u16string_view rSearchName, sal_uInt32* pIndex) const
173 {
174 // Append if there is no entry in the list or if the entry is larger
175 // then the last one. We only compare to the last entry as the list of VCL
176 // is returned sorted, which increases the probability that appending
177 // is more likely
178 if (m_Entries.empty())
179 {
180 if ( pIndex )
181 *pIndex = SAL_MAX_UINT32;
182 return nullptr;
183 }
184 else
185 {
186 const ImplFontListNameInfo* pCmpData = m_Entries.back().get();
187 sal_Int32 nComp = rSearchName.compare( pCmpData->maSearchName );
188 if (nComp > 0)
189 {
190 if ( pIndex )
191 *pIndex = SAL_MAX_UINT32;
192 return nullptr;
193 }
194 else if (nComp == 0)
195 return const_cast<ImplFontListNameInfo*>(pCmpData);
196 }
197
198 // search fonts in the list
199 const ImplFontListNameInfo* pCompareData;
200 const ImplFontListNameInfo* pFoundData = nullptr;
201 size_t nLow = 0;
202 size_t nHigh = m_Entries.size() - 1;
203 size_t nMid;
204
205 do
206 {
207 nMid = (nLow + nHigh) / 2;
208 pCompareData = m_Entries[nMid].get();
209 sal_Int32 nComp = rSearchName.compare(pCompareData->maSearchName);
210 if (nComp < 0)
211 {
212 if ( !nMid )
213 break;
214 nHigh = nMid-1;
215 }
216 else
217 {
218 if (nComp > 0)
219 nLow = nMid + 1;
220 else
221 {
222 pFoundData = pCompareData;
223 break;
224 }
225 }
226 }
227 while ( nLow <= nHigh );
228
229 if ( pIndex )
230 {
231 sal_Int32 nComp = rSearchName.compare(pCompareData->maSearchName);
232 if (nComp > 0)
233 *pIndex = (nMid+1);
234 else
235 *pIndex = nMid;
236 }
237
238 return const_cast<ImplFontListNameInfo*>(pFoundData);
239 }
240
ImplFindByName(std::u16string_view rStr) const241 ImplFontListNameInfo* FontList::ImplFindByName(std::u16string_view rStr) const
242 {
243 OUString aSearchName = ImplMakeSearchStringFromName(rStr);
244 return ImplFind( aSearchName, nullptr );
245 }
246
ImplInsertFonts(OutputDevice * pDevice,bool bInsertData)247 void FontList::ImplInsertFonts(OutputDevice* pDevice, bool bInsertData)
248 {
249 rtl_TextEncoding eSystemEncoding = osl_getThreadTextEncoding();
250
251 FontListFontNameType nType;
252 if ( pDevice->GetOutDevType() != OUTDEV_PRINTER )
253 nType = FontListFontNameType::SCREEN;
254 else
255 nType = FontListFontNameType::PRINTER;
256
257 // inquire all fonts from the device
258 int n = pDevice->GetFontFaceCollectionCount();
259 if (n == 0 && comphelper::LibreOfficeKit::isActive())
260 {
261 pDevice->RefreshFontData(true);
262 n = pDevice->GetFontFaceCollectionCount();
263 }
264
265 for (int i = 0; i < n; ++i)
266 {
267 FontMetric aFontMetric = pDevice->GetFontMetricFromCollection( i );
268 OUString aSearchName(aFontMetric.GetFamilyName());
269
270 // If this font is embedded in a document, is restricted, and is not installed locally
271 // (which is returned from EmbeddedFontsManager::isEmbeddedAndRestricted), we must not
272 // display this family name in the UI.
273 if (EmbeddedFontsManager::isEmbeddedAndRestricted(aSearchName))
274 continue;
275
276 ImplFontListNameInfo* pData;
277 sal_uInt32 nIndex;
278 aSearchName = ImplMakeSearchString(aSearchName);
279 pData = ImplFind( aSearchName, &nIndex );
280
281 if ( !pData )
282 {
283 if ( bInsertData )
284 {
285 ImplFontListFontMetric* pNewInfo = new ImplFontListFontMetric( aFontMetric );
286 pData = new ImplFontListNameInfo( aSearchName );
287 pData->mpFirst = pNewInfo;
288 pNewInfo->mpNext = nullptr;
289
290 if (nIndex < static_cast<sal_uInt32>(m_Entries.size()))
291 m_Entries.insert(m_Entries.begin()+nIndex,
292 std::unique_ptr<ImplFontListNameInfo>(pData));
293 else
294 m_Entries.push_back(std::unique_ptr<ImplFontListNameInfo>(pData));
295 }
296 }
297 else
298 {
299 if ( bInsertData )
300 {
301 bool bInsert = true;
302 ImplFontListFontMetric* pPrev = nullptr;
303 ImplFontListFontMetric* pTemp = pData->mpFirst;
304 ImplFontListFontMetric* pNewInfo = new ImplFontListFontMetric( aFontMetric );
305 while ( pTemp )
306 {
307 sal_Int32 eComp = ImplCompareFontMetric( pNewInfo, pTemp );
308 if ( eComp <= 0 )
309 {
310 if ( eComp == 0 )
311 {
312 // Overwrite charset, because charset should match
313 // with the system charset
314 if ( (pTemp->GetCharSet() != eSystemEncoding) &&
315 (pNewInfo->GetCharSet() == eSystemEncoding) )
316 {
317 ImplFontListFontMetric* pTemp2 = pTemp->mpNext;
318 *static_cast<FontMetric*>(pTemp) = *static_cast<FontMetric*>(pNewInfo);
319 pTemp->mpNext = pTemp2;
320 }
321 delete pNewInfo;
322 bInsert = false;
323 }
324
325 break;
326 }
327
328 pPrev = pTemp;
329 pTemp = pTemp->mpNext;
330 }
331
332 if ( bInsert )
333 {
334 pNewInfo->mpNext = pTemp;
335 if ( pPrev )
336 pPrev->mpNext = pNewInfo;
337 else
338 pData->mpFirst = pNewInfo;
339 }
340 }
341 }
342
343 if ( pData )
344 pData->mnType |= nType;
345 }
346 }
347
FontList(OutputDevice * pDevice,OutputDevice * pDevice2)348 FontList::FontList(OutputDevice* pDevice, OutputDevice* pDevice2)
349 {
350 // initialise variables
351 mpDev = pDevice;
352 mpDev2 = pDevice2;
353
354 // store style names
355 maLight = SvtResId(STR_SVT_STYLE_LIGHT);
356 maLightItalic = SvtResId(STR_SVT_STYLE_LIGHT_ITALIC);
357 maNormal = SvtResId(STR_SVT_STYLE_NORMAL);
358 maNormalItalic = SvtResId(STR_SVT_STYLE_NORMAL_ITALIC);
359 maBold = SvtResId(STR_SVT_STYLE_BOLD);
360 maBoldItalic = SvtResId(STR_SVT_STYLE_BOLD_ITALIC);
361 maBlack = SvtResId(STR_SVT_STYLE_BLACK);
362 maBlackItalic = SvtResId(STR_SVT_STYLE_BLACK_ITALIC);
363
364 ImplInsertFonts(pDevice, true);
365
366 // if required compare to the screen fonts
367 // in order to map the duplicates to Equal
368 bool bCompareWindow = false;
369 if ( !pDevice2 && (pDevice->GetOutDevType() == OUTDEV_PRINTER) )
370 {
371 bCompareWindow = true;
372 pDevice2 = Application::GetDefaultDevice();
373 }
374
375 if ( pDevice2 &&
376 (pDevice2->GetOutDevType() != pDevice->GetOutDevType()) )
377 ImplInsertFonts(pDevice2, !bCompareWindow);
378 }
379
~FontList()380 FontList::~FontList()
381 {
382 // delete FontMetrics
383 ImplFontListFontMetric *pTemp, *pInfo;
384 for (auto const& it : m_Entries)
385 {
386 pInfo = it->mpFirst;
387 while ( pInfo )
388 {
389 pTemp = pInfo->mpNext;
390 delete pInfo;
391 pInfo = pTemp;
392 }
393 }
394 }
395
Clone() const396 std::unique_ptr<FontList> FontList::Clone() const
397 {
398 return std::unique_ptr<FontList>(new FontList(mpDev, mpDev2));
399 }
400
GetStyleName(FontWeight eWeight,FontItalic eItalic) const401 const OUString& FontList::GetStyleName(FontWeight eWeight, FontItalic eItalic) const
402 {
403 if ( eWeight > WEIGHT_BOLD )
404 {
405 if ( eItalic > ITALIC_NONE )
406 return maBlackItalic;
407 else
408 return maBlack;
409 }
410 else if ( eWeight > WEIGHT_MEDIUM )
411 {
412 if ( eItalic > ITALIC_NONE )
413 return maBoldItalic;
414 else
415 return maBold;
416 }
417 else if ( eWeight > WEIGHT_LIGHT )
418 {
419 if ( eItalic > ITALIC_NONE )
420 return maNormalItalic;
421 else
422 return maNormal;
423 }
424 else if ( eWeight != WEIGHT_DONTKNOW )
425 {
426 if ( eItalic > ITALIC_NONE )
427 return maLightItalic;
428 else
429 return maLight;
430 }
431 else
432 {
433 if ( eItalic > ITALIC_NONE )
434 return maNormalItalic;
435 else
436 return maNormal;
437 }
438 }
439
GetStyleName(const FontMetric & rInfo) const440 OUString FontList::GetStyleName(const FontMetric& rInfo) const
441 {
442 OUString aStyleName = rInfo.GetStyleName();
443 FontWeight eWeight = rInfo.GetWeight();
444 FontItalic eItalic = rInfo.GetItalic();
445
446 // return synthetic Name if no StyleName was set
447 if (aStyleName.isEmpty())
448 aStyleName = GetStyleName(eWeight, eItalic);
449 else
450 {
451 // Translate StyleName to localized name
452 OUString aCompareStyleName = aStyleName.toAsciiLowerCase().replaceAll(" ", "");
453 if (aCompareStyleName == "bold")
454 aStyleName = maBold;
455 else if (aCompareStyleName == "bolditalic")
456 aStyleName = maBoldItalic;
457 else if (aCompareStyleName == "italic")
458 aStyleName = maNormalItalic;
459 else if (aCompareStyleName == "standard")
460 aStyleName = maNormal;
461 else if (aCompareStyleName == "regular")
462 aStyleName = maNormal;
463 else if (aCompareStyleName == "light")
464 aStyleName = maLight;
465 else if (aCompareStyleName == "lightitalic")
466 aStyleName = maLightItalic;
467 else if (aCompareStyleName == "black")
468 aStyleName = maBlack;
469 else if (aCompareStyleName == "blackitalic")
470 aStyleName = maBlackItalic;
471 /* tdf#107700 support some less common style names with localization */
472 else if (aCompareStyleName == "book")
473 aStyleName = SvtResId(STR_SVT_STYLE_BOOK);
474 else if (aCompareStyleName == "boldoblique")
475 aStyleName = SvtResId(STR_SVT_STYLE_BOLD_OBLIQUE);
476 else if (aCompareStyleName == "condensed")
477 aStyleName = SvtResId(STR_SVT_STYLE_CONDENSED);
478 else if (aCompareStyleName == "condensedbold")
479 aStyleName = SvtResId(STR_SVT_STYLE_CONDENSED_BOLD);
480 else if (aCompareStyleName == "condensedbolditalic")
481 aStyleName = SvtResId(STR_SVT_STYLE_CONDENSED_BOLD_ITALIC);
482 else if (aCompareStyleName == "condensedboldoblique")
483 aStyleName = SvtResId(STR_SVT_STYLE_CONDENSED_BOLD_OBLIQUE);
484 else if (aCompareStyleName == "condenseditalic")
485 aStyleName = SvtResId(STR_SVT_STYLE_CONDENSED_ITALIC);
486 else if (aCompareStyleName == "condensedoblique")
487 aStyleName = SvtResId(STR_SVT_STYLE_CONDENSED_OBLIQUE);
488 else if (aCompareStyleName == "extralight")
489 aStyleName = SvtResId(STR_SVT_STYLE_EXTRALIGHT);
490 else if (aCompareStyleName == "extralightitalic")
491 aStyleName = SvtResId(STR_SVT_STYLE_EXTRALIGHT_ITALIC);
492 else if (aCompareStyleName == "oblique")
493 aStyleName = SvtResId(STR_SVT_STYLE_OBLIQUE);
494 else if (aCompareStyleName == "semibold")
495 aStyleName = SvtResId(STR_SVT_STYLE_SEMIBOLD);
496 else if (aCompareStyleName == "semibolditalic")
497 aStyleName = SvtResId(STR_SVT_STYLE_SEMIBOLD_ITALIC);
498 // tdf#147739 medium is not a synonym of normal
499 else if (aCompareStyleName == "medium")
500 aStyleName = SvtResId(STR_SVT_STYLE_MEDIUM);
501 else if (aCompareStyleName == "mediumitalic")
502 aStyleName = SvtResId(STR_SVT_STYLE_MEDIUM_ITALIC);
503
504 // fix up StyleName, because the PS Printer driver from
505 // W2000 returns wrong StyleNames (e.g. Bold instead of Bold Italic
506 // for Helvetica)
507 if ( eItalic > ITALIC_NONE )
508 {
509 if ( (aStyleName == maNormal) ||
510 (aStyleName == maBold) ||
511 (aStyleName == maLight) ||
512 (aStyleName == maBlack) )
513 aStyleName = GetStyleName( eWeight, eItalic );
514 }
515 }
516
517 return aStyleName;
518 }
519
GetFontMapText(const FontMetric & rInfo) const520 const OUString & FontList::GetFontMapText( const FontMetric& rInfo ) const
521 {
522 if ( rInfo.GetFamilyName().isEmpty() )
523 {
524 return EMPTY_OUSTRING;
525 }
526
527 // Search Fontname
528 ImplFontListNameInfo* pData = ImplFindByName( rInfo.GetFamilyName() );
529 if ( !pData )
530 {
531 if (maMapNotAvailable.isEmpty())
532 maMapNotAvailable = SvtResId(STR_SVT_FONTMAP_NOTAVAILABLE);
533 return maMapNotAvailable;
534 }
535
536 // search for synthetic style
537 FontListFontNameType nType = pData->mnType;
538 const OUString& rStyleName = rInfo.GetStyleName();
539 if (!rStyleName.isEmpty())
540 {
541 bool bNotSynthetic = false;
542 FontWeight eWeight = rInfo.GetWeight();
543 FontItalic eItalic = rInfo.GetItalic();
544 ImplFontListFontMetric* pFontMetric = pData->mpFirst;
545 while ( pFontMetric )
546 {
547 if ( (eWeight == pFontMetric->GetWeightMaybeAskConfig()) &&
548 (eItalic == pFontMetric->GetItalicMaybeAskConfig()) )
549 {
550 bNotSynthetic = true;
551 break;
552 }
553
554 pFontMetric = pFontMetric->mpNext;
555 }
556
557 if ( !bNotSynthetic )
558 {
559 if (maMapStyleNotAvailable.isEmpty())
560 const_cast<FontList*>(this)->maMapStyleNotAvailable = SvtResId(STR_SVT_FONTMAP_STYLENOTAVAILABLE);
561 return maMapStyleNotAvailable;
562 }
563 }
564
565 // Only Printer-Font?
566 if ( nType == FontListFontNameType::PRINTER )
567 {
568 if (maMapPrinterOnly.isEmpty())
569 const_cast<FontList*>(this)->maMapPrinterOnly = SvtResId(STR_SVT_FONTMAP_PRINTERONLY);
570 return maMapPrinterOnly;
571 }
572 else
573 {
574 if (maMapBoth.isEmpty())
575 const_cast<FontList*>(this)->maMapBoth = SvtResId(STR_SVT_FONTMAP_BOTH);
576 return maMapBoth;
577 }
578 }
579
580 namespace
581 {
makeMissing(ImplFontListFontMetric const * pFontNameInfo,std::u16string_view rName,FontWeight eWeight,FontItalic eItalic)582 FontMetric makeMissing(ImplFontListFontMetric const * pFontNameInfo, std::u16string_view rName,
583 FontWeight eWeight, FontItalic eItalic)
584 {
585 FontMetric aInfo;
586 // if the fontname matches, we copy as much as possible
587 if (pFontNameInfo)
588 {
589 aInfo = *pFontNameInfo;
590 aInfo.SetStyleName(OUString());
591 }
592
593 aInfo.SetWeight(eWeight);
594 aInfo.SetItalic(eItalic);
595
596 //If this is a known but uninstalled symbol font which we can remap to
597 //OpenSymbol then toggle its charset to be a symbol font
598 if (ConvertChar::GetRecodeData(rName, u"OpenSymbol"))
599 aInfo.SetCharSet(RTL_TEXTENCODING_SYMBOL);
600
601 return aInfo;
602 }
603 }
604
Get(const OUString & rName,const OUString & rStyleName) const605 FontMetric FontList::Get(const OUString& rName, const OUString& rStyleName) const
606 {
607 ImplFontListNameInfo* pData = ImplFindByName( rName );
608 ImplFontListFontMetric* pFontMetric = nullptr;
609 ImplFontListFontMetric* pFontNameInfo = nullptr;
610 if ( pData )
611 {
612 ImplFontListFontMetric* pSearchInfo = pData->mpFirst;
613 pFontNameInfo = pSearchInfo;
614 pSearchInfo = pData->mpFirst;
615 while ( pSearchInfo )
616 {
617 if (rStyleName.equalsIgnoreAsciiCase(GetStyleName(*pSearchInfo)))
618 {
619 pFontMetric = pSearchInfo;
620 break;
621 }
622
623 pSearchInfo = pSearchInfo->mpNext;
624 }
625 }
626
627 // reproduce attributes if data could not be found
628 FontMetric aInfo;
629 if ( !pFontMetric )
630 {
631 FontWeight eWeight = WEIGHT_DONTKNOW;
632 FontItalic eItalic = ITALIC_NONE;
633
634 if ( rStyleName == maNormal )
635 {
636 eItalic = ITALIC_NONE;
637 eWeight = WEIGHT_NORMAL;
638 }
639 else if ( rStyleName == maNormalItalic )
640 {
641 eItalic = ITALIC_NORMAL;
642 eWeight = WEIGHT_NORMAL;
643 }
644 else if ( rStyleName == maBold )
645 {
646 eItalic = ITALIC_NONE;
647 eWeight = WEIGHT_BOLD;
648 }
649 else if ( rStyleName == maBoldItalic )
650 {
651 eItalic = ITALIC_NORMAL;
652 eWeight = WEIGHT_BOLD;
653 }
654 else if ( rStyleName == maLight )
655 {
656 eItalic = ITALIC_NONE;
657 eWeight = WEIGHT_LIGHT;
658 }
659 else if ( rStyleName == maLightItalic )
660 {
661 eItalic = ITALIC_NORMAL;
662 eWeight = WEIGHT_LIGHT;
663 }
664 else if ( rStyleName == maBlack )
665 {
666 eItalic = ITALIC_NONE;
667 eWeight = WEIGHT_BLACK;
668 }
669 else if ( rStyleName == maBlackItalic )
670 {
671 eItalic = ITALIC_NORMAL;
672 eWeight = WEIGHT_BLACK;
673 }
674 aInfo = makeMissing(pFontNameInfo, rName, eWeight, eItalic);
675 }
676 else
677 aInfo = *pFontMetric;
678
679 // set Fontname to keep FontAlias
680 aInfo.SetFamilyName( rName );
681 aInfo.SetStyleName( rStyleName );
682
683 return aInfo;
684 }
685
Get(const OUString & rName,FontWeight eWeight,FontItalic eItalic) const686 FontMetric FontList::Get(const OUString& rName,
687 FontWeight eWeight, FontItalic eItalic) const
688 {
689 ImplFontListNameInfo* pData = ImplFindByName( rName );
690 ImplFontListFontMetric* pFontMetric = nullptr;
691 ImplFontListFontMetric* pFontNameInfo = nullptr;
692 if ( pData )
693 {
694 ImplFontListFontMetric* pSearchInfo = pData->mpFirst;
695 pFontNameInfo = pSearchInfo;
696 while ( pSearchInfo )
697 {
698 if ( (eWeight == pSearchInfo->GetWeightMaybeAskConfig()) &&
699 (eItalic == pSearchInfo->GetItalicMaybeAskConfig()) )
700 {
701 pFontMetric = pSearchInfo;
702 break;
703 }
704
705 pSearchInfo = pSearchInfo->mpNext;
706 }
707 }
708
709 // reproduce attributes if data could not be found
710 FontMetric aInfo;
711 if ( !pFontMetric )
712 aInfo = makeMissing(pFontNameInfo, rName, eWeight, eItalic);
713 else
714 aInfo = *pFontMetric;
715
716 // set Fontname to keep FontAlias
717 aInfo.SetFamilyName( rName );
718
719 return aInfo;
720 }
721
IsAvailable(std::u16string_view rName) const722 bool FontList::IsAvailable(std::u16string_view rName) const
723 {
724 return (ImplFindByName( rName ) != nullptr);
725 }
726
GetFontName(size_t const nFont) const727 const FontMetric& FontList::GetFontName(size_t const nFont) const
728 {
729 DBG_ASSERT( nFont < GetFontNameCount(), "FontList::GetFontName(): nFont >= Count" );
730
731 return *(m_Entries[nFont]->mpFirst);
732 }
733
GetFirstFontMetric(std::u16string_view rName) const734 sal_Handle FontList::GetFirstFontMetric(std::u16string_view rName) const
735 {
736 ImplFontListNameInfo* pData = ImplFindByName( rName );
737 if ( !pData )
738 return nullptr;
739 else
740 return static_cast<sal_Handle>(pData->mpFirst);
741 }
742
GetNextFontMetric(sal_Handle hFontMetric)743 sal_Handle FontList::GetNextFontMetric( sal_Handle hFontMetric )
744 {
745 ImplFontListFontMetric* pInfo = static_cast<ImplFontListFontMetric*>(hFontMetric);
746 return static_cast<sal_Handle>(pInfo->mpNext);
747 }
748
GetFontMetric(sal_Handle hFontMetric)749 const FontMetric& FontList::GetFontMetric( sal_Handle hFontMetric )
750 {
751 ImplFontListFontMetric* pInfo = static_cast<ImplFontListFontMetric*>(hFontMetric);
752 return *pInfo;
753 }
754
755 struct ImplFSNameItem
756 {
757 sal_Int32 mnSize;
758 const char* mszUtf8Name;
759 };
760
761 const ImplFSNameItem aImplSimplifiedChinese[] =
762 {
763 { 50, "\xe5\x85\xab\xe5\x8f\xb7" },
764 { 55, "\xe4\xb8\x83\xe5\x8f\xb7" },
765 { 65, "\xe5\xb0\x8f\xe5\x85\xad" },
766 { 75, "\xe5\x85\xad\xe5\x8f\xb7" },
767 { 90, "\xe5\xb0\x8f\xe4\xba\x94" },
768 { 105, "\xe4\xba\x94\xe5\x8f\xb7" },
769 { 120, "\xe5\xb0\x8f\xe5\x9b\x9b" },
770 { 140, "\xe5\x9b\x9b\xe5\x8f\xb7" },
771 { 150, "\xe5\xb0\x8f\xe4\xb8\x89" },
772 { 160, "\xe4\xb8\x89\xe5\x8f\xb7" },
773 { 180, "\xe5\xb0\x8f\xe4\xba\x8c" },
774 { 220, "\xe4\xba\x8c\xe5\x8f\xb7" },
775 { 240, "\xe5\xb0\x8f\xe4\xb8\x80" },
776 { 260, "\xe4\xb8\x80\xe5\x8f\xb7" },
777 { 360, "\xe5\xb0\x8f\xe5\x88\x9d" },
778 { 420, "\xe5\x88\x9d\xe5\x8f\xb7" }
779 };
780
FontSizeNames(LanguageType eLanguage)781 FontSizeNames::FontSizeNames( LanguageType eLanguage )
782 {
783 if ( eLanguage == LANGUAGE_DONTKNOW )
784 eLanguage = Application::GetSettings().GetUILanguageTag().getLanguageType();
785 if ( eLanguage == LANGUAGE_SYSTEM )
786 eLanguage = MsLangId::getConfiguredSystemUILanguage();
787
788 if (MsLangId::isSimplifiedChinese(eLanguage))
789 {
790 // equivalent for traditional chinese disabled by popular request, #i89077#
791 mpArray = aImplSimplifiedChinese;
792 mnElem = SAL_N_ELEMENTS(aImplSimplifiedChinese);
793 }
794 else
795 {
796 mpArray = nullptr;
797 mnElem = 0;
798 }
799 }
800
Name2Size(std::u16string_view rName) const801 sal_Int32 FontSizeNames::Name2Size( std::u16string_view rName ) const
802 {
803 if ( mnElem )
804 {
805 OString aName(OUStringToOString(rName,
806 RTL_TEXTENCODING_UTF8));
807
808 // linear search is sufficient for this rare case
809 for( tools::Long i = mnElem; --i >= 0; )
810 if ( aName == mpArray[i].mszUtf8Name )
811 return mpArray[i].mnSize;
812 }
813
814 return 0;
815 }
816
Size2Name(sal_Int32 nValue) const817 OUString FontSizeNames::Size2Name( sal_Int32 nValue ) const
818 {
819 OUString aStr;
820
821 // binary search
822 for( tools::Long lower = 0, upper = mnElem - 1; lower <= upper; )
823 {
824 tools::Long mid = (upper + lower) >> 1;
825 if ( nValue == mpArray[mid].mnSize )
826 {
827 aStr = OUString( mpArray[mid].mszUtf8Name, strlen(mpArray[mid].mszUtf8Name), RTL_TEXTENCODING_UTF8 );
828 break;
829 }
830 else if ( nValue < mpArray[mid].mnSize )
831 upper = mid - 1;
832 else /* ( nValue > mpArray[mid].mnSize ) */
833 lower = mid + 1;
834 }
835
836 return aStr;
837 }
838
GetIndexName(sal_Int32 nIndex) const839 OUString FontSizeNames::GetIndexName( sal_Int32 nIndex ) const
840 {
841 OUString aStr;
842
843 if ( nIndex < mnElem )
844 aStr = OUString( mpArray[nIndex].mszUtf8Name, strlen(mpArray[nIndex].mszUtf8Name), RTL_TEXTENCODING_UTF8 );
845
846 return aStr;
847 }
848
GetIndexSize(sal_Int32 nIndex) const849 sal_Int32 FontSizeNames::GetIndexSize( sal_Int32 nIndex ) const
850 {
851 if ( nIndex >= mnElem )
852 return 0;
853 return mpArray[nIndex].mnSize;
854 }
855
856 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
857