include/vcl/outdev.hxx | 19 +++++++ offapi/UnoApi_offapi.mk | 3 + offapi/com/sun/star/awt/XFontMappingUse.idl | 56 +++++++++++++++++++++++ offapi/com/sun/star/awt/XFontMappingUseItem.idl | 55 ++++++++++++++++++++++ offapi/com/sun/star/awt/XToolkit3.idl | 47 +++++++++++++++++++ offapi/com/sun/star/awt/XToolkitExperimental.idl | 4 - toolkit/source/awt/vclxtoolkit.cxx | 28 +++++++++++ vcl/source/outdev/text.cxx | 55 ++++++++++++++++++++++ 8 files changed, 265 insertions(+), 2 deletions(-)
New commits: commit 5054202e71605cb4f10c798be766798d99cb1b6a Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Mon Oct 4 15:03:19 2021 +0200 Commit: Luboš Luňák <l.lu...@collabora.com> CommitDate: Fri Nov 12 12:12:13 2021 +0100 make it possible to find out what fonts are actually really used A document specifies which font each text is supposed to use, but we still need to map that to a real available font, which includes also font fallback in case the font selected doesn't cover all glyphs. This commit adds API to track this font mapping, first StartTrackingFontMappingUse() will make VCL record this information, and then FinishTrackingFontMappingUse() will stop and return all the information, as a listing saying that a requested font got mapped to a list of fonts and the number of times this took place. This can be useful to find out what actually gets used for a specific document, or compare how changing fonts available affects a specific document. Change-Id: I6426ecef354166bef337b1dc9b9007fda148d5c5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123051 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index e9b8d3540cd1..8c0746215a50 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -1253,6 +1253,25 @@ public: LogicalFontInstance* pLogicalFont, int nFallbackLevel, vcl::text::ImplLayoutArgs& rLayoutArgs, const SalLayoutGlyphs* ) const; + /* + These functions allow collecting information on how fonts are mapped when used, such as what + replacements are used when a requrested font is missing or which fonts are used as fallbacks + when a font doesn't provide all necessary glyphs. + After StartTrackingFontMappingUse() is called, VCL starts collecting font usage for all + text layout calls, FinishTrackingFontMappingUse() will stop collecting and providing + the collected information. + Each item is a mapping from a requested font to a list of actually used fonts and the number + of times this mapping was done. + */ + struct FontMappingUseItem + { + OUString mOriginalFont; + std::vector<OUString> mUsedFonts; + int mCount; + }; + typedef std::vector<FontMappingUseItem> FontMappingUseData; + static void StartTrackingFontMappingUse(); + static FontMappingUseData FinishTrackingFontMappingUse(); // Enabling/disabling RTL only makes sense for OutputDevices that use a mirroring SalGraphicsLayout virtual void EnableRTL( bool bEnable = true); diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk index 26b56bedd8e5..6f1dc604a8e3 100644 --- a/offapi/UnoApi_offapi.mk +++ b/offapi/UnoApi_offapi.mk @@ -1828,6 +1828,8 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/awt,\ XFocusListener \ XFont \ XFont2 \ + XFontMappingUse \ + XFontMappingUseItem \ XGraphics \ XGraphics2 \ XImageButton \ @@ -1890,6 +1892,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/awt,\ XToggleButton \ XToolkit \ XToolkit2 \ + XToolkit3 \ XToolkitExperimental \ XToolkitRobot \ XTopWindow \ diff --git a/offapi/com/sun/star/awt/XFontMappingUse.idl b/offapi/com/sun/star/awt/XFontMappingUse.idl new file mode 100644 index 000000000000..8140d6a78a4a --- /dev/null +++ b/offapi/com/sun/star/awt/XFontMappingUse.idl @@ -0,0 +1,56 @@ +/* -*- 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 . + */ + +#ifndef __com_sun_star_awt_XFontMappingUse_idl__ +#define __com_sun_star_awt_XFontMappingUse_idl__ + +#include <com/sun/star/uno/XInterface.idl> +#include <com/sun/star/awt/XFontMappingUseItem.idl> + +module com { module sun { module star { module awt { + +/** + This interface extends the XToolkit interface with support + for tracking how requested fonts are mapped to actual fonts + when laying out text. + @since LibreOffice 7.3 +*/ +published interface XFontMappingUse: com::sun::star::uno::XInterface +{ + /** + Activate tracking of how requested fonts are mapped to available + fonts. + */ + void startTrackingFontMappingUse(); + + /** + Stop tracking of how requested fonts are mapped to available + fonts and return the mappings that took place since the call + to startTrackingFontMappingUse(). + */ + sequence<XFontMappingUseItem> finishTrackingFontMappingUse(); + +}; + + +}; }; }; }; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/XFontMappingUseItem.idl b/offapi/com/sun/star/awt/XFontMappingUseItem.idl new file mode 100644 index 000000000000..2cb5a8936fd2 --- /dev/null +++ b/offapi/com/sun/star/awt/XFontMappingUseItem.idl @@ -0,0 +1,55 @@ +/* -*- 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 . + */ + +#ifndef __com_sun_star_awt_XFontMappingUseItem_idl__ +#define __com_sun_star_awt_XFontMappingUseItem_idl__ + +module com { module sun { module star { module awt { + +/** + Information about a font mapping that took place. + @since LibreOffice 7.3 +*/ +published struct XFontMappingUseItem +{ + /** + The family name or 'familyName/styleName' (if style name is not empty) + of the requested font. + */ + string originalFont; + + /** + A list of fonts that were actually used, in their order. Each font + is identified as family name or 'familyName/styleName' (if style + name is not empty). + */ + sequence<string> usedFonts; + + /** + The number of times this mapping took place. + */ + long count; +}; + + +}; }; }; }; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/XToolkit3.idl b/offapi/com/sun/star/awt/XToolkit3.idl new file mode 100644 index 000000000000..36d9800c560c --- /dev/null +++ b/offapi/com/sun/star/awt/XToolkit3.idl @@ -0,0 +1,47 @@ +/* -*- 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 . + */ +#ifndef __com_sun_star_awt_XToolkit3_idl__ +#define __com_sun_star_awt_XToolkit3_idl__ + +#include <com/sun/star/awt/XToolkit2.idl> +#include <com/sun/star/awt/XFontMappingUse.idl> + + + +module com { module sun { module star { module awt { + + +/** + Provides a unified interface for the new-style service Toolkit to implement. + + @since LibreOffice 7.3 + */ +published interface XToolkit3 +{ + interface XToolkit2; + + interface com::sun::star::awt::XFontMappingUse; +}; + + +}; }; }; }; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/awt/XToolkitExperimental.idl b/offapi/com/sun/star/awt/XToolkitExperimental.idl index 958c80c1cb9b..d47353dc70b5 100644 --- a/offapi/com/sun/star/awt/XToolkitExperimental.idl +++ b/offapi/com/sun/star/awt/XToolkitExperimental.idl @@ -10,14 +10,14 @@ #ifndef __com_sun_star_awt_XToolkitExperimental_idl__ #define __com_sun_star_awt_XToolkitExperimental_idl__ -#include <com/sun/star/awt/XToolkit2.idl> +#include <com/sun/star/awt/XToolkit3.idl> module com { module sun { module star { module awt { /** Work in progress, don't use unless you know what you are doing. */ -interface XToolkitExperimental : XToolkit2 +interface XToolkitExperimental : XToolkit3 { /** Process all pending idle events */ diff --git a/toolkit/source/awt/vclxtoolkit.cxx b/toolkit/source/awt/vclxtoolkit.cxx index 6914d7125c9b..5991df78fddb 100644 --- a/toolkit/source/awt/vclxtoolkit.cxx +++ b/toolkit/source/awt/vclxtoolkit.cxx @@ -564,6 +564,11 @@ public: // css::awt::XReschedule: virtual void SAL_CALL reschedule() override; + // css::awt::XFontMappingUse: + virtual void SAL_CALL startTrackingFontMappingUse() override; + + virtual css::uno::Sequence<css::awt::XFontMappingUseItem> SAL_CALL finishTrackingFontMappingUse() override; + // css:awt:XToolkitRobot virtual void SAL_CALL keyPress( const css::awt::KeyEvent & aKeyEvent ) override; @@ -2532,6 +2537,29 @@ void SAL_CALL VCLXToolkit::reschedule() Application::Reschedule(true); } +// css::awt::XFontMappingUse: +void SAL_CALL VCLXToolkit::startTrackingFontMappingUse() +{ + SolarMutexGuard aSolarGuard; + OutputDevice::StartTrackingFontMappingUse(); +} + +css::uno::Sequence<css::awt::XFontMappingUseItem> +SAL_CALL VCLXToolkit::finishTrackingFontMappingUse() +{ + SolarMutexGuard aSolarGuard; + OutputDevice::FontMappingUseData data = OutputDevice::FinishTrackingFontMappingUse(); + css::uno::Sequence<css::awt::XFontMappingUseItem> ret( data.size()); + for( size_t i = 0; i < data.size(); ++i ) + { + ret[ i ].originalFont = data[ i ].mOriginalFont; + ret[ i ].usedFonts = comphelper::arrayToSequence<OUString,OUString> + (data[ i ].mUsedFonts.data(), data[ i ].mUsedFonts.size()); + ret[ i ].count = data[ i ].mCount; + } + return ret; +} + // css::awt::XToolkitExperimental void SAL_CALL VCLXToolkit::processEventsToIdle() diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx index 8557ba2654c8..bdeee4fbc428 100644 --- a/vcl/source/outdev/text.cxx +++ b/vcl/source/outdev/text.cxx @@ -51,6 +51,7 @@ #include <textlineinfo.hxx> #include <impglyphitem.hxx> #include <optional> +#include <font/PhysicalFontFace.hxx> #define TEXT_DRAW_ELLIPSIS (DrawTextFlags::EndEllipsis | DrawTextFlags::PathEllipsis | DrawTextFlags::NewsEllipsis) @@ -1245,6 +1246,57 @@ vcl::text::ImplLayoutArgs OutputDevice::ImplPrepareLayoutArgs( OUString& rStr, return aLayoutArgs; } +static OutputDevice::FontMappingUseData* fontMappingUseData = nullptr; + +static inline bool IsTrackingFontMappingUse() +{ + return fontMappingUseData != nullptr; +} + +static void TrackFontMappingUse( const vcl::Font& originalFont, const SalLayout* salLayout) +{ + assert(fontMappingUseData); + OUString originalName = originalFont.GetStyleName().isEmpty() + ? originalFont.GetFamilyName() + : originalFont.GetFamilyName() + "/" + originalFont.GetStyleName(); + std::vector<OUString> usedFontNames; + SalLayoutGlyphs glyphs = salLayout->GetGlyphs(); // includes all font fallbacks + int level = 0; + while( const SalLayoutGlyphsImpl* impl = glyphs.Impl(level++)) + { + const vcl::font::PhysicalFontFace* face = impl->GetFont()->GetFontFace(); + OUString name = face->GetStyleName().isEmpty() + ? face->GetFamilyName() + : face->GetFamilyName() + "/" + face->GetStyleName(); + usedFontNames.push_back( name ); + } + for( OutputDevice::FontMappingUseItem& item : *fontMappingUseData ) + { + if( item.mOriginalFont == originalName && item.mUsedFonts == usedFontNames ) + { + ++item.mCount; + return; + } + } + fontMappingUseData->push_back( { originalName, usedFontNames, 1 } ); +} + +void OutputDevice::StartTrackingFontMappingUse() +{ + delete fontMappingUseData; + fontMappingUseData = new FontMappingUseData; +} + +OutputDevice::FontMappingUseData OutputDevice::FinishTrackingFontMappingUse() +{ + if(!fontMappingUseData) + return {}; + FontMappingUseData ret = std::move( *fontMappingUseData ); + delete fontMappingUseData; + fontMappingUseData = nullptr; + return ret; +} + std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const OUString& rOrigStr, sal_Int32 nMinIndex, sal_Int32 nLen, const Point& rLogicalPos, tools::Long nLogicalWidth, @@ -1358,6 +1410,9 @@ std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const OUString& rOrigStr, pSalLayout->DrawOffset().setX( 1 - nRTLOffset ); } + if(IsTrackingFontMappingUse()) + TrackFontMappingUse(GetFont(), pSalLayout.get()); + return pSalLayout; }