[Libreoffice-commits] core.git: Branch 'libreoffice-7-0' - canvas/source include/vcl vcl/headless vcl/inc vcl/qt5 vcl/source vcl/unx

Caolán McNamara (via logerrit) logerrit at kemper.freedesktop.org
Tue Sep 8 08:22:51 UTC 2020


 canvas/source/cairo/cairo_canvashelper_text.cxx |    4 
 canvas/source/cairo/cairo_textlayout.cxx        |  227 +++++++++++++++++++++++-
 canvas/source/cairo/cairo_textlayout.hxx        |    5 
 include/vcl/outdev.hxx                          |   15 +
 include/vcl/sysdata.hxx                         |   43 ++++
 include/vcl/vcllayout.hxx                       |    3 
 vcl/headless/svptext.cxx                        |   10 +
 vcl/inc/headless/svpgdi.hxx                     |    1 
 vcl/inc/qt5/Qt5Graphics.hxx                     |    1 
 vcl/inc/salgdi.hxx                              |    6 
 vcl/inc/sallayout.hxx                           |    6 
 vcl/inc/textrender.hxx                          |    5 
 vcl/inc/unx/freetypetextrender.hxx              |    3 
 vcl/inc/unx/genpspgraphics.h                    |    2 
 vcl/inc/unx/glyphcache.hxx                      |    3 
 vcl/inc/unx/salgdi.h                            |    1 
 vcl/qt5/Qt5Graphics.cxx                         |    5 
 vcl/source/control/button.cxx                   |    1 
 vcl/source/gdi/sallayout.cxx                    |    9 
 vcl/source/outdev/font.cxx                      |   17 +
 vcl/source/outdev/text.cxx                      |   61 ++++++
 vcl/unx/generic/gdi/font.cxx                    |    9 
 vcl/unx/generic/gdi/freetypetextrender.cxx      |   23 ++
 vcl/unx/generic/print/genpspgraphics.cxx        |    5 
 24 files changed, 448 insertions(+), 17 deletions(-)

New commits:
commit ee18059ed6402eb0725048b3dd406852120a9faf
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Mon Sep 7 19:53:02 2020 +0100
Commit:     Xisco Fauli <xiscofauli at libreoffice.org>
CommitDate: Tue Sep 8 10:22:17 2020 +0200

    tdf#136545 revert cairo canvas uses cairo for text rendering already
    
    This was the fallback path, so the problem must already exist in the uncommon
    fallback case. I think I know the best approach to take, but for the 7-0 case
    be conservative and restore the historic state.
    
    this reverts 770892a387361067d23ab08ed38690c50b8b9395 and associated
    code removal
    
    Change-Id: I0e61d934e4dae03442ca5910f802199a1d3d53f4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102197
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <xiscofauli at libreoffice.org>

diff --git a/canvas/source/cairo/cairo_canvashelper_text.cxx b/canvas/source/cairo/cairo_canvashelper_text.cxx
index 830388775670..3b4d161417bd 100644
--- a/canvas/source/cairo/cairo_canvashelper_text.cxx
+++ b/canvas/source/cairo/cairo_canvashelper_text.cxx
@@ -254,7 +254,7 @@ namespace cairocanvas
             mpVirtualDevice->SetLayoutMode( nLayoutMode );
 
             rtl::Reference pTextLayout( new TextLayout(text, textDirection, 0, CanvasFont::Reference(dynamic_cast< CanvasFont* >( xFont.get() )), mpSurfaceProvider) );
-            pTextLayout->draw(*mpVirtualDevice, aOutpos, viewState, renderState);
+            pTextLayout->draw(mpCairo, *mpVirtualDevice, aOutpos, viewState, renderState);
         }
 
         return uno::Reference< rendering::XCachedPrimitive >(nullptr);
@@ -289,7 +289,7 @@ namespace cairocanvas
                     return uno::Reference< rendering::XCachedPrimitive >(nullptr); // no output necessary
 
                 // TODO(F2): What about the offset scalings?
-                pTextLayout->draw(*mpVirtualDevice, aOutpos, viewState, renderState);
+                pTextLayout->draw(mpCairo, *mpVirtualDevice, aOutpos, viewState, renderState);
             }
         }
         else
diff --git a/canvas/source/cairo/cairo_textlayout.cxx b/canvas/source/cairo/cairo_textlayout.cxx
index d81a739b4956..32a62c5ea790 100644
--- a/canvas/source/cairo/cairo_textlayout.cxx
+++ b/canvas/source/cairo/cairo_textlayout.cxx
@@ -77,6 +77,11 @@ namespace cairocanvas
             // as required at the API spec
             rOutDev.SetLayoutMode( nLayoutMode | ComplexTextLayoutFlags::TextOriginLeft );
         }
+
+        bool compareFallbacks(const SystemGlyphData&rA, const SystemGlyphData &rB)
+        {
+            return rA.fallbacklevel < rB.fallbacklevel;
+        }
     }
 
     TextLayout::TextLayout( const rendering::StringContext&     aText,
@@ -256,6 +261,33 @@ namespace cairocanvas
         return maText;
     }
 
+  /**
+   * TextLayout::isCairoRenderable
+   *
+   * Features currently not supported by Cairo (VCL rendering is used as fallback):
+   * - vertical glyphs
+   *
+   * @return true, if text/font can be rendered with cairo
+   **/
+    bool TextLayout::isCairoRenderable(SystemFontData aSysFontData) const
+    {
+#if defined CAIRO_HAS_FT_FONT
+        // is font usable?
+        if (!aSysFontData.nFontId)
+            return false;
+#endif
+
+        // vertical glyph rendering is not supported in cairo for now
+        if (aSysFontData.bVerticalCharacterType)
+        {
+            SAL_WARN("canvas.cairo", ":cairocanvas::TextLayout::isCairoRenderable(): Vertical Character Style not supported");
+            return false;
+        }
+
+        return true;
+    }
+
+
   /**
    * TextLayout::draw
    *
@@ -265,30 +297,207 @@ namespace cairocanvas
    * Note: some text effects are not rendered due to lacking generic canvas or cairo canvas
    *       implementation. See issues 92657, 92658, 92659, 92660, 97529
    **/
-    void TextLayout::draw( OutputDevice&                 rOutDev,
+    void TextLayout::draw( CairoSharedPtr const &        pSCairo,
+                           OutputDevice&                 rOutDev,
                            const Point&                  rOutpos,
                            const rendering::ViewState&   viewState,
                            const rendering::RenderState& renderState ) const
     {
         ::osl::MutexGuard aGuard( m_aMutex );
+        SystemTextLayoutData aSysLayoutData;
         setupLayoutMode( rOutDev, mnTextDirection );
 
+        // TODO(P2): cache that
         std::unique_ptr< long []> aOffsets(new long[maLogicalAdvancements.getLength()]);
 
         if( maLogicalAdvancements.hasElements() )
+        {
             setupTextOffsets( aOffsets.get(), maLogicalAdvancements, viewState, renderState );
 
-        if (maLogicalAdvancements.hasElements())
+            // TODO(F3): ensure correct length and termination for DX
+            // array (last entry _must_ contain the overall width)
+        }
+
+        aSysLayoutData = rOutDev.GetSysTextLayoutData(rOutpos, maText.Text,
+                                                      ::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
+                                                      ::canvas::tools::numeric_cast<sal_uInt16>(maText.Length),
+                                                      maLogicalAdvancements.hasElements() ? aOffsets.get() : nullptr);
+
+        // Sort them so that all glyphs on the same glyph fallback level are consecutive
+        std::sort(aSysLayoutData.rGlyphData.begin(), aSysLayoutData.rGlyphData.end(), compareFallbacks);
+        bool bCairoRenderable = true;
+
+        //Pull all the fonts we need to render the text
+        typedef std::pair<SystemFontData,int> FontLevel;
+        std::vector<FontLevel> aFontData;
+        for (auto const& glyph : aSysLayoutData.rGlyphData)
         {
-            rOutDev.DrawTextArray( rOutpos, maText.Text, aOffsets.get(),
-                                   ::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
-                                   ::canvas::tools::numeric_cast<sal_uInt16>(maText.Length) );
+            if( aFontData.empty() || glyph.fallbacklevel != aFontData.back().second )
+            {
+                aFontData.emplace_back(rOutDev.GetSysFontData(glyph.fallbacklevel),
+                                              glyph.fallbacklevel);
+                if( !isCairoRenderable(aFontData.back().first) )
+                {
+                    bCairoRenderable = false;
+                    SAL_INFO("canvas.cairo", ":cairocanvas::TextLayout::draw(S,O,p,v,r): VCL FALLBACK " <<
+                             (maLogicalAdvancements.hasElements() ? "ADV " : "") <<
+                             (aFontData.back().first.bAntialias ? "AA " : "") <<
+                             (aFontData.back().first.bFakeBold ? "FB " : "") <<
+                             (aFontData.back().first.bFakeItalic ? "FI " : "") <<
+                             " - " <<
+                             maText.Text.copy( maText.StartPosition, maText.Length));
+                    break;
+                }
+            }
         }
-        else
+
+        // The ::GetSysTextLayoutData(), i.e. layouting of text to glyphs can change the font being used.
+        // The fallback checks need to be done after final font is known.
+        if (!bCairoRenderable)    // VCL FALLBACKS
         {
-            rOutDev.DrawText( rOutpos, maText.Text,
-                              ::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
-                              ::canvas::tools::numeric_cast<sal_uInt16>(maText.Length) );
+            if (maLogicalAdvancements.hasElements())        // VCL FALLBACK - with glyph advances
+            {
+                rOutDev.DrawTextArray( rOutpos, maText.Text, aOffsets.get(),
+                                       ::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
+                                       ::canvas::tools::numeric_cast<sal_uInt16>(maText.Length) );
+                return;
+            }
+            else                                               // VCL FALLBACK - without advances
+            {
+                rOutDev.DrawText( rOutpos, maText.Text,
+                                  ::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
+                                  ::canvas::tools::numeric_cast<sal_uInt16>(maText.Length) );
+                return;
+            }
+        }
+
+        if (aSysLayoutData.rGlyphData.empty())
+            return; //??? false?
+
+        /**
+         * Setup platform independent glyph vector into cairo-based glyphs vector.
+         **/
+
+        // Loop through the fonts used and render the matching glyphs for each
+        for (auto const& elemFontData : aFontData)
+        {
+            const SystemFontData &rSysFontData = elemFontData.first;
+
+            // setup glyphs
+            std::vector<cairo_glyph_t> cairo_glyphs;
+            cairo_glyphs.reserve( 256 );
+
+            for (auto const& systemGlyph : aSysLayoutData.rGlyphData)
+            {
+                if( systemGlyph.fallbacklevel != elemFontData.second )
+                    continue;
+
+                cairo_glyph_t aGlyph;
+                aGlyph.index = systemGlyph.index;
+                aGlyph.x = systemGlyph.x;
+                aGlyph.y = systemGlyph.y;
+                cairo_glyphs.push_back(aGlyph);
+            }
+
+            if (cairo_glyphs.empty())
+                continue;
+
+            const vcl::Font& aFont = rOutDev.GetFont();
+            long nWidth = aFont.GetAverageFontWidth();
+            long nHeight = aFont.GetFontHeight();
+            if (nWidth == 0)
+                nWidth = nHeight;
+            if (nWidth == 0 || nHeight == 0)
+                continue;
+
+            /**
+             * Setup font
+             **/
+            cairo_font_face_t* font_face = nullptr;
+
+#if defined CAIRO_HAS_FT_FONT
+            font_face = cairo_ft_font_face_create_for_ft_face(static_cast<FT_Face>(rSysFontData.nFontId),
+                                                              rSysFontData.nFontFlags);
+#else
+# error Native API needed.
+#endif
+
+            cairo_set_font_face( pSCairo.get(), font_face);
+
+            // create default font options. cairo_get_font_options() does not retrieve the surface defaults,
+            // only what has been set before with cairo_set_font_options()
+            cairo_font_options_t* options = cairo_font_options_create();
+            if (rSysFontData.bAntialias)
+            {
+                // CAIRO_ANTIALIAS_GRAY provides more similar result to VCL Canvas,
+                // so we're not using CAIRO_ANTIALIAS_SUBPIXEL
+                cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_GRAY);
+            }
+            cairo_set_font_options( pSCairo.get(), options);
+
+            // Font color
+            Color aTextColor = rOutDev.GetTextColor();
+            cairo_set_source_rgb(pSCairo.get(),
+                                 aTextColor.GetRed()/255.0,
+                                 aTextColor.GetGreen()/255.0,
+                                 aTextColor.GetBlue()/255.0);
+
+            // Font rotation and scaling
+            cairo_matrix_t m;
+
+            cairo_matrix_init_identity(&m);
+
+            if (aSysLayoutData.orientation)
+                cairo_matrix_rotate(&m, (3600 - aSysLayoutData.orientation) * M_PI / 1800.0);
+
+            cairo_matrix_scale(&m, nWidth, nHeight);
+
+            //faux italics
+            if (rSysFontData.bFakeItalic)
+                m.xy = -m.xx * 0x6000 / 0x10000;
+
+            cairo_set_font_matrix(pSCairo.get(), &m);
+
+            SAL_INFO(
+                "canvas.cairo",
+                "Size:(" << aFont.GetAverageFontWidth() << "," << aFont.GetFontHeight()
+                    << "), Pos (" << rOutpos.X() << "," << rOutpos.Y()
+                    << "), G("
+                    << (!cairo_glyphs.empty() ? cairo_glyphs[0].index : -1)
+                    << ","
+                    << (cairo_glyphs.size() > 1 ? cairo_glyphs[1].index : -1)
+                    << ","
+                    << (cairo_glyphs.size() > 2 ? cairo_glyphs[2].index : -1)
+                    << ") " << (maLogicalAdvancements.hasElements() ? "ADV " : "")
+                    << (rSysFontData.bAntialias ? "AA " : "")
+                    << (rSysFontData.bFakeBold ? "FB " : "")
+                    << (rSysFontData.bFakeItalic ? "FI " : "") << " || Name:"
+                    << aFont.GetFamilyName() << " - "
+                    << maText.Text.copy(maText.StartPosition, maText.Length));
+
+            cairo_show_glyphs(pSCairo.get(), cairo_glyphs.data(), cairo_glyphs.size());
+
+            //faux bold
+            if (rSysFontData.bFakeBold)
+            {
+                double bold_dx = 0.5 * sqrt( 0.7 * aFont.GetFontHeight() );
+                int total_steps = 1 * static_cast<int>(bold_dx + 0.5);
+
+                // loop to draw the text for every half pixel of displacement
+                for (int nSteps = 0; nSteps < total_steps; nSteps++)
+                {
+                    for(cairo_glyph_t & cairo_glyph : cairo_glyphs)
+                    {
+                        cairo_glyph.x += (bold_dx * nSteps / total_steps) / 4;
+                        cairo_glyph.y -= (bold_dx * nSteps / total_steps) / 4;
+                    }
+                    cairo_show_glyphs(pSCairo.get(), cairo_glyphs.data(), cairo_glyphs.size());
+                }
+                SAL_INFO("canvas.cairo",":cairocanvas::TextLayout::draw(S,O,p,v,r): FAKEBOLD - dx:" << static_cast<int>(bold_dx));
+            }
+
+            cairo_font_face_destroy(font_face);
+            cairo_font_options_destroy(options);
         }
     }
 
diff --git a/canvas/source/cairo/cairo_textlayout.hxx b/canvas/source/cairo/cairo_textlayout.hxx
index 6254108a50ad..b5ba2d84bb21 100644
--- a/canvas/source/cairo/cairo_textlayout.hxx
+++ b/canvas/source/cairo/cairo_textlayout.hxx
@@ -82,7 +82,8 @@ namespace cairocanvas
         virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
         virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
 
-        void draw( OutputDevice&                                   rOutDev,
+        void draw( ::cairo::CairoSharedPtr const &                 pSCairo,
+                   OutputDevice&                                   rOutDev,
                    const Point&                                    rOutpos,
                    const css::rendering::ViewState&   viewState,
                    const css::rendering::RenderState& renderState ) const;
@@ -101,6 +102,8 @@ namespace cairocanvas
         CanvasFont::Reference                      mpFont;
         SurfaceProviderRef                         mpRefDevice;
         sal_Int8                                   mnTextDirection;
+
+        bool isCairoRenderable(SystemFontData aSysFontData) const;
     };
 
 }
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 372d1a7e4830..26a2920b86e1 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -55,6 +55,8 @@
 struct ImplOutDevData;
 class LogicalFontInstance;
 struct SystemGraphicsData;
+struct SystemFontData;
+struct SystemTextLayoutData;
 class ImplFontCache;
 class PhysicalFontCollection;
 class ImplDeviceFontList;
@@ -1231,6 +1233,15 @@ public:
 
     bool GetFontFeatures(std::vector<vcl::font::Feature>& rFontFeatures) const;
 
+
+    /** Retrieve detailed font information in platform independent structure
+
+        @param  nFallbacklevel      Fallback font level (0 = best matching font)
+
+        @return SystemFontData
+     */
+    SystemFontData              GetSysFontData( int nFallbacklevel ) const;
+
     SAL_DLLPRIVATE void         ImplGetEmphasisMark( tools::PolyPolygon& rPolyPoly, bool& rPolyLine, tools::Rectangle& rRect1, tools::Rectangle& rRect2,
                                                      long& rYOff, long& rWidth, FontEmphasisMark eEmphasis, long nHeight );
     SAL_DLLPRIVATE static FontEmphasisMark
@@ -1320,6 +1331,10 @@ private:
 
 public:
 
+    SystemTextLayoutData        GetSysTextLayoutData( const Point& rStartPt, const OUString& rStr,
+                                                      sal_Int32 nIndex, sal_Int32 nLen,
+                                                      const long* pDXAry ) const;
+
     // tells whether this output device is RTL in an LTR UI or LTR in a RTL UI
     SAL_DLLPRIVATE bool         ImplIsAntiparallel() const ;
     SAL_DLLPRIVATE void         ReMirror( Point &rPoint ) const;
diff --git a/include/vcl/sysdata.hxx b/include/vcl/sysdata.hxx
index 1be73fef8856..3152fa3bed56 100644
--- a/include/vcl/sysdata.hxx
+++ b/include/vcl/sysdata.hxx
@@ -185,6 +185,49 @@ struct SystemWindowData
 #endif
 };
 
+struct SystemGlyphData
+{
+    sal_uInt32           index;
+    double               x;
+    double               y;
+    int                  fallbacklevel;
+};
+
+#if ENABLE_CAIRO_CANVAS
+
+struct SystemFontData
+{
+#if defined( UNX )
+    void*           nFontId;        // native font id
+    int             nFontFlags;     // native font flags
+#endif
+    bool            bFakeBold;      // Does this font need faking the bold style
+    bool            bFakeItalic;    // Does this font need faking the italic style
+    bool            bAntialias;     // Should this font be antialiased
+    bool            bVerticalCharacterType;      // Is the font using vertical character type
+
+    SystemFontData()
+        :
+#if defined( UNX )
+        nFontId( nullptr ),
+        nFontFlags( 0 ),
+#endif
+        bFakeBold( false ),
+        bFakeItalic( false ),
+        bAntialias( true ),
+        bVerticalCharacterType( false )
+    {
+    }
+};
+
+#endif // ENABLE_CAIRO_CANVAS
+
+struct SystemTextLayoutData
+{
+    std::vector<SystemGlyphData> rGlyphData;    // glyph data
+    int orientation;   // Text orientation
+};
+
 #endif // INCLUDED_VCL_SYSDATA_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/vcl/vcllayout.hxx b/include/vcl/vcllayout.hxx
index 1d6aa9f174f5..99884011e928 100644
--- a/include/vcl/vcllayout.hxx
+++ b/include/vcl/vcllayout.hxx
@@ -89,7 +89,8 @@ public:
 
     // methods using glyph indexing
     virtual bool    GetNextGlyph(const GlyphItem** pGlyph, Point& rPos, int& nStart,
-                                 const PhysicalFontFace** pFallbackFont = nullptr) const = 0;
+                                 const PhysicalFontFace** pFallbackFont = nullptr,
+                                 int* const pFallbackLevel = nullptr) const = 0;
     virtual bool GetOutline(basegfx::B2DPolyPolygonVector&) const;
     bool GetBoundRect(tools::Rectangle&) const;
 
diff --git a/vcl/headless/svptext.cxx b/vcl/headless/svptext.cxx
index f44373f5acc1..e4b625b365cb 100644
--- a/vcl/headless/svptext.cxx
+++ b/vcl/headless/svptext.cxx
@@ -22,6 +22,7 @@
 #include <vcl/fontcharmap.hxx>
 #include <basegfx/range/b2ibox.hxx>
 #include <headless/svpgdi.hxx>
+#include <config_cairo_canvas.h>
 #include <impfontmetricdata.hxx>
 #include <sallayout.hxx>
 
@@ -108,4 +109,13 @@ void SvpSalGraphics::SetTextColor( Color nColor )
     m_aTextRenderImpl.SetTextColor(nColor);
 }
 
+#if ENABLE_CAIRO_CANVAS
+
+SystemFontData SvpSalGraphics::GetSysFontData( int nFallbacklevel ) const
+{
+    return m_aTextRenderImpl.GetSysFontData(nFallbacklevel);
+}
+
+#endif // ENABLE_CAIRO_CANVAS
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx
index 3cffdcd2a1c0..3d1617d07100 100644
--- a/vcl/inc/headless/svpgdi.hxx
+++ b/vcl/inc/headless/svpgdi.hxx
@@ -273,6 +273,7 @@ public:
     virtual cairo::SurfaceSharedPtr CreateSurface(const OutputDevice& rRefDevice, int x, int y, int width, int height) const override;
     virtual cairo::SurfaceSharedPtr CreateBitmapSurface(const OutputDevice& rRefDevice, const BitmapSystemData& rData, const Size& rSize) const override;
     virtual css::uno::Any   GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize) const override;
+    virtual SystemFontData  GetSysFontData( int nFallbacklevel ) const override;
 #endif // ENABLE_CAIRO_CANVAS
 
     cairo_t*                getCairoContext(bool bXorModeAllowed) const;
diff --git a/vcl/inc/qt5/Qt5Graphics.hxx b/vcl/inc/qt5/Qt5Graphics.hxx
index 1515783f6076..bc4870ee7e18 100644
--- a/vcl/inc/qt5/Qt5Graphics.hxx
+++ b/vcl/inc/qt5/Qt5Graphics.hxx
@@ -92,6 +92,7 @@ public:
                                                         const Size& rSize) const override;
     virtual css::uno::Any GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface,
                                                  const basegfx::B2ISize& rSize) const override;
+    virtual SystemFontData GetSysFontData(int nFallbacklevel) const override;
 #endif // ENABLE_CAIRO_CANVAS
 
     // GDI
diff --git a/vcl/inc/salgdi.hxx b/vcl/inc/salgdi.hxx
index d2b92c65110f..8d8e4c96dbf3 100644
--- a/vcl/inc/salgdi.hxx
+++ b/vcl/inc/salgdi.hxx
@@ -48,6 +48,10 @@ class OutputDevice;
 class FreetypeFont;
 struct SystemGraphicsData;
 
+#if ENABLE_CAIRO_CANVAS
+struct SystemFontData;
+#endif // ENABLE_CAIRO_CANVAS
+
 namespace basegfx {
     class B2DVector;
     class B2DPolygon;
@@ -431,6 +435,8 @@ public:
     virtual cairo::SurfaceSharedPtr CreateBitmapSurface(const OutputDevice& rRefDevice, const BitmapSystemData& rData, const Size& rSize) const = 0;
     virtual css::uno::Any       GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize) const = 0;
 
+    virtual SystemFontData      GetSysFontData( int nFallbacklevel ) const = 0;
+
 #endif // ENABLE_CAIRO_CANVAS
 
 protected:
diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index 9ab526365ea7..e94b4c20531e 100644
--- a/vcl/inc/sallayout.hxx
+++ b/vcl/inc/sallayout.hxx
@@ -130,7 +130,8 @@ public:
     DeviceCoordinate FillDXArray(DeviceCoordinate* pDXArray) const override;
     void            GetCaretPositions(int nArraySize, long* pCaretXArray) const override;
     bool            GetNextGlyph(const GlyphItem** pGlyph, Point& rPos, int& nStart,
-                                 const PhysicalFontFace** pFallbackFont = nullptr) const override;
+                                 const PhysicalFontFace** pFallbackFont = nullptr,
+                                 int* const pFallbackLevel = nullptr) const override;
     bool            GetOutline(basegfx::B2DPolyPolygonVector&) const override;
     bool            IsKashidaPosValid(int nCharPos) const override;
 
@@ -183,7 +184,8 @@ public:
         { return m_GlyphItems.Impl()->GetFont(); }
 
     bool            GetNextGlyph(const GlyphItem** pGlyph, Point& rPos, int& nStart,
-                                 const PhysicalFontFace** pFallbackFont = nullptr) const override;
+                                 const PhysicalFontFace** pFallbackFont = nullptr,
+                                 int* const pFallbackLevel = nullptr) const override;
 
 private:
     // for glyph+font+script fallback
diff --git a/vcl/inc/textrender.hxx b/vcl/inc/textrender.hxx
index f1cbfd8990b5..1aec8fba2301 100644
--- a/vcl/inc/textrender.hxx
+++ b/vcl/inc/textrender.hxx
@@ -22,6 +22,8 @@
 
 #include "salgdi.hxx"
 
+#include <config_cairo_canvas.h>
+
 class ImplLayoutArgs;
 class ImplFontMetricData;
 class PhysicalFontCollection;
@@ -62,6 +64,9 @@ public:
     virtual std::unique_ptr<GenericSalLayout>
                                     GetTextLayout(int nFallbackLevel) = 0;
     virtual void                    DrawTextLayout(const GenericSalLayout&, const SalGraphics&) = 0;
+#if ENABLE_CAIRO_CANVAS
+    virtual SystemFontData          GetSysFontData( int nFallbackLevel ) const = 0;
+#endif // ENABLE_CAIRO_CANVAS
 };
 
 #endif
diff --git a/vcl/inc/unx/freetypetextrender.hxx b/vcl/inc/unx/freetypetextrender.hxx
index 9c4960e0f36c..ccc1db0157d2 100644
--- a/vcl/inc/unx/freetypetextrender.hxx
+++ b/vcl/inc/unx/freetypetextrender.hxx
@@ -65,6 +65,9 @@ public:
 
     virtual std::unique_ptr<GenericSalLayout>
                                 GetTextLayout(int nFallbackLevel) override;
+#if ENABLE_CAIRO_CANVAS
+    virtual SystemFontData      GetSysFontData( int nFallbackLevel ) const override;
+#endif
 };
 
 #endif
diff --git a/vcl/inc/unx/genpspgraphics.h b/vcl/inc/unx/genpspgraphics.h
index c02d6aa21fe3..b696618c75ca 100644
--- a/vcl/inc/unx/genpspgraphics.h
+++ b/vcl/inc/unx/genpspgraphics.h
@@ -203,6 +203,8 @@ public:
     virtual cairo::SurfaceSharedPtr CreateSurface(const OutputDevice& rRefDevice, int x, int y, int width, int height) const override;
     virtual cairo::SurfaceSharedPtr CreateBitmapSurface(const OutputDevice& rRefDevice, const BitmapSystemData& rData, const Size& rSize) const override;
     virtual css::uno::Any   GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize) const override;
+
+    virtual SystemFontData  GetSysFontData( int nFallbacklevel ) const override;
 #endif // ENABLE_CAIRO_CANVAS
 };
 
diff --git a/vcl/inc/unx/glyphcache.hxx b/vcl/inc/unx/glyphcache.hxx
index 993a0cf49a22..983a6ec0382e 100644
--- a/vcl/inc/unx/glyphcache.hxx
+++ b/vcl/inc/unx/glyphcache.hxx
@@ -116,6 +116,7 @@ public:
     int                     GetFontFaceVariation() const;
     bool                    TestFont() const { return mbFaceOk;}
     FT_Face                 GetFtFace() const;
+    int                     GetLoadFlags() const { return (mnLoadFlags & ~FT_LOAD_IGNORE_TRANSFORM); }
     const FontConfigFontOptions* GetFontOptions() const;
     bool                    NeedsArtificialBold() const { return mbArtBold; }
     bool                    NeedsArtificialItalic() const { return mbArtItalic; }
@@ -129,6 +130,8 @@ public:
     bool                    GetGlyphOutline(sal_GlyphId, basegfx::B2DPolyPolygon&, bool) const;
     bool                    GetAntialiasAdvice() const;
 
+    FreetypeFontInstance&   GetFontInstance() const { return mrFontInstance; }
+
     void                    SetFontVariationsOnHBFont(hb_font_t* pHbFace) const;
 
     // tdf#127189 FreeType <= 2.8 will fail to render stretched horizontal brace glyphs
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index caef46a1a2e8..4216b703c14e 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -264,6 +264,7 @@ public:
     virtual cairo::SurfaceSharedPtr CreateSurface(const OutputDevice& rRefDevice, int x, int y, int width, int height) const override;
     virtual cairo::SurfaceSharedPtr CreateBitmapSurface(const OutputDevice& rRefDevice, const BitmapSystemData& rData, const Size& rSize) const override;
     virtual css::uno::Any           GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize) const override;
+    virtual SystemFontData          GetSysFontData( int nFallbackLevel ) const override;
 
     void clipRegion(cairo_t* cr);
 #endif // ENABLE_CAIRO_CANVAS
diff --git a/vcl/qt5/Qt5Graphics.cxx b/vcl/qt5/Qt5Graphics.cxx
index 257e0f436334..34f610812d45 100644
--- a/vcl/qt5/Qt5Graphics.cxx
+++ b/vcl/qt5/Qt5Graphics.cxx
@@ -104,6 +104,11 @@ css::uno::Any Qt5Graphics::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& /*rSu
     return css::uno::Any();
 }
 
+SystemFontData Qt5Graphics::GetSysFontData(int /*nFallbacklevel*/) const
+{
+    return SystemFontData();
+}
+
 #endif
 
 void Qt5Graphics::handleDamage(const tools::Rectangle& rDamagedRegion)
diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx
index 1f9e2573e144..7e0a1bfa81fa 100644
--- a/vcl/source/control/button.cxx
+++ b/vcl/source/control/button.cxx
@@ -1528,6 +1528,7 @@ void PushButton::SetState( TriState eState )
 void PushButton::statusChanged(const css::frame::FeatureStateEvent& rEvent)
 {
     Button::statusChanged(rEvent);
+    fprintf(stderr, "State is %d\n", rEvent.State.has<bool>());
     if (rEvent.State.has<bool>())
         SetPressed(rEvent.State.get<bool>());
 }
diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
index 55aa145095be..eaa016ed1927 100644
--- a/vcl/source/gdi/sallayout.cxx
+++ b/vcl/source/gdi/sallayout.cxx
@@ -895,7 +895,7 @@ sal_Int32 GenericSalLayout::GetTextBreak( DeviceCoordinate nMaxWidth, DeviceCoor
 
 bool GenericSalLayout::GetNextGlyph(const GlyphItem** pGlyph,
                                     Point& rPos, int& nStart,
-                                    const PhysicalFontFace**) const
+                                    const PhysicalFontFace**, int* const pFallbackLevel) const
 {
     std::vector<GlyphItem>::const_iterator pGlyphIter = m_GlyphItems.Impl()->begin();
     std::vector<GlyphItem>::const_iterator pGlyphIterEnd = m_GlyphItems.Impl()->end();
@@ -918,6 +918,8 @@ bool GenericSalLayout::GetNextGlyph(const GlyphItem** pGlyph,
 
     // update return data with glyph info
     *pGlyph = &(*pGlyphIter);
+    if (pFallbackLevel)
+        *pFallbackLevel = 0;
     ++nStart;
 
     // calculate absolute position in pixel units
@@ -1504,7 +1506,8 @@ void MultiSalLayout::GetCaretPositions( int nMaxIndex, long* pCaretXArray ) cons
 
 bool MultiSalLayout::GetNextGlyph(const GlyphItem** pGlyph,
                                   Point& rPos, int& nStart,
-                                  const PhysicalFontFace** pFallbackFont) const
+                                  const PhysicalFontFace** pFallbackFont,
+                                  int* const pFallbackLevel) const
 {
     // NOTE: nStart is tagged with current font index
     int nLevel = static_cast<unsigned>(nStart) >> GF_FONTSHIFT;
@@ -1520,6 +1523,8 @@ bool MultiSalLayout::GetNextGlyph(const GlyphItem** pGlyph,
             nStart |= nFontTag;
             if (pFallbackFont)
                 *pFallbackFont = pFontFace;
+            if (pFallbackLevel)
+                *pFallbackLevel = nLevel;
             rPos += maDrawBase;
             rPos += maDrawOffset;
             return true;
diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx
index b7d8bfeeba7c..59ce4ef52a99 100644
--- a/vcl/source/outdev/font.cxx
+++ b/vcl/source/outdev/font.cxx
@@ -278,6 +278,23 @@ bool OutputDevice::GetFontCapabilities( vcl::FontCapabilities& rFontCapabilities
     return mpGraphics->GetFontCapabilities(rFontCapabilities);
 }
 
+#if ENABLE_CAIRO_CANVAS
+
+SystemFontData OutputDevice::GetSysFontData(int nFallbacklevel) const
+{
+    SystemFontData aSysFontData;
+
+    if (!mpGraphics)
+        (void) AcquireGraphics();
+
+    if (mpGraphics)
+        aSysFontData = mpGraphics->GetSysFontData(nFallbacklevel);
+
+    return aSysFontData;
+}
+
+#endif // ENABLE_CAIRO_CANVAS
+
 void OutputDevice::ImplGetEmphasisMark( tools::PolyPolygon& rPolyPoly, bool& rPolyLine,
                                         tools::Rectangle& rRect1, tools::Rectangle& rRect2,
                                         long& rYOff, long& rWidth,
diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index b11e1e480503..34db8e6299c1 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -2254,6 +2254,67 @@ OUString OutputDevice::GetNonMnemonicString( const OUString& rStr, sal_Int32& rM
     return aStr;
 }
 
+/** OutputDevice::GetSysTextLayoutData
+ *
+ * @param rStartPt Start point of the text
+ * @param rStr Text string that will be transformed into layout of glyphs
+ * @param nIndex Position in the string from where layout will be done
+ * @param nLen Length of the string
+ * @param pDXAry Custom layout adjustment data
+ *
+ * Export finalized glyph layout data as platform independent SystemTextLayoutData
+ * (see vcl/inc/vcl/sysdata.hxx)
+ *
+ * Only parameters rStartPt and rStr are mandatory, the rest is optional
+ * (default values will be used)
+ *
+ * @return SystemTextLayoutData
+ **/
+SystemTextLayoutData OutputDevice::GetSysTextLayoutData(const Point& rStartPt, const OUString& rStr, sal_Int32 nIndex, sal_Int32 nLen,
+                                                        const long* pDXAry) const
+{
+    if( (nLen < 0) || (nIndex + nLen >= rStr.getLength()))
+    {
+        nLen = rStr.getLength() - nIndex;
+    }
+
+    SystemTextLayoutData aSysLayoutData;
+    aSysLayoutData.rGlyphData.reserve( 256 );
+    aSysLayoutData.orientation = 0;
+
+    if ( mpMetaFile )
+    {
+        if (pDXAry)
+            mpMetaFile->AddAction( new MetaTextArrayAction( rStartPt, rStr, pDXAry, nIndex, nLen ) );
+        else
+            mpMetaFile->AddAction( new MetaTextAction( rStartPt, rStr, nIndex, nLen ) );
+    }
+
+    if ( !IsDeviceOutputNecessary() ) return aSysLayoutData;
+
+    std::unique_ptr<SalLayout> pLayout = ImplLayout(rStr, nIndex, nLen, rStartPt, 0, pDXAry);
+
+    if ( !pLayout ) return aSysLayoutData;
+
+    // setup glyphs
+    Point aPos;
+    const GlyphItem* pGlyph;
+    int nStart = 0;
+    SystemGlyphData aSystemGlyph;
+    while (pLayout->GetNextGlyph(&pGlyph, aPos, nStart, nullptr, &aSystemGlyph.fallbacklevel))
+    {
+        aSystemGlyph.index = pGlyph->glyphId();
+        aSystemGlyph.x = aPos.X();
+        aSystemGlyph.y = aPos.Y();
+        aSysLayoutData.rGlyphData.push_back(aSystemGlyph);
+    }
+
+    // Get font data
+    aSysLayoutData.orientation = pLayout->GetOrientation();
+
+    return aSysLayoutData;
+}
+
 bool OutputDevice::GetTextBoundRect( tools::Rectangle& rRect,
                                          const OUString& rStr, sal_Int32 nBase,
                                          sal_Int32 nIndex, sal_Int32 nLen,
diff --git a/vcl/unx/generic/gdi/font.cxx b/vcl/unx/generic/gdi/font.cxx
index 5a6f04fd856f..ede4d953c48e 100644
--- a/vcl/unx/generic/gdi/font.cxx
+++ b/vcl/unx/generic/gdi/font.cxx
@@ -80,6 +80,15 @@ std::unique_ptr<GenericSalLayout> X11SalGraphics::GetTextLayout(int nFallbackLev
     return mxTextRenderImpl->GetTextLayout(nFallbackLevel);
 }
 
+#if ENABLE_CAIRO_CANVAS
+
+SystemFontData X11SalGraphics::GetSysFontData( int nFallbackLevel ) const
+{
+    return mxTextRenderImpl->GetSysFontData(nFallbackLevel);
+}
+
+#endif
+
 bool X11SalGraphics::CreateFontSubset(
                                    const OUString& rToFile,
                                    const PhysicalFontFace* pFont,
diff --git a/vcl/unx/generic/gdi/freetypetextrender.cxx b/vcl/unx/generic/gdi/freetypetextrender.cxx
index b364406f1e1d..3d94da30440a 100644
--- a/vcl/unx/generic/gdi/freetypetextrender.cxx
+++ b/vcl/unx/generic/gdi/freetypetextrender.cxx
@@ -153,6 +153,29 @@ std::unique_ptr<GenericSalLayout> FreeTypeTextRenderImpl::GetTextLayout(int nFal
     return std::make_unique<GenericSalLayout>(*mpFreetypeFont[nFallbackLevel]);
 }
 
+#if ENABLE_CAIRO_CANVAS
+SystemFontData FreeTypeTextRenderImpl::GetSysFontData( int nFallbackLevel ) const
+{
+    SystemFontData aSysFontData;
+
+    if (nFallbackLevel >= MAX_FALLBACK) nFallbackLevel = MAX_FALLBACK - 1;
+    if (nFallbackLevel < 0 ) nFallbackLevel = 0;
+
+    if (mpFreetypeFont[nFallbackLevel])
+    {
+        FreetypeFont& rFreetypeFont = mpFreetypeFont[nFallbackLevel]->GetFreetypeFont();
+        aSysFontData.nFontId = rFreetypeFont.GetFtFace();
+        aSysFontData.nFontFlags = rFreetypeFont.GetLoadFlags();
+        aSysFontData.bFakeBold = rFreetypeFont.NeedsArtificialBold();
+        aSysFontData.bFakeItalic = rFreetypeFont.NeedsArtificialItalic();
+        aSysFontData.bAntialias = rFreetypeFont.GetAntialiasAdvice();
+        aSysFontData.bVerticalCharacterType = mpFreetypeFont[nFallbackLevel]->GetFontSelectPattern().mbVertical;
+    }
+
+    return aSysFontData;
+}
+#endif
+
 bool FreeTypeTextRenderImpl::CreateFontSubset(
                                    const OUString& rToFile,
                                    const PhysicalFontFace* pFont,
diff --git a/vcl/unx/generic/print/genpspgraphics.cxx b/vcl/unx/generic/print/genpspgraphics.cxx
index 03319d1acf53..235f45eb83a4 100644
--- a/vcl/unx/generic/print/genpspgraphics.cxx
+++ b/vcl/unx/generic/print/genpspgraphics.cxx
@@ -944,6 +944,11 @@ css::uno::Any GenPspGraphics::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& /*
     return css::uno::Any();
 }
 
+SystemFontData GenPspGraphics::GetSysFontData( int /* nFallbacklevel */ ) const
+{
+    return SystemFontData();
+}
+
 #endif // ENABLE_CAIRO_CANVAS
 
 bool GenPspGraphics::supportsOperation( OutDevSupportType ) const


More information about the Libreoffice-commits mailing list