diff options
Diffstat (limited to 'svtools/source/control/ctrltool.cxx')
-rw-r--r-- | svtools/source/control/ctrltool.cxx | 890 |
1 files changed, 890 insertions, 0 deletions
diff --git a/svtools/source/control/ctrltool.cxx b/svtools/source/control/ctrltool.cxx new file mode 100644 index 000000000..cdd1aed8a --- /dev/null +++ b/svtools/source/control/ctrltool.cxx @@ -0,0 +1,890 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <memory> +#include <string.h> + +#include <tools/debug.hxx> +#include <tools/fract.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <i18nlangtag/mslangid.hxx> +#include <vcl/outdev.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <sal/macros.h> +#include <svtools/strings.hrc> +#include <svtools/svtresid.hxx> +#include <svtools/ctrltool.hxx> +#include <o3tl/typed_flags_set.hxx> +#include <comphelper/lok.hxx> + +// Standard fontsizes for scalable Fonts +const sal_IntPtr FontList::aStdSizeAry[] = +{ + 60, + 70, + 80, + 90, + 100, + 105, + 110, + 120, + 130, + 140, + 150, + 160, + 180, + 200, + 220, + 240, + 260, + 280, + 320, + 360, + 400, + 440, + 480, + 540, + 600, + 660, + 720, + 800, + 880, + 960, + 0 +}; + +namespace { + +class ImplFontListFontMetric : public FontMetric +{ + friend FontList; + +private: + VclPtr<OutputDevice> mpDevice; + ImplFontListFontMetric* mpNext; + +public: + ImplFontListFontMetric( const FontMetric& rInfo, + OutputDevice* pDev ) : + FontMetric( rInfo ), mpDevice(pDev), mpNext(nullptr) + { + } + + OutputDevice* GetDevice() const { return mpDevice; } +}; + +enum class FontListFontNameType +{ + NONE = 0x00, + PRINTER = 0x01, + SCREEN = 0x02, +}; + +} + +namespace o3tl +{ + template<> struct typed_flags<FontListFontNameType> : is_typed_flags<FontListFontNameType, 0x3> {}; +} + +class ImplFontListNameInfo +{ + friend class FontList; + +private: + OUString maSearchName; + ImplFontListFontMetric* mpFirst; + FontListFontNameType mnType; + + explicit ImplFontListNameInfo(const OUString& rSearchName) + : maSearchName(rSearchName) + , mpFirst(nullptr) + , mnType(FontListFontNameType::NONE) + { + } +}; + +//sort normal to the start +static int sortWeightValue(FontWeight eWeight) +{ + if (eWeight < WEIGHT_NORMAL) + return eWeight + 1; + if (eWeight > WEIGHT_NORMAL) + return eWeight - 1; + return 0; // eWeight == WEIGHT_NORMAL +} + +static sal_Int32 ImplCompareFontMetric( ImplFontListFontMetric* pInfo1, + ImplFontListFontMetric* pInfo2 ) +{ + //Sort non italic before italics + if ( pInfo1->GetItalic() < pInfo2->GetItalic() ) + return -1; + else if ( pInfo1->GetItalic() > pInfo2->GetItalic() ) + return 1; + + //Sort normal weight to the start, followed by lightest to heaviest weights + int nWeight1 = sortWeightValue(pInfo1->GetWeight()); + int nWeight2 = sortWeightValue(pInfo2->GetWeight()); + + if ( nWeight1 < nWeight2 ) + return -1; + else if ( nWeight1 > nWeight2 ) + return 1; + + return pInfo1->GetStyleName().compareTo( pInfo2->GetStyleName() ); +} + +static OUString ImplMakeSearchString(const OUString& rStr) +{ + return rStr.toAsciiLowerCase(); +} + +static OUString ImplMakeSearchStringFromName(const OUString& rStr) +{ + // check for features before alternate font separator + sal_Int32 nColon = rStr.indexOf(':'); + sal_Int32 nSemiColon = rStr.indexOf(';'); + if (nColon != -1 && (nSemiColon == -1 || nColon < nSemiColon)) + return ImplMakeSearchString(rStr.getToken( 0, ':' )); + return ImplMakeSearchString(rStr.getToken( 0, ';' )); +} + +ImplFontListNameInfo* FontList::ImplFind(const OUString& rSearchName, sal_uInt32* pIndex) const +{ + // Append if there is no entry in the list or if the entry is larger + // then the last one. We only compare to the last entry as the list of VCL + // is returned sorted, which increases the probability that appending + // is more likely + if (m_Entries.empty()) + { + if ( pIndex ) + *pIndex = SAL_MAX_UINT32; + return nullptr; + } + else + { + const ImplFontListNameInfo* pCmpData = m_Entries.back().get(); + sal_Int32 nComp = rSearchName.compareTo( pCmpData->maSearchName ); + if (nComp > 0) + { + if ( pIndex ) + *pIndex = SAL_MAX_UINT32; + return nullptr; + } + else if (nComp == 0) + return const_cast<ImplFontListNameInfo*>(pCmpData); + } + + // search fonts in the list + const ImplFontListNameInfo* pCompareData; + const ImplFontListNameInfo* pFoundData = nullptr; + size_t nLow = 0; + size_t nHigh = m_Entries.size() - 1; + size_t nMid; + + do + { + nMid = (nLow + nHigh) / 2; + pCompareData = m_Entries[nMid].get(); + sal_Int32 nComp = rSearchName.compareTo(pCompareData->maSearchName); + if (nComp < 0) + { + if ( !nMid ) + break; + nHigh = nMid-1; + } + else + { + if (nComp > 0) + nLow = nMid + 1; + else + { + pFoundData = pCompareData; + break; + } + } + } + while ( nLow <= nHigh ); + + if ( pIndex ) + { + sal_Int32 nComp = rSearchName.compareTo(pCompareData->maSearchName); + if (nComp > 0) + *pIndex = (nMid+1); + else + *pIndex = nMid; + } + + return const_cast<ImplFontListNameInfo*>(pFoundData); +} + +ImplFontListNameInfo* FontList::ImplFindByName(const OUString& rStr) const +{ + OUString aSearchName = ImplMakeSearchStringFromName(rStr); + return ImplFind( aSearchName, nullptr ); +} + +void FontList::ImplInsertFonts(OutputDevice* pDevice, bool bInsertData) +{ + rtl_TextEncoding eSystemEncoding = osl_getThreadTextEncoding(); + + FontListFontNameType nType; + if ( pDevice->GetOutDevType() != OUTDEV_PRINTER ) + nType = FontListFontNameType::SCREEN; + else + nType = FontListFontNameType::PRINTER; + + // inquire all fonts from the device + int n = pDevice->GetDevFontCount(); + if (n == 0 && comphelper::LibreOfficeKit::isActive()) + { + pDevice->RefreshFontData(true); + n = pDevice->GetDevFontCount(); + } + + for (int i = 0; i < n; ++i) + { + FontMetric aFontMetric = pDevice->GetDevFont( i ); + OUString aSearchName(aFontMetric.GetFamilyName()); + ImplFontListNameInfo* pData; + sal_uInt32 nIndex; + aSearchName = ImplMakeSearchString(aSearchName); + pData = ImplFind( aSearchName, &nIndex ); + + if ( !pData ) + { + if ( bInsertData ) + { + ImplFontListFontMetric* pNewInfo = new ImplFontListFontMetric( aFontMetric, pDevice ); + pData = new ImplFontListNameInfo( aSearchName ); + pData->mpFirst = pNewInfo; + pNewInfo->mpNext = nullptr; + + if (nIndex < static_cast<sal_uInt32>(m_Entries.size())) + m_Entries.insert(m_Entries.begin()+nIndex, + std::unique_ptr<ImplFontListNameInfo>(pData)); + else + m_Entries.push_back(std::unique_ptr<ImplFontListNameInfo>(pData)); + } + } + else + { + if ( bInsertData ) + { + bool bInsert = true; + ImplFontListFontMetric* pPrev = nullptr; + ImplFontListFontMetric* pTemp = pData->mpFirst; + ImplFontListFontMetric* pNewInfo = new ImplFontListFontMetric( aFontMetric, pDevice ); + while ( pTemp ) + { + sal_Int32 eComp = ImplCompareFontMetric( pNewInfo, pTemp ); + if ( eComp <= 0 ) + { + if ( eComp == 0 ) + { + // Overwrite charset, because charset should match + // with the system charset + if ( (pTemp->GetCharSet() != eSystemEncoding) && + (pNewInfo->GetCharSet() == eSystemEncoding) ) + { + ImplFontListFontMetric* pTemp2 = pTemp->mpNext; + *static_cast<FontMetric*>(pTemp) = *static_cast<FontMetric*>(pNewInfo); + pTemp->mpNext = pTemp2; + } + delete pNewInfo; + bInsert = false; + } + + break; + } + + pPrev = pTemp; + pTemp = pTemp->mpNext; + } + + if ( bInsert ) + { + pNewInfo->mpNext = pTemp; + if ( pPrev ) + pPrev->mpNext = pNewInfo; + else + pData->mpFirst = pNewInfo; + } + } + } + + if ( pData ) + pData->mnType |= nType; + } +} + +FontList::FontList(OutputDevice* pDevice, OutputDevice* pDevice2) +{ + // initialise variables + mpDev = pDevice; + mpDev2 = pDevice2; + + // store style names + maLight = SvtResId(STR_SVT_STYLE_LIGHT); + maLightItalic = SvtResId(STR_SVT_STYLE_LIGHT_ITALIC); + maNormal = SvtResId(STR_SVT_STYLE_NORMAL); + maNormalItalic = SvtResId(STR_SVT_STYLE_NORMAL_ITALIC); + maBold = SvtResId(STR_SVT_STYLE_BOLD); + maBoldItalic = SvtResId(STR_SVT_STYLE_BOLD_ITALIC); + maBlack = SvtResId(STR_SVT_STYLE_BLACK); + maBlackItalic = SvtResId(STR_SVT_STYLE_BLACK_ITALIC); + + ImplInsertFonts(pDevice, true); + + // if required compare to the screen fonts + // in order to map the duplicates to Equal + bool bCompareWindow = false; + if ( !pDevice2 && (pDevice->GetOutDevType() == OUTDEV_PRINTER) ) + { + bCompareWindow = true; + pDevice2 = Application::GetDefaultDevice(); + } + + if ( pDevice2 && + (pDevice2->GetOutDevType() != pDevice->GetOutDevType()) ) + ImplInsertFonts(pDevice2, !bCompareWindow); +} + +FontList::~FontList() +{ + // delete FontMetrics + ImplFontListFontMetric *pTemp, *pInfo; + for (auto const& it : m_Entries) + { + pInfo = it->mpFirst; + while ( pInfo ) + { + pTemp = pInfo->mpNext; + delete pInfo; + pInfo = pTemp; + } + } +} + +std::unique_ptr<FontList> FontList::Clone() const +{ + return std::unique_ptr<FontList>(new FontList(mpDev, mpDev2)); +} + +const OUString& FontList::GetStyleName(FontWeight eWeight, FontItalic eItalic) const +{ + if ( eWeight > WEIGHT_BOLD ) + { + if ( eItalic > ITALIC_NONE ) + return maBlackItalic; + else + return maBlack; + } + else if ( eWeight > WEIGHT_MEDIUM ) + { + if ( eItalic > ITALIC_NONE ) + return maBoldItalic; + else + return maBold; + } + else if ( eWeight > WEIGHT_LIGHT ) + { + if ( eItalic > ITALIC_NONE ) + return maNormalItalic; + else + return maNormal; + } + else if ( eWeight != WEIGHT_DONTKNOW ) + { + if ( eItalic > ITALIC_NONE ) + return maLightItalic; + else + return maLight; + } + else + { + if ( eItalic > ITALIC_NONE ) + return maNormalItalic; + else + return maNormal; + } +} + +OUString FontList::GetStyleName(const FontMetric& rInfo) const +{ + OUString aStyleName = rInfo.GetStyleName(); + FontWeight eWeight = rInfo.GetWeight(); + FontItalic eItalic = rInfo.GetItalic(); + + // return synthetic Name if no StyleName was set + if (aStyleName.isEmpty()) + aStyleName = GetStyleName(eWeight, eItalic); + else + { + // Translate StyleName to localized name + OUString aCompareStyleName = aStyleName.toAsciiLowerCase().replaceAll(" ", ""); + if (aCompareStyleName == "bold") + aStyleName = maBold; + else if (aCompareStyleName == "bolditalic") + aStyleName = maBoldItalic; + else if (aCompareStyleName == "italic") + aStyleName = maNormalItalic; + else if (aCompareStyleName == "standard") + aStyleName = maNormal; + else if (aCompareStyleName == "regular") + aStyleName = maNormal; + else if (aCompareStyleName == "medium") + aStyleName = maNormal; + else if (aCompareStyleName == "light") + aStyleName = maLight; + else if (aCompareStyleName == "lightitalic") + aStyleName = maLightItalic; + else if (aCompareStyleName == "black") + aStyleName = maBlack; + else if (aCompareStyleName == "blackitalic") + aStyleName = maBlackItalic; + /* tdf#107700 support some less common style names with localization */ + else if (aCompareStyleName == "book") + aStyleName = SvtResId(STR_SVT_STYLE_BOOK); + else if (aCompareStyleName == "boldoblique") + aStyleName = SvtResId(STR_SVT_STYLE_BOLD_OBLIQUE); + else if (aCompareStyleName == "condensed") + aStyleName = SvtResId(STR_SVT_STYLE_CONDENSED); + else if (aCompareStyleName == "condensedbold") + aStyleName = SvtResId(STR_SVT_STYLE_CONDENSED_BOLD); + else if (aCompareStyleName == "condensedbolditalic") + aStyleName = SvtResId(STR_SVT_STYLE_CONDENSED_BOLD_ITALIC); + else if (aCompareStyleName == "condensedboldoblique") + aStyleName = SvtResId(STR_SVT_STYLE_CONDENSED_BOLD_OBLIQUE); + else if (aCompareStyleName == "condenseditalic") + aStyleName = SvtResId(STR_SVT_STYLE_CONDENSED_ITALIC); + else if (aCompareStyleName == "condensedoblique") + aStyleName = SvtResId(STR_SVT_STYLE_CONDENSED_OBLIQUE); + else if (aCompareStyleName == "extralight") + aStyleName = SvtResId(STR_SVT_STYLE_EXTRALIGHT); + else if (aCompareStyleName == "extralightitalic") + aStyleName = SvtResId(STR_SVT_STYLE_EXTRALIGHT_ITALIC); + /* Medium is synonym with Normal */ + else if (aCompareStyleName == "mediumitalic") + aStyleName = maNormalItalic; + else if (aCompareStyleName == "oblique") + aStyleName = SvtResId(STR_SVT_STYLE_OBLIQUE); + else if (aCompareStyleName == "semibold") + aStyleName = SvtResId(STR_SVT_STYLE_SEMIBOLD); + else if (aCompareStyleName == "semibolditalic") + aStyleName = SvtResId(STR_SVT_STYLE_SEMIBOLD_ITALIC); + + // fix up StyleName, because the PS Printer driver from + // W2000 returns wrong StyleNames (e.g. Bold instead of Bold Italic + // for Helvetica) + if ( eItalic > ITALIC_NONE ) + { + if ( (aStyleName == maNormal) || + (aStyleName == maBold) || + (aStyleName == maLight) || + (aStyleName == maBlack) ) + aStyleName = GetStyleName( eWeight, eItalic ); + } + } + + return aStyleName; +} + +OUString FontList::GetFontMapText( const FontMetric& rInfo ) const +{ + if ( rInfo.GetFamilyName().isEmpty() ) + { + return OUString(); + } + + // Search Fontname + ImplFontListNameInfo* pData = ImplFindByName( rInfo.GetFamilyName() ); + if ( !pData ) + { + if (maMapNotAvailable.isEmpty()) + maMapNotAvailable = SvtResId(STR_SVT_FONTMAP_NOTAVAILABLE); + return maMapNotAvailable; + } + + // search for synthetic style + FontListFontNameType nType = pData->mnType; + const OUString& rStyleName = rInfo.GetStyleName(); + if (!rStyleName.isEmpty()) + { + bool bNotSynthetic = false; + FontWeight eWeight = rInfo.GetWeight(); + FontItalic eItalic = rInfo.GetItalic(); + ImplFontListFontMetric* pFontMetric = pData->mpFirst; + while ( pFontMetric ) + { + if ( (eWeight == pFontMetric->GetWeight()) && + (eItalic == pFontMetric->GetItalic()) ) + { + bNotSynthetic = true; + break; + } + + pFontMetric = pFontMetric->mpNext; + } + + if ( !bNotSynthetic ) + { + if (maMapStyleNotAvailable.isEmpty()) + const_cast<FontList*>(this)->maMapStyleNotAvailable = SvtResId(STR_SVT_FONTMAP_STYLENOTAVAILABLE); + return maMapStyleNotAvailable; + } + } + + // Only Printer-Font? + if ( nType == FontListFontNameType::PRINTER ) + { + if (maMapPrinterOnly.isEmpty()) + const_cast<FontList*>(this)->maMapPrinterOnly = SvtResId(STR_SVT_FONTMAP_PRINTERONLY); + return maMapPrinterOnly; + } + else + { + if (maMapBoth.isEmpty()) + const_cast<FontList*>(this)->maMapBoth = SvtResId(STR_SVT_FONTMAP_BOTH); + return maMapBoth; + } +} + +namespace +{ + FontMetric makeMissing(ImplFontListFontMetric const * pFontNameInfo, const OUString &rName, + FontWeight eWeight, FontItalic eItalic) + { + FontMetric aInfo; + // if the fontname matches, we copy as much as possible + if (pFontNameInfo) + { + aInfo = *pFontNameInfo; + aInfo.SetStyleName(OUString()); + } + + aInfo.SetWeight(eWeight); + aInfo.SetItalic(eItalic); + + //If this is a known but uninstalled symbol font which we can remap to + //OpenSymbol then toggle its charset to be a symbol font + if (ConvertChar::GetRecodeData(rName, "OpenSymbol")) + aInfo.SetCharSet(RTL_TEXTENCODING_SYMBOL); + + return aInfo; + } +} + +FontMetric FontList::Get(const OUString& rName, const OUString& rStyleName) const +{ + ImplFontListNameInfo* pData = ImplFindByName( rName ); + ImplFontListFontMetric* pFontMetric = nullptr; + ImplFontListFontMetric* pFontNameInfo = nullptr; + if ( pData ) + { + ImplFontListFontMetric* pSearchInfo = pData->mpFirst; + pFontNameInfo = pSearchInfo; + pSearchInfo = pData->mpFirst; + while ( pSearchInfo ) + { + if (rStyleName.equalsIgnoreAsciiCase(GetStyleName(*pSearchInfo))) + { + pFontMetric = pSearchInfo; + break; + } + + pSearchInfo = pSearchInfo->mpNext; + } + } + + // reproduce attributes if data could not be found + FontMetric aInfo; + if ( !pFontMetric ) + { + FontWeight eWeight = WEIGHT_DONTKNOW; + FontItalic eItalic = ITALIC_NONE; + + if ( rStyleName == maNormal ) + { + eItalic = ITALIC_NONE; + eWeight = WEIGHT_NORMAL; + } + else if ( rStyleName == maNormalItalic ) + { + eItalic = ITALIC_NORMAL; + eWeight = WEIGHT_NORMAL; + } + else if ( rStyleName == maBold ) + { + eItalic = ITALIC_NONE; + eWeight = WEIGHT_BOLD; + } + else if ( rStyleName == maBoldItalic ) + { + eItalic = ITALIC_NORMAL; + eWeight = WEIGHT_BOLD; + } + else if ( rStyleName == maLight ) + { + eItalic = ITALIC_NONE; + eWeight = WEIGHT_LIGHT; + } + else if ( rStyleName == maLightItalic ) + { + eItalic = ITALIC_NORMAL; + eWeight = WEIGHT_LIGHT; + } + else if ( rStyleName == maBlack ) + { + eItalic = ITALIC_NONE; + eWeight = WEIGHT_BLACK; + } + else if ( rStyleName == maBlackItalic ) + { + eItalic = ITALIC_NORMAL; + eWeight = WEIGHT_BLACK; + } + aInfo = makeMissing(pFontNameInfo, rName, eWeight, eItalic); + } + else + aInfo = *pFontMetric; + + // set Fontname to keep FontAlias + aInfo.SetFamilyName( rName ); + aInfo.SetStyleName( rStyleName ); + + return aInfo; +} + +FontMetric FontList::Get(const OUString& rName, + FontWeight eWeight, FontItalic eItalic) const +{ + ImplFontListNameInfo* pData = ImplFindByName( rName ); + ImplFontListFontMetric* pFontMetric = nullptr; + ImplFontListFontMetric* pFontNameInfo = nullptr; + if ( pData ) + { + ImplFontListFontMetric* pSearchInfo = pData->mpFirst; + pFontNameInfo = pSearchInfo; + while ( pSearchInfo ) + { + if ( (eWeight == pSearchInfo->GetWeight()) && + (eItalic == pSearchInfo->GetItalic()) ) + { + pFontMetric = pSearchInfo; + break; + } + + pSearchInfo = pSearchInfo->mpNext; + } + } + + // reproduce attributes if data could not be found + FontMetric aInfo; + if ( !pFontMetric ) + aInfo = makeMissing(pFontNameInfo, rName, eWeight, eItalic); + else + aInfo = *pFontMetric; + + // set Fontname to keep FontAlias + aInfo.SetFamilyName( rName ); + + return aInfo; +} + +bool FontList::IsAvailable(const OUString& rName) const +{ + return (ImplFindByName( rName ) != nullptr); +} + +const FontMetric& FontList::GetFontName(size_t const nFont) const +{ + DBG_ASSERT( nFont < GetFontNameCount(), "FontList::GetFontName(): nFont >= Count" ); + + return *(m_Entries[nFont]->mpFirst); +} + +sal_Handle FontList::GetFirstFontMetric(const OUString& rName) const +{ + ImplFontListNameInfo* pData = ImplFindByName( rName ); + if ( !pData ) + return nullptr; + else + return static_cast<sal_Handle>(pData->mpFirst); +} + +sal_Handle FontList::GetNextFontMetric( sal_Handle hFontMetric ) +{ + ImplFontListFontMetric* pInfo = static_cast<ImplFontListFontMetric*>(hFontMetric); + return static_cast<sal_Handle>(pInfo->mpNext); +} + +const FontMetric& FontList::GetFontMetric( sal_Handle hFontMetric ) +{ + ImplFontListFontMetric* pInfo = static_cast<ImplFontListFontMetric*>(hFontMetric); + return *pInfo; +} + +const sal_IntPtr* FontList::GetSizeAry( const FontMetric& rInfo ) const +{ + // first delete Size-Array + mpSizeAry.reset(); + + // use standard sizes if no name + if ( rInfo.GetFamilyName().isEmpty() ) + return aStdSizeAry; + + // first search fontname in order to use device from the matching font + OutputDevice* pDevice = mpDev; + ImplFontListNameInfo* pData = ImplFindByName( rInfo.GetFamilyName() ); + if ( pData ) + pDevice = pData->mpFirst->GetDevice(); + + int nDevSizeCount = pDevice->GetDevFontSizeCount( rInfo ); + if ( !nDevSizeCount || + (pDevice->GetDevFontSize( rInfo, 0 ).Height() == 0) ) + return aStdSizeAry; + + MapMode aOldMapMode = pDevice->GetMapMode(); + MapMode aMap( MapUnit::Map10thInch, Point(), Fraction( 1, 72 ), Fraction( 1, 72 ) ); + pDevice->SetMapMode( aMap ); + + int nRealCount = 0; + long nOldHeight = 0; + mpSizeAry.reset(new sal_IntPtr[nDevSizeCount+1] ); + for (int i = 0; i < nDevSizeCount; ++i) + { + Size aSize = pDevice->GetDevFontSize( rInfo, i ); + if ( aSize.Height() != nOldHeight ) + { + nOldHeight = aSize.Height(); + mpSizeAry[nRealCount] = nOldHeight; + nRealCount++; + } + } + mpSizeAry[nRealCount] = 0; + + pDevice->SetMapMode( aOldMapMode ); + return mpSizeAry.get(); +} + +struct ImplFSNameItem +{ + sal_Int32 mnSize; + const char* mszUtf8Name; +}; + +static const ImplFSNameItem aImplSimplifiedChinese[] = +{ + { 50, "\xe5\x85\xab\xe5\x8f\xb7" }, + { 55, "\xe4\xb8\x83\xe5\x8f\xb7" }, + { 65, "\xe5\xb0\x8f\xe5\x85\xad" }, + { 75, "\xe5\x85\xad\xe5\x8f\xb7" }, + { 90, "\xe5\xb0\x8f\xe4\xba\x94" }, + { 105, "\xe4\xba\x94\xe5\x8f\xb7" }, + { 120, "\xe5\xb0\x8f\xe5\x9b\x9b" }, + { 140, "\xe5\x9b\x9b\xe5\x8f\xb7" }, + { 150, "\xe5\xb0\x8f\xe4\xb8\x89" }, + { 160, "\xe4\xb8\x89\xe5\x8f\xb7" }, + { 180, "\xe5\xb0\x8f\xe4\xba\x8c" }, + { 220, "\xe4\xba\x8c\xe5\x8f\xb7" }, + { 240, "\xe5\xb0\x8f\xe4\xb8\x80" }, + { 260, "\xe4\xb8\x80\xe5\x8f\xb7" }, + { 360, "\xe5\xb0\x8f\xe5\x88\x9d" }, + { 420, "\xe5\x88\x9d\xe5\x8f\xb7" } +}; + +FontSizeNames::FontSizeNames( LanguageType eLanguage ) +{ + if ( eLanguage == LANGUAGE_DONTKNOW ) + eLanguage = Application::GetSettings().GetUILanguageTag().getLanguageType(); + if ( eLanguage == LANGUAGE_SYSTEM ) + eLanguage = MsLangId::getSystemUILanguage(); + + if (MsLangId::isSimplifiedChinese(eLanguage)) + { + // equivalent for traditional chinese disabled by popular request, #i89077# + mpArray = aImplSimplifiedChinese; + mnElem = SAL_N_ELEMENTS(aImplSimplifiedChinese); + } + else + { + mpArray = nullptr; + mnElem = 0; + } +} + +sal_Int32 FontSizeNames::Name2Size( const OUString& rName ) const +{ + if ( mnElem ) + { + OString aName(OUStringToOString(rName, + RTL_TEXTENCODING_UTF8)); + + // linear search is sufficient for this rare case + for( long i = mnElem; --i >= 0; ) + if ( aName == mpArray[i].mszUtf8Name ) + return mpArray[i].mnSize; + } + + return 0; +} + +OUString FontSizeNames::Size2Name( sal_Int32 nValue ) const +{ + OUString aStr; + + // binary search + for( long lower = 0, upper = mnElem - 1; lower <= upper; ) + { + long mid = (upper + lower) >> 1; + if ( nValue == mpArray[mid].mnSize ) + { + aStr = OUString( mpArray[mid].mszUtf8Name, strlen(mpArray[mid].mszUtf8Name), RTL_TEXTENCODING_UTF8 ); + break; + } + else if ( nValue < mpArray[mid].mnSize ) + upper = mid - 1; + else /* ( nValue > mpArray[mid].mnSize ) */ + lower = mid + 1; + } + + return aStr; +} + +OUString FontSizeNames::GetIndexName( sal_Int32 nIndex ) const +{ + OUString aStr; + + if ( nIndex < mnElem ) + aStr = OUString( mpArray[nIndex].mszUtf8Name, strlen(mpArray[nIndex].mszUtf8Name), RTL_TEXTENCODING_UTF8 ); + + return aStr; +} + +sal_Int32 FontSizeNames::GetIndexSize( sal_Int32 nIndex ) const +{ + if ( nIndex >= mnElem ) + return 0; + return mpArray[nIndex].mnSize; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |