forked from amazingfate/loongoffice
* all .ui files go from <interface> to <interface domain="MODULE"> e.g. vcl
* all .src files go away and the english source strings folded into the .hrc as NC_("context", "source string")
* ResMgr is dropped in favour of std::locale imbued by boost::locale::generator pointed at matching
MODULE .mo files
* UIConfig translations are folded into the module .mo, so e.g. UIConfig_cui
goes from l10n target to normal one, so the res/lang.zips of UI files go away
* translation via Translation::get(hrc-define-key, imbued-std::locale)
* python can now be translated with its inbuilt gettext support (we keep the name strings.hrc there
to keep finding the .hrc file uniform) so magic numbers can go away there
* java and starbasic components can be translated via the pre-existing css.resource.StringResourceWithLocation
mechanism
* en-US res files go away, their strings are now the .hrc keys in the source code
* remaining .res files are replaced by .mo files
* in .res/.ui-lang-zip files, the old scheme missing translations of strings
results in inserting the english original so something can be found, now the
standard fallback of using the english original from the source key is used, so
partial translations shrink dramatically in size
* extract .hrc strings with hrcex which backs onto
xgettext -C --add-comments --keyword=NC_:1c,2 --from-code=UTF-8 --no-wrap
* extract .ui strings with uiex which backs onto
xgettext --add-comments --no-wrap
* qtz for gettext translations is generated at runtime as ascii-ified crc32 of
content + "|" + msgid
* [API CHANGE] remove deprecated binary .res resouce loader related uno apis
com::sun:⭐:resource::OfficeResourceLoader
com::sun:⭐:resource::XResourceBundleLoader
com::sun:⭐:resource::XResourceBundle
when translating strings via uno apis
com.sun.star.resource.StringResourceWithLocation
can continue to be used
Change-Id: Ia2594a2672b7301d9c3421fdf31b6cfe7f3f8d0a
889 lines
26 KiB
C++
889 lines
26 KiB
C++
/* -*- 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 <comphelper/string.hxx>
|
|
#include <tools/debug.hxx>
|
|
#include <tools/fract.hxx>
|
|
#include <i18nlangtag/mslangid.hxx>
|
|
#include <vcl/window.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/wrkwin.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
|
|
};
|
|
|
|
class ImplFontListFontMetric : public FontMetric
|
|
{
|
|
friend class FontList;
|
|
|
|
private:
|
|
VclPtr<OutputDevice> mpDevice;
|
|
ImplFontListFontMetric* mpNext;
|
|
|
|
public:
|
|
ImplFontListFontMetric( const FontMetric& rInfo,
|
|
OutputDevice* pDev ) :
|
|
FontMetric( rInfo ), mpNext(nullptr)
|
|
{
|
|
mpDevice = pDev;
|
|
}
|
|
|
|
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_uLong* 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 = ULONG_MAX;
|
|
return nullptr;
|
|
}
|
|
else
|
|
{
|
|
const ImplFontListNameInfo* pCmpData = m_Entries.back().get();
|
|
sal_Int32 nComp = rSearchName.compareTo( pCmpData->maSearchName );
|
|
if (nComp > 0)
|
|
{
|
|
if ( pIndex )
|
|
*pIndex = ULONG_MAX;
|
|
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_uLong 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 < 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
FontList* FontList::Clone() const
|
|
{
|
|
FontList* pReturn = new FontList(mpDev, mpDev2);
|
|
return pReturn;
|
|
}
|
|
|
|
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
|
|
{
|
|
long 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;
|
|
}
|
|
}
|
|
|
|
long 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( long 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_uLong nIndex ) const
|
|
{
|
|
OUString aStr;
|
|
|
|
if ( nIndex < mnElem )
|
|
aStr = OUString( mpArray[nIndex].mszUtf8Name, strlen(mpArray[nIndex].mszUtf8Name), RTL_TEXTENCODING_UTF8 );
|
|
|
|
return aStr;
|
|
}
|
|
|
|
long FontSizeNames::GetIndexSize( sal_uLong nIndex ) const
|
|
{
|
|
if ( nIndex >= mnElem )
|
|
return 0;
|
|
return mpArray[nIndex].mnSize;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|