summaryrefslogtreecommitdiff
path: root/vcl/win
diff options
context:
space:
mode:
authorMark Hung <marklh9@gmail.com>2021-11-01 20:53:19 +0800
committerXisco Fauli <xiscofauli@libreoffice.org>2021-12-09 13:00:40 +0100
commit3c2836972613ff418d76306d958a8ef85ff18afe (patch)
tree38b51ed89619e1f3be09a7d506224bd735e9a73f /vcl/win
parent8ff5ba1ccd9c83bd03559ec4727e886e76721f53 (diff)
tdf#145322, tdf#144378 fix printing for vertical writing
Printing still uses ExTextOutRenderer to render text because Skia haven't yet support printing and DWriteTextRenderer can't bind the printer DC. ExTextOutRenderer uses win32 API ExtTextOutW. In order to renderer upright CJK text in vertical writing with that API, the HFONT created with CreateFontIndirectW needs a font name prefixed with '@'. OTOH, use '@' prefixed font with Skia break the vertical writing unit test. - WinSalGraphics::ImplDoSetFont: use '@' prefixed font name if the requested font is vertical and is for printing. - ExTextOutRenderer: use SetTextAlign and text metric tmDescent to adjust vertical glyphs. It's not consistent with Skia or DWriteTextRenderer, and is still incorrect in many cases. The patch is adapted from reverting commit 5686c1aca40beb9514d40c86b4a3780a8a1334ba Author: Mark Hung <marklh9@gmail.com> Date: Sun May 2 14:45:45 2021 +0800 vcl: use DWriteTextRenderer for vertical writing. Change-Id: Ib2d3df8b68cad4bebe0672c9da0a16b62aed99e6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125978 Tested-by: Jenkins Reviewed-by: Mark Hung <marklh9@gmail.com> (cherry picked from commit 6720e9569d7ab6c20616ec6b97e5d4a56948908b) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126443 Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Diffstat (limited to 'vcl/win')
-rw-r--r--vcl/win/gdi/salfont.cxx32
-rw-r--r--vcl/win/gdi/winlayout.cxx42
2 files changed, 65 insertions, 9 deletions
diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx
index 7682def12661..acaca76584a3 100644
--- a/vcl/win/gdi/salfont.cxx
+++ b/vcl/win/gdi/salfont.cxx
@@ -762,6 +762,12 @@ void WinSalGraphics::SetTextColor( Color nColor )
::SetTextColor( getHDC(), aCol );
}
+static int CALLBACK SalEnumQueryFontProcExW( const LOGFONTW*, const TEXTMETRICW*, DWORD, LPARAM lParam )
+{
+ *reinterpret_cast<bool*>(lParam) = true;
+ return 0;
+}
+
void ImplGetLogFontFromFontSelect( const vcl::font::FontSelectPattern& rFont,
const vcl::font::PhysicalFontFace* pFontFace,
LOGFONTW& rLogFont )
@@ -811,7 +817,7 @@ void ImplGetLogFontFromFontSelect( const vcl::font::FontSelectPattern& rFont,
}
-HFONT WinSalGraphics::ImplDoSetFont(HDC hDC, vcl::font::FontSelectPattern const & i_rFont,
+std::tuple<HFONT,bool,sal_Int32> WinSalGraphics::ImplDoSetFont(HDC hDC, vcl::font::FontSelectPattern const & i_rFont,
const vcl::font::PhysicalFontFace * i_pFontFace,
HFONT& o_rOldFont)
{
@@ -820,6 +826,27 @@ HFONT WinSalGraphics::ImplDoSetFont(HDC hDC, vcl::font::FontSelectPattern const
LOGFONTW aLogFont;
ImplGetLogFontFromFontSelect( i_rFont, i_pFontFace, aLogFont );
+ bool bIsCJKVerticalFont = false;
+ // select vertical mode for printing if requested and available
+ if ( i_rFont.mbVertical && mbPrinter )
+ {
+ constexpr size_t nLen = sizeof(aLogFont.lfFaceName) - sizeof(aLogFont.lfFaceName[0]);
+ // vertical fonts start with an '@'
+ memmove( &aLogFont.lfFaceName[1], &aLogFont.lfFaceName[0], nLen );
+ aLogFont.lfFaceName[0] = '@';
+ aLogFont.lfFaceName[LF_FACESIZE - 1] = 0;
+
+ // check availability of vertical mode for this font
+ EnumFontFamiliesExW( getHDC(), &aLogFont, SalEnumQueryFontProcExW,
+ reinterpret_cast<LPARAM>(&bIsCJKVerticalFont), 0 );
+ if( !bIsCJKVerticalFont )
+ {
+ // restore non-vertical name if not vertical mode isn't available
+ memcpy( &aLogFont.lfFaceName[0], &aLogFont.lfFaceName[1], nLen );
+ aLogFont.lfFaceName[LF_FACESIZE - 1] = 0;
+ }
+ }
+
hNewFont = ::CreateFontIndirectW( &aLogFont );
HDC hdcScreen = nullptr;
@@ -847,12 +874,13 @@ HFONT WinSalGraphics::ImplDoSetFont(HDC hDC, vcl::font::FontSelectPattern const
SelectFont(hDC, hNewFont2);
DeleteFont( hNewFont );
hNewFont = hNewFont2;
+ bIsCJKVerticalFont = false;
}
if( hdcScreen )
::ReleaseDC( nullptr, hdcScreen );
- return hNewFont;
+ return std::make_tuple(hNewFont, bIsCJKVerticalFont, static_cast<sal_Int32>(aTextMetricW.tmDescent));
}
void WinSalGraphics::SetFont(LogicalFontInstance* pFont, int nFallbackLevel)
diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx
index 862539083d29..83033e9f6be8 100644
--- a/vcl/win/gdi/winlayout.cxx
+++ b/vcl/win/gdi/winlayout.cxx
@@ -83,12 +83,38 @@ bool ExTextOutRenderer::operator()(GenericSalLayout const& rLayout, SalGraphics&
int nStart = 0;
Point aPos(0, 0);
const GlyphItem* pGlyph;
+ const WinFontInstance* pWinFont = static_cast<const WinFontInstance*>(&rLayout.GetFont());
+ UINT nTextAlign = GetTextAlign(hDC);
+ UINT nCurTextAlign = nTextAlign;
+ sal_Int32 nGlyphOffset = -pWinFont->GetTmDescent();
+
while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart))
{
wchar_t glyphWStr = pGlyph->glyphId();
- ExtTextOutW(hDC, aPos.X(), aPos.Y(), ETO_GLYPH_INDEX, nullptr, &glyphWStr, 1, nullptr);
+ UINT32 nNewTextAlign = nCurTextAlign;
+ sal_Int32 nYOffset = 0;
+
+ if (pWinFont->IsCJKVerticalFont() && pGlyph->IsVertical())
+ {
+ tools::Rectangle aRect;
+ nNewTextAlign = VTA_CENTER | TA_BOTTOM;
+ nYOffset = nGlyphOffset;
+ }
+ else
+ nNewTextAlign = nTextAlign;
+
+ if (nCurTextAlign != nNewTextAlign)
+ SetTextAlign(hDC, nNewTextAlign);
+
+ ExtTextOutW(hDC, aPos.X(), aPos.Y() + nYOffset, ETO_GLYPH_INDEX, nullptr, &glyphWStr, 1,
+ nullptr);
+
+ nCurTextAlign = nNewTextAlign;
}
+ if (nCurTextAlign != nTextAlign)
+ SetTextAlign(hDC, nTextAlign);
+
return true;
}
@@ -109,6 +135,8 @@ WinFontInstance::WinFontInstance(const WinFontFace& rPFF, const vcl::font::FontS
, m_pGraphics(nullptr)
, m_hFont(nullptr)
, m_fScale(1.0f)
+ , m_bIsCJKVerticalFont(false)
+ , m_nTmDescent(0)
{
}
@@ -260,9 +288,10 @@ void WinFontInstance::SetGraphics(WinSalGraphics* pGraphics)
if (m_hFont)
return;
HFONT hOrigFont;
- m_hFont = m_pGraphics->ImplDoSetFont(m_pGraphics->getHDC(), GetFontSelectPattern(),
- GetFontFace(), hOrigFont);
- SelectObject(m_pGraphics->getHDC(), hOrigFont);
+ HDC hDC = m_pGraphics->getHDC();
+ std::tie(m_hFont, m_bIsCJKVerticalFont, m_nTmDescent)
+ = m_pGraphics->ImplDoSetFont(hDC, GetFontSelectPattern(), GetFontFace(), hOrigFont);
+ SelectObject(hDC, hOrigFont);
}
void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout, HDC hDC, bool bUseDWrite)
@@ -283,9 +312,8 @@ void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout)
const HFONT hOrigFont = ::SelectFont(hDC, hLayoutFont);
- // There isn't a way for Win32 API ExtTextOutW to render vertical-writing glyphs correctly,
- // so let's use DWrite text renderer in this case.
- DrawTextLayout(rLayout, hDC, rLayout.GetFont().GetFontSelectPattern().mbVertical);
+ // DWrite text renderer performs vertical writing better except printing.
+ DrawTextLayout(rLayout, hDC, !mbPrinter && rLayout.GetFont().GetFontSelectPattern().mbVertical);
::SelectFont(hDC, hOrigFont);
}