xref: /core/svtools/source/control/ctrltool.cxx (revision 0d0399a567d4870ba431d172c54a818fdb22bc07)
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