summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorMark Hung <marklh9@gmail.com>2022-04-03 14:53:14 +0800
committerMark Hung <marklh9@gmail.com>2022-04-08 15:25:37 +0200
commit257bb11cbc5b1eb1f90014f528b9e7d6ccfeae86 (patch)
tree5b1aad0787c01d86759e514ccee52e9d27fb62ba /vcl
parent2b2d1c08c94fdc3982971c2b19ea241f05e578c9 (diff)
tdf#148330 fix vertical offset for DFKai-SB (ukai.ttf).
DFKai-SB (ukai.ttf) is a built-in font under tradtional Chinese Windows. The font is very common, especially for official documents. It is one of the so-called tricky fonts in FreeType[1]. DFKai-SB has incorrect extent in the glyf table[2]. It results in incorrect glyph positions in vertical writing. FreeType recalculates the extents based on the glyph outline, but LibreOffice uses Harfbuzz with built-in ot font functions instead of ft (FreeType). This patch decides if the fix is necessary by checking the family name of the font and the y-offset value, and recaculates the glyph offset based on glyph height and top bearing obtained from the glyph bound rect. [1]https://freetype.org/freetype2/docs/reference/ft2-base_interface.html#ft_face_flag_tricky [2]https://github.com/harfbuzz/harfbuzz/issues/3521 Change-Id: If632dd38c462c229837e1efb5446e2142f8f0639 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132511 Tested-by: Jenkins Reviewed-by: Mark Hung <marklh9@gmail.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/fontinstance.hxx8
-rw-r--r--vcl/source/font/fontinstance.cxx37
-rw-r--r--vcl/source/gdi/CommonSalLayout.cxx13
3 files changed, 58 insertions, 0 deletions
diff --git a/vcl/inc/fontinstance.hxx b/vcl/inc/fontinstance.hxx
index 5822bd1a08b5..5b5ab206c26a 100644
--- a/vcl/inc/fontinstance.hxx
+++ b/vcl/inc/fontinstance.hxx
@@ -86,6 +86,9 @@ public: // TODO: make data members private
inline hb_font_t* GetHbFont();
bool IsGraphiteFont();
+ // NeedOffsetCorrection: Return if the font need offset correction in TTB direction.
+ // nYOffset is the original offset. It is used to check if the correction is necessary.
+ bool NeedOffsetCorrection(sal_Int32 nYOffset);
void SetAverageWidthFactor(double nFactor) { m_nAveWidthFactor = std::abs(nFactor); }
double GetAverageWidthFactor() const { return m_nAveWidthFactor; }
const vcl::font::FontSelectPattern& GetFontSelectPattern() const { return m_aFontSelData; }
@@ -129,6 +132,11 @@ private:
double m_nAveWidthFactor;
rtl::Reference<vcl::font::PhysicalFontFace> m_pFontFace;
std::optional<bool> m_xbIsGraphiteFont;
+
+ enum class FontFamilyEnum { Unclassified, DFKaiSB };
+
+ // The value is initialized and used in NeedOffsetCorrection().
+ std::optional<FontFamilyEnum> m_xeFontFamilyEnum;
};
inline hb_font_t* LogicalFontInstance::GetHbFont()
diff --git a/vcl/source/font/fontinstance.cxx b/vcl/source/font/fontinstance.cxx
index 5dbd1748a3c3..6f5bc7d1f37a 100644
--- a/vcl/source/font/fontinstance.cxx
+++ b/vcl/source/font/fontinstance.cxx
@@ -152,4 +152,41 @@ bool LogicalFontInstance::IsGraphiteFont()
return *m_xbIsGraphiteFont;
}
+bool LogicalFontInstance::NeedOffsetCorrection(sal_Int32 nYOffset)
+{
+ if (!m_xeFontFamilyEnum)
+ {
+ char familyname[10];
+ unsigned int familyname_size = 10;
+
+ m_xeFontFamilyEnum = FontFamilyEnum::Unclassified;
+
+ if (hb_ot_name_get_utf8 (hb_font_get_face(GetHbFont()),
+ HB_OT_NAME_ID_FONT_FAMILY , HB_LANGUAGE_INVALID, &familyname_size, familyname) == 8)
+ {
+ // DFKai-SB (ukai.ttf) is a built-in font under tradtional Chinese
+ // Windows. It has wrong extent values in glyf table. The problem results
+ // in wrong positioning of glyphs in vertical writing.
+ // Check https://github.com/harfbuzz/harfbuzz/issues/3521 for reference.
+ if (!strncmp("DFKai-SB", familyname, 8))
+ m_xeFontFamilyEnum = FontFamilyEnum::DFKaiSB;
+ }
+ }
+
+ bool bRet = true;
+
+ switch (*m_xeFontFamilyEnum)
+ {
+ case FontFamilyEnum::DFKaiSB:
+ // -839: optimization for one third of ukai.ttf
+ if (nYOffset == -839)
+ bRet = false;
+ break;
+ default:
+ bRet = false;
+ }
+
+ return bRet;
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index be6480bfde1a..8dee28727997 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -621,6 +621,19 @@ bool GenericSalLayout::LayoutText(vcl::text::ImplLayoutArgs& rArgs, const SalLay
nAdvance = -pHbPositions[i].y_advance;
nXOffset = -pHbPositions[i].y_offset;
nYOffset = -pHbPositions[i].x_offset - nBaseOffset;
+
+ if (GetFont().NeedOffsetCorrection(pHbPositions[i].y_offset))
+ {
+ // We need glyph's advance, top bearing, and height to
+ // correct y offset.
+ tools::Rectangle aRect;
+ // Get cached bound rect value for the font,
+ GetFont().GetGlyphBoundRect(nGlyphIndex, aRect, true);
+
+ nXOffset = -(aRect.Top() / nXScale + ( pHbPositions[i].y_advance
+ + ( aRect.GetHeight() / nXScale ) ) / 2 );
+ }
+
}
else
{