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