From eb20f085489d2467935f2086b0ebdaf433b5ef21 Mon Sep 17 00:00:00 2001 From: Mike Kaganski Date: Mon, 14 Jun 2021 14:28:04 +0200 Subject: Use FontList::GetFirstFontMetric instead of custom iteration code Besides code deduplication, this takes care of case-insensitive search. Also fall back to a default font in case of no match in doc_renderFont*. Change-Id: Ica45ca10c374cf6581ba2f6b60563d6a1447232a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117121 Tested-by: Jenkins Reviewed-by: Mike Kaganski Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117184 Tested-by: Jenkins CollaboraOffice Tested-by: Aron Budea Reviewed-by: Aron Budea --- desktop/source/lib/init.cxx | 190 ++++++++++++++++++++------------------------ 1 file changed, 87 insertions(+), 103 deletions(-) diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 34853628f1d6..b06f5900912f 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1220,6 +1220,26 @@ rtl::Reference forceSetClipboardForCurrentView(LibreOfficeKitDocum #endif +const vcl::Font* FindFont(const OUString& rFontName) +{ + SfxObjectShell* pDocSh = SfxObjectShell::Current(); + const SvxFontListItem* pFonts + = static_cast(pDocSh->GetItem(SID_ATTR_CHAR_FONTLIST)); + const FontList* pList = pFonts ? pFonts->GetFontList() : nullptr; + if (pList && !rFontName.isEmpty()) + if (sal_Handle hMetric = pList->GetFirstFontMetric(rFontName)) + return &FontList::GetFontMetric(hMetric); + return nullptr; +} + +vcl::Font FindFont_FallbackToDefault(const OUString& rFontName) +{ + if (auto pFound = FindFont(rFontName)) + return *pFound; + + return OutputDevice::GetDefaultFont(DefaultFontType::SANS_UNICODE, LANGUAGE_NONE, + GetDefaultFontFlags::NONE); +} } // anonymous namespace LibLODocument_Impl::LibLODocument_Impl(const uno::Reference &xComponent, int nDocumentId) @@ -4684,43 +4704,25 @@ static char* getFonts (const char* pCommand) static char* getFontSubset (const OString& aFontName) { OUString aFoundFont(::rtl::Uri::decode(OStringToOUString(aFontName, RTL_TEXTENCODING_UTF8), rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8)); - SfxObjectShell* pDocSh = SfxObjectShell::Current(); - const SvxFontListItem* pFonts = static_cast( - pDocSh->GetItem(SID_ATTR_CHAR_FONTLIST)); - const FontList* pList = pFonts ? pFonts->GetFontList() : nullptr; boost::property_tree::ptree aTree; aTree.put("commandName", ".uno:FontSubset"); boost::property_tree::ptree aValues; - if ( pList && !aFoundFont.isEmpty() ) + if (const vcl::Font* pFont = FindFont(aFoundFont)) { - sal_uInt16 nFontCount = pList->GetFontNameCount(); - sal_uInt16 nItFont = 0; - for (; nItFont < nFontCount; ++nItFont) - { - if (aFoundFont == pList->GetFontName(nItFont).GetFamilyName()) - { - break; - } - } + FontCharMapRef xFontCharMap (new FontCharMap()); + auto aDevice(VclPtr::Create(DeviceFormat::DEFAULT)); - if ( nItFont < nFontCount ) - { - FontCharMapRef xFontCharMap (new FontCharMap()); - auto aDevice(VclPtr::Create(DeviceFormat::DEFAULT)); - const vcl::Font& aFont(pList->GetFontName(nItFont)); + aDevice->SetFont(*pFont); + aDevice->GetFontCharMap(xFontCharMap); + SubsetMap aSubMap(xFontCharMap); - aDevice->SetFont(aFont); - aDevice->GetFontCharMap(xFontCharMap); - SubsetMap aSubMap(xFontCharMap); - - for (auto const& subset : aSubMap.GetSubsetMap()) - { - boost::property_tree::ptree aChild; - aChild.put("", static_cast(ublock_getCode(subset.GetRangeMin()))); - aValues.push_back(std::make_pair("", aChild)); - } + for (auto const& subset : aSubMap.GetSubsetMap()) + { + boost::property_tree::ptree aChild; + aChild.put("", static_cast(ublock_getCode(subset.GetRangeMin()))); + aValues.push_back(std::make_pair("", aChild)); } } @@ -5341,98 +5343,80 @@ unsigned char* doc_renderFontOrientation(SAL_UNUSED_PARAMETER LibreOfficeKitDocu SolarMutexGuard aGuard; SetLastExceptionMsg(); - OString aSearchedFontName(pFontName); - OUString aText(OStringToOUString(pChar, RTL_TEXTENCODING_UTF8)); - SfxObjectShell* pDocSh = SfxObjectShell::Current(); - const SvxFontListItem* pFonts = static_cast( - pDocSh->GetItem(SID_ATTR_CHAR_FONTLIST)); - const FontList* pList = pFonts ? pFonts->GetFontList() : nullptr; - const int nDefaultFontSize = 25; - if ( pList ) - { - sal_uInt16 nFontCount = pList->GetFontNameCount(); - for (sal_uInt16 i = 0; i < nFontCount; ++i) - { - const FontMetric& rFontMetric = pList->GetFontName(i); - const OUString& aFontName = rFontMetric.GetFamilyName(); - if (aSearchedFontName != aFontName.toUtf8()) - continue; - - if (aText.isEmpty()) - aText = rFontMetric.GetFamilyName(); + auto aFont = FindFont_FallbackToDefault(OStringToOUString(pFontName, RTL_TEXTENCODING_UTF8)); - auto aDevice(VclPtr::Create(DeviceFormat::DEFAULT)); - ::tools::Rectangle aRect; - vcl::Font aFont(rFontMetric); - aFont.SetFontSize(Size(0, nDefaultFontSize)); - aFont.SetOrientation(pOrientation); - aDevice->SetFont(aFont); - aDevice->GetTextBoundRect(aRect, aText); - if (aRect.IsEmpty()) - break; + OUString aText(OStringToOUString(pChar, RTL_TEXTENCODING_UTF8)); + if (aText.isEmpty()) + aText = aFont.GetFamilyName(); + + auto aDevice(VclPtr::Create(DeviceFormat::DEFAULT)); + ::tools::Rectangle aRect; + aFont.SetFontSize(Size(0, nDefaultFontSize)); + aFont.SetOrientation(pOrientation); + aDevice->SetFont(aFont); + aDevice->GetTextBoundRect(aRect, aText); + if (aRect.IsEmpty()) + return nullptr; - int nFontWidth = aRect.BottomRight().X() + 1; - int nFontHeight = aRect.BottomRight().Y() + 1; + int nFontWidth = aRect.BottomRight().X() + 1; + int nFontHeight = aRect.BottomRight().Y() + 1; - if (!(nFontWidth > 0 && nFontHeight > 0)) - break; + if (!(nFontWidth > 0 && nFontHeight > 0)) + return nullptr; - if (*pFontWidth > 0 && *pFontHeight > 0) - { - double fScaleX = *pFontWidth / static_cast(nFontWidth) / 1.5; - double fScaleY = *pFontHeight / static_cast(nFontHeight) / 1.5; + if (*pFontWidth > 0 && *pFontHeight > 0) + { + double fScaleX = *pFontWidth / static_cast(nFontWidth) / 1.5; + double fScaleY = *pFontHeight / static_cast(nFontHeight) / 1.5; - double fScale = std::min(fScaleX, fScaleY); + double fScale = std::min(fScaleX, fScaleY); - if (fScale >= 1.0) - { - int nFontSize = fScale * nDefaultFontSize; - aFont.SetFontSize(Size(0, nFontSize)); - aDevice->SetFont(aFont); - } + if (fScale >= 1.0) + { + int nFontSize = fScale * nDefaultFontSize; + aFont.SetFontSize(Size(0, nFontSize)); + aDevice->SetFont(aFont); + } - aRect = tools::Rectangle(0, 0, *pFontWidth, *pFontHeight); + aRect = tools::Rectangle(0, 0, *pFontWidth, *pFontHeight); - nFontWidth = *pFontWidth; - nFontHeight = *pFontHeight; + nFontWidth = *pFontWidth; + nFontHeight = *pFontHeight; - } + } - unsigned char* pBuffer = static_cast(malloc(4 * nFontWidth * nFontHeight)); - if (!pBuffer) - break; + unsigned char* pBuffer = static_cast(malloc(4 * nFontWidth * nFontHeight)); + if (!pBuffer) + return nullptr; - memset(pBuffer, 0, nFontWidth * nFontHeight * 4); - aDevice->SetBackground(Wallpaper(COL_TRANSPARENT)); - aDevice->SetOutputSizePixelScaleOffsetAndBuffer( - Size(nFontWidth, nFontHeight), Fraction(1.0), Point(), - pBuffer); + memset(pBuffer, 0, nFontWidth * nFontHeight * 4); + aDevice->SetBackground(Wallpaper(COL_TRANSPARENT)); + aDevice->SetOutputSizePixelScaleOffsetAndBuffer( + Size(nFontWidth, nFontHeight), Fraction(1.0), Point(), + pBuffer); - if (*pFontWidth > 0 && *pFontHeight > 0) - { - DrawTextFlags const nStyle = - DrawTextFlags::Center - | DrawTextFlags::VCenter - | DrawTextFlags::MultiLine - | DrawTextFlags::WordBreak;// | DrawTextFlags::WordBreakHyphenation ; + if (*pFontWidth > 0 && *pFontHeight > 0) + { + DrawTextFlags const nStyle = + DrawTextFlags::Center + | DrawTextFlags::VCenter + | DrawTextFlags::MultiLine + | DrawTextFlags::WordBreak;// | DrawTextFlags::WordBreakHyphenation ; - aDevice->DrawText(aRect, aText, nStyle); - } - else - { - *pFontWidth = nFontWidth; - *pFontHeight = nFontHeight; + aDevice->DrawText(aRect, aText, nStyle); + } + else + { + *pFontWidth = nFontWidth; + *pFontHeight = nFontHeight; - aDevice->DrawText(Point(0,0), aText); - } + aDevice->DrawText(Point(0,0), aText); + } - return pBuffer; - } - } - return nullptr; + return pBuffer; } -- cgit v1.2.3