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;
 }
 

Reply via email to