tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / vcl / win / gdi / winlayout.cxx
blob83c3a653b1ae670929db48191e273a3bfe4b2a00
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
21 #include <config_features.h>
23 #include <memory>
25 #include <o3tl/safeint.hxx>
26 #include <osl/module.h>
27 #include <osl/file.h>
28 #include <sal/log.hxx>
30 #include <comphelper/windowserrorstring.hxx>
31 #include <comphelper/scopeguard.hxx>
33 #include <win/salgdi.h>
34 #include <win/saldata.hxx>
35 #include <win/wingdiimpl.hxx>
36 #include <ImplOutDevData.hxx>
38 #include <win/DWriteTextRenderer.hxx>
39 #include <win/scoped_gdi.hxx>
41 #include <sallayout.hxx>
43 #include <cstdio>
44 #include <cstdlib>
46 #include <rtl/character.hxx>
48 #include <algorithm>
50 #include <shlwapi.h>
51 #include <winver.h>
53 TextOutRenderer& TextOutRenderer::get(bool bUseDWrite, bool bRenderingModeNatural, bool bAntiAlias)
55 SalData* const pSalData = GetSalData();
57 if (!pSalData)
58 { // don't call this after DeInitVCL()
59 fprintf(stderr, "TextOutRenderer fatal error: no SalData");
60 abort();
63 if (bUseDWrite)
65 const auto mode = D2DWriteTextOutRenderer::GetMode(bRenderingModeNatural, bAntiAlias);
66 if (pSalData->m_pD2DWriteTextOutRenderer)
68 auto pRenderer
69 = static_cast<D2DWriteTextOutRenderer*>(pSalData->m_pD2DWriteTextOutRenderer.get());
70 if (pRenderer->GetRenderingMode() == mode)
71 return *pSalData->m_pD2DWriteTextOutRenderer;
74 pSalData->m_pD2DWriteTextOutRenderer.reset(new D2DWriteTextOutRenderer(mode));
75 return *pSalData->m_pD2DWriteTextOutRenderer;
77 if (!pSalData->m_pExTextOutRenderer)
79 pSalData->m_pExTextOutRenderer.reset(new ExTextOutRenderer);
81 return *pSalData->m_pExTextOutRenderer;
84 bool ExTextOutRenderer::operator()(GenericSalLayout const& rLayout, SalGraphics& /*rGraphics*/,
85 HDC hDC)
87 int nStart = 0;
88 basegfx::B2DPoint aPos;
89 const GlyphItem* pGlyph;
90 const WinFontInstance* pWinFont = static_cast<const WinFontInstance*>(&rLayout.GetFont());
91 UINT nTextAlign = GetTextAlign(hDC);
92 UINT nCurTextAlign = nTextAlign;
93 sal_Int32 nGlyphOffset = -pWinFont->GetTmDescent();
95 while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart))
97 wchar_t glyphWStr = pGlyph->glyphId();
98 UINT32 nNewTextAlign = nCurTextAlign;
99 sal_Int32 nYOffset = 0;
101 if (pWinFont->IsCJKVerticalFont() && pGlyph->IsVertical())
103 nNewTextAlign = VTA_CENTER | TA_BOTTOM;
104 nYOffset = nGlyphOffset;
106 else
107 nNewTextAlign = nTextAlign;
109 if (nCurTextAlign != nNewTextAlign)
110 SetTextAlign(hDC, nNewTextAlign);
112 ExtTextOutW(hDC, aPos.getX(), aPos.getY() + nYOffset, ETO_GLYPH_INDEX, nullptr, &glyphWStr,
113 1, nullptr);
115 nCurTextAlign = nNewTextAlign;
118 if (nCurTextAlign != nTextAlign)
119 SetTextAlign(hDC, nTextAlign);
121 return true;
124 std::unique_ptr<GenericSalLayout> WinSalGraphics::GetTextLayout(int nFallbackLevel)
126 assert(mpWinFontEntry[nFallbackLevel]);
127 if (!mpWinFontEntry[nFallbackLevel])
128 return nullptr;
130 assert(mpWinFontEntry[nFallbackLevel]->GetFontFace());
132 mpWinFontEntry[nFallbackLevel]->SetGraphics(this);
133 return std::make_unique<GenericSalLayout>(*mpWinFontEntry[nFallbackLevel]);
136 WinFontInstance::WinFontInstance(const WinFontFace& rPFF, const vcl::font::FontSelectPattern& rFSP)
137 : LogicalFontInstance(rPFF, rFSP)
138 , m_pGraphics(nullptr)
139 , m_hFont(nullptr)
140 , m_bIsCJKVerticalFont(false)
141 , m_nTmDescent(0)
145 WinFontInstance::~WinFontInstance()
147 if (m_hFont)
148 ::DeleteFont(m_hFont);
151 float WinFontInstance::getHScale() const
153 const vcl::font::FontSelectPattern& rPattern = GetFontSelectPattern();
154 if (!rPattern.mnHeight || !rPattern.mnWidth)
155 return 1.0;
156 return rPattern.mnWidth * GetAverageWidthFactor() / rPattern.mnHeight;
159 void WinFontInstance::ImplInitHbFont(hb_font_t* /*pHbFont*/)
161 assert(m_pGraphics);
162 // Calculate the AverageWidthFactor, see LogicalFontInstance::GetScale().
163 if (GetFontSelectPattern().mnWidth)
165 double nUPEM = GetFontFace()->UnitsPerEm();
167 LOGFONTW aLogFont;
168 GetObjectW(m_hFont, sizeof(LOGFONTW), &aLogFont);
170 // Set the height (font size) to EM to minimize rounding errors.
171 aLogFont.lfHeight = -nUPEM;
172 // Set width to the default to get the original value in the metrics.
173 aLogFont.lfWidth = 0;
175 TEXTMETRICW aFontMetric;
177 // Get the font metrics.
178 HDC hDC = m_pGraphics->getHDC();
179 ScopedSelectedHFONT hFont(hDC, CreateFontIndirectW(&aLogFont));
180 GetTextMetricsW(hDC, &aFontMetric);
183 SetAverageWidthFactor(nUPEM / aFontMetric.tmAveCharWidth);
187 void WinFontInstance::SetGraphics(WinSalGraphics* pGraphics)
189 m_pGraphics = pGraphics;
190 if (m_hFont)
191 return;
192 HFONT hOrigFont;
193 HDC hDC = m_pGraphics->getHDC();
194 std::tie(m_hFont, m_bIsCJKVerticalFont, m_nTmDescent)
195 = m_pGraphics->ImplDoSetFont(hDC, GetFontSelectPattern(), GetFontFace(), hOrigFont);
196 SelectObject(hDC, hOrigFont);
199 void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout, HDC hDC, bool bUseDWrite,
200 bool bRenderingModeNatural)
202 auto& render = TextOutRenderer::get(bUseDWrite, bRenderingModeNatural, getAntiAlias());
203 render(rLayout, *this, hDC);
206 void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout)
208 if (!mbPrinter && mWinSalGraphicsImplBase->DrawTextLayout(rLayout))
209 return; // handled by mWinSalGraphicsImplBase
211 HDC hDC = getHDC();
212 const WinFontInstance* pWinFont = static_cast<const WinFontInstance*>(&rLayout.GetFont());
213 const HFONT hLayoutFont = pWinFont->GetHFONT();
215 const HFONT hOrigFont = ::SelectFont(hDC, hLayoutFont);
217 // DWrite text renderer performs vertical writing better except printing.
218 const bool bVerticalScreenText
219 = !mbPrinter && rLayout.GetFont().GetFontSelectPattern().mbVertical;
220 const bool bRenderingModeNatural = rLayout.GetSubpixelPositioning();
221 const bool bUseDWrite = bVerticalScreenText || bRenderingModeNatural;
222 DrawTextLayout(rLayout, hDC, bUseDWrite, bRenderingModeNatural);
224 ::SelectFont(hDC, hOrigFont);
227 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */