vcl/inc/unx/cairotextrender.hxx         |    8 +++++
 vcl/unx/generic/gdi/cairotextrender.cxx |   50 +++++++++++++++++++++++++++-----
 2 files changed, 51 insertions(+), 7 deletions(-)

New commits:
commit 35e4647689b1663a6e5a13f7ab8aebb0165e4ab2
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Thu Aug 25 13:10:23 2022 +0100
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Thu Aug 25 16:48:46 2022 +0200

    tdf#150507 reenable slight hinting for cairo with 
ResolutionIndependentLayout
    
    it was disabled because of:
    tdf#150145 text appears to have a row of pixels cropped out
    which seems to be the same issue as
    https://gitlab.freedesktop.org/cairo/cairo/-/issues/390
    
    reenable, drop CAIRO_HINT_METRICS_OFF and emulate a proposed solution of
    https://gitlab.freedesktop.org/cairo/cairo/-/merge_requests/235 by
    hacking in a route to disable CAIRO_ROUND_GLYPH_POS_ON
    
    Change-Id: I3c9f982c9737b84fe0ee6b645f507e1226807d60
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138810
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

diff --git a/vcl/inc/unx/cairotextrender.hxx b/vcl/inc/unx/cairotextrender.hxx
index c046b00c9e49..e9a85739827b 100644
--- a/vcl/inc/unx/cairotextrender.hxx
+++ b/vcl/inc/unx/cairotextrender.hxx
@@ -25,9 +25,15 @@
 class GenericSalLayout;
 class SalGraphics;
 typedef struct _cairo cairo_t;
+typedef struct _cairo_font_options cairo_font_options_t;
 
 class VCL_DLLPUBLIC CairoTextRender : public FreeTypeTextRenderImpl
 {
+private:
+    // https://gitlab.freedesktop.org/cairo/cairo/-/merge_requests/235
+    // I don't want to have CAIRO_ROUND_GLYPH_POS_ON set in the cairo
+    // surfaces font_options, but that's private, so tricky to achieve
+    cairo_font_options_t*       mpRoundGlyphPosOffOptions;
 protected:
     virtual cairo_t*            getCairoContext() = 0;
     virtual void                getSurfaceOffset(double& nDX, double& nDY) = 0;
@@ -37,6 +43,8 @@ protected:
 
 public:
     virtual void                DrawTextLayout(const GenericSalLayout&, const 
SalGraphics&) override;
+    CairoTextRender();
+    virtual ~CairoTextRender();
 };
 
 #endif
diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx 
b/vcl/unx/generic/gdi/cairotextrender.cxx
index 1e2e75c01d79..24e5580e9bdb 100644
--- a/vcl/unx/generic/gdi/cairotextrender.cxx
+++ b/vcl/unx/generic/gdi/cairotextrender.cxx
@@ -29,6 +29,11 @@
 
 #include <cairo.h>
 #include <cairo-ft.h>
+#if defined(CAIRO_HAS_SVG_SURFACE)
+#include <cairo-svg.h>
+#elif defined(CAIRO_HAS_PDF_SURFACE)
+#include <cairo-pdf.h>
+#endif
 
 #include <deque>
 
@@ -125,6 +130,36 @@ extern "C"
 }
 #endif
 
+CairoTextRender::CairoTextRender()
+{
+    // https://gitlab.freedesktop.org/cairo/cairo/-/merge_requests/235
+    // I don't want to have CAIRO_ROUND_GLYPH_POS_ON set in the cairo surfaces
+    // font_options when trying subpixel rendering, but that's a private
+    // feature of cairo_font_options_t, so tricky to achieve. Hack this by
+    // getting the font options of a backend known to set this private feature
+    // to CAIRO_ROUND_GLYPH_POS_OFF and then set to defaults the public
+    // features and the result can be merged with new font options to set
+    // CAIRO_ROUND_GLYPH_POS_OFF in those
+    mpRoundGlyphPosOffOptions = cairo_font_options_create();
+#if defined(CAIRO_HAS_SVG_SURFACE)
+    // svg, pdf and ps backends have CAIRO_ROUND_GLYPH_POS_OFF by default
+    cairo_surface_t* hack = cairo_svg_surface_create(nullptr, 1, 1);
+#elif defined(CAIRO_HAS_PDF_SURFACE)
+    cairo_surface_t* hack = cairo_pdf_surface_create(nullptr, 1, 1);
+#endif
+    cairo_surface_get_font_options(hack, mpRoundGlyphPosOffOptions);
+    cairo_surface_destroy(hack);
+    cairo_font_options_set_antialias(mpRoundGlyphPosOffOptions, 
CAIRO_ANTIALIAS_DEFAULT);
+    cairo_font_options_set_subpixel_order(mpRoundGlyphPosOffOptions, 
CAIRO_SUBPIXEL_ORDER_DEFAULT);
+    cairo_font_options_set_hint_style(mpRoundGlyphPosOffOptions, 
CAIRO_HINT_STYLE_DEFAULT);
+    cairo_font_options_set_hint_metrics(mpRoundGlyphPosOffOptions, 
CAIRO_HINT_METRICS_DEFAULT);
+}
+
+CairoTextRender::~CairoTextRender()
+{
+    cairo_font_options_destroy(mpRoundGlyphPosOffOptions);
+}
+
 void CairoTextRender::DrawTextLayout(const GenericSalLayout& rLayout, const 
SalGraphics& rGraphics)
 {
     const FreetypeFontInstance& rInstance = 
static_cast<FreetypeFontInstance&>(rLayout.GetFont());
@@ -199,21 +234,22 @@ void CairoTextRender::DrawTextLayout(const 
GenericSalLayout& rLayout, const SalG
     if (pFontOptions || bDisableAA || bResolutionIndependentLayoutEnabled)
     {
         cairo_hint_style_t eHintStyle = pFontOptions ? 
cairo_font_options_get_hint_style(pFontOptions) : CAIRO_HINT_STYLE_DEFAULT;
-        cairo_hint_metrics_t eHintMetricsStyle = pFontOptions ? 
cairo_font_options_get_hint_metrics(pFontOptions) : CAIRO_HINT_METRICS_DEFAULT;
-        bool bAllowedHintStyle = !bResolutionIndependentLayoutEnabled || 
(eHintStyle == CAIRO_HINT_STYLE_NONE);
-        bool bAllowedHintMetricStyle = !bResolutionIndependentLayoutEnabled || 
(eHintMetricsStyle == CAIRO_HINT_METRICS_OFF);
+        bool bAllowedHintStyle = !bResolutionIndependentLayoutEnabled || 
(eHintStyle == CAIRO_HINT_STYLE_NONE || eHintStyle == CAIRO_HINT_STYLE_SLIGHT);
 
-        if (bDisableAA || !bAllowedHintStyle || !bAllowedHintMetricStyle)
+        if (bDisableAA || !bAllowedHintStyle || 
bResolutionIndependentLayoutEnabled)
         {
             // Disable font AA in case global AA setting is supposed to affect
             // font rendering (not the default) and AA is disabled.
             cairo_font_options_t* pOptions = pFontOptions ? 
cairo_font_options_copy(pFontOptions) : cairo_font_options_create();
+
             if (bDisableAA)
                 cairo_font_options_set_antialias(pOptions, 
CAIRO_ANTIALIAS_NONE);
-            if (!bAllowedHintMetricStyle)
-                cairo_font_options_set_hint_metrics(pOptions, 
CAIRO_HINT_METRICS_OFF);
             if (!bAllowedHintStyle)
-                cairo_font_options_set_hint_style(pOptions, 
CAIRO_HINT_STYLE_NONE);
+                cairo_font_options_set_hint_style(pOptions, 
CAIRO_HINT_STYLE_SLIGHT);
+            // Disable private CAIRO_ROUND_GLYPH_POS_ON by merging with font 
options known to have
+            // CAIRO_ROUND_GLYPH_POS_OFF
+            if (bResolutionIndependentLayoutEnabled)
+                cairo_font_options_merge(pOptions, mpRoundGlyphPosOffOptions);
             cairo_set_font_options(cr, pOptions);
             cairo_font_options_destroy(pOptions);
         }

Reply via email to