calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / vcl / win / gdi / winlayout.cxx
blob371bdeb9642e2eebab7e87e270ab2629a79563e8
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)
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 if (!pSalData->m_pD2DWriteTextOutRenderer
66 || static_cast<D2DWriteTextOutRenderer*>(pSalData->m_pD2DWriteTextOutRenderer.get())
67 ->GetRenderingModeNatural()
68 != bRenderingModeNatural)
70 pSalData->m_pD2DWriteTextOutRenderer.reset(
71 new D2DWriteTextOutRenderer(bRenderingModeNatural));
73 return *pSalData->m_pD2DWriteTextOutRenderer;
75 if (!pSalData->m_pExTextOutRenderer)
77 pSalData->m_pExTextOutRenderer.reset(new ExTextOutRenderer);
79 return *pSalData->m_pExTextOutRenderer;
82 bool ExTextOutRenderer::operator()(GenericSalLayout const& rLayout, SalGraphics& /*rGraphics*/,
83 HDC hDC, bool /*bRenderingModeNatural*/)
85 int nStart = 0;
86 DevicePoint aPos;
87 const GlyphItem* pGlyph;
88 const WinFontInstance* pWinFont = static_cast<const WinFontInstance*>(&rLayout.GetFont());
89 UINT nTextAlign = GetTextAlign(hDC);
90 UINT nCurTextAlign = nTextAlign;
91 sal_Int32 nGlyphOffset = -pWinFont->GetTmDescent();
93 while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart))
95 wchar_t glyphWStr = pGlyph->glyphId();
96 UINT32 nNewTextAlign = nCurTextAlign;
97 sal_Int32 nYOffset = 0;
99 if (pWinFont->IsCJKVerticalFont() && pGlyph->IsVertical())
101 nNewTextAlign = VTA_CENTER | TA_BOTTOM;
102 nYOffset = nGlyphOffset;
104 else
105 nNewTextAlign = nTextAlign;
107 if (nCurTextAlign != nNewTextAlign)
108 SetTextAlign(hDC, nNewTextAlign);
110 ExtTextOutW(hDC, aPos.getX(), aPos.getY() + nYOffset, ETO_GLYPH_INDEX, nullptr, &glyphWStr,
111 1, nullptr);
113 nCurTextAlign = nNewTextAlign;
116 if (nCurTextAlign != nTextAlign)
117 SetTextAlign(hDC, nTextAlign);
119 return true;
122 std::unique_ptr<GenericSalLayout> WinSalGraphics::GetTextLayout(int nFallbackLevel)
124 assert(mpWinFontEntry[nFallbackLevel]);
125 if (!mpWinFontEntry[nFallbackLevel])
126 return nullptr;
128 assert(mpWinFontEntry[nFallbackLevel]->GetFontFace());
130 mpWinFontEntry[nFallbackLevel]->SetGraphics(this);
131 return std::make_unique<GenericSalLayout>(*mpWinFontEntry[nFallbackLevel]);
134 WinFontInstance::WinFontInstance(const WinFontFace& rPFF, const vcl::font::FontSelectPattern& rFSP)
135 : LogicalFontInstance(rPFF, rFSP)
136 , m_pGraphics(nullptr)
137 , m_hFont(nullptr)
138 , m_fScale(1.0f)
139 , m_bIsCJKVerticalFont(false)
140 , m_nTmDescent(0)
144 WinFontInstance::~WinFontInstance()
146 if (m_hFont)
147 ::DeleteFont(m_hFont);
150 bool WinFontInstance::hasHScale() const
152 const vcl::font::FontSelectPattern& rPattern = GetFontSelectPattern();
153 int nHeight(rPattern.mnHeight);
154 int nWidth(rPattern.mnWidth ? rPattern.mnWidth * GetAverageWidthFactor() : nHeight);
155 return nWidth != nHeight;
158 float WinFontInstance::getHScale() const
160 const vcl::font::FontSelectPattern& rPattern = GetFontSelectPattern();
161 int nHeight(rPattern.mnHeight);
162 if (!nHeight)
163 return 1.0;
164 float nWidth(rPattern.mnWidth ? rPattern.mnWidth * GetAverageWidthFactor() : nHeight);
165 return nWidth / nHeight;
168 void WinFontInstance::ImplInitHbFont(hb_font_t* /*pHbFont*/)
170 assert(m_pGraphics);
171 // Calculate the AverageWidthFactor, see LogicalFontInstance::GetScale().
172 if (GetFontSelectPattern().mnWidth)
174 double nUPEM = GetFontFace()->UnitsPerEm();
176 LOGFONTW aLogFont;
177 GetObjectW(m_hFont, sizeof(LOGFONTW), &aLogFont);
179 // Set the height (font size) to EM to minimize rounding errors.
180 aLogFont.lfHeight = -nUPEM;
181 // Set width to the default to get the original value in the metrics.
182 aLogFont.lfWidth = 0;
184 TEXTMETRICW aFontMetric;
186 // Get the font metrics.
187 HDC hDC = m_pGraphics->getHDC();
188 ScopedSelectedHFONT hFont(hDC, CreateFontIndirectW(&aLogFont));
189 GetTextMetricsW(hDC, &aFontMetric);
192 SetAverageWidthFactor(nUPEM / aFontMetric.tmAveCharWidth);
196 void WinFontInstance::SetGraphics(WinSalGraphics* pGraphics)
198 m_pGraphics = pGraphics;
199 if (m_hFont)
200 return;
201 HFONT hOrigFont;
202 HDC hDC = m_pGraphics->getHDC();
203 std::tie(m_hFont, m_bIsCJKVerticalFont, m_nTmDescent)
204 = m_pGraphics->ImplDoSetFont(hDC, GetFontSelectPattern(), GetFontFace(), hOrigFont);
205 SelectObject(hDC, hOrigFont);
208 void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout, HDC hDC, bool bUseDWrite,
209 bool bRenderingModeNatural)
211 TextOutRenderer& render = TextOutRenderer::get(bUseDWrite, bRenderingModeNatural);
212 render(rLayout, *this, hDC, bRenderingModeNatural);
215 void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout)
217 if (!mbPrinter && mWinSalGraphicsImplBase->DrawTextLayout(rLayout))
218 return; // handled by mWinSalGraphicsImplBase
220 HDC hDC = getHDC();
221 const WinFontInstance* pWinFont = static_cast<const WinFontInstance*>(&rLayout.GetFont());
222 const HFONT hLayoutFont = pWinFont->GetHFONT();
224 const HFONT hOrigFont = ::SelectFont(hDC, hLayoutFont);
226 // DWrite text renderer performs vertical writing better except printing.
227 const bool bVerticalScreenText
228 = !mbPrinter && rLayout.GetFont().GetFontSelectPattern().mbVertical;
229 const bool bRenderingModeNatural = rLayout.GetTextRenderModeForResolutionIndependentLayout();
230 const bool bUseDWrite = bVerticalScreenText || bRenderingModeNatural;
231 DrawTextLayout(rLayout, hDC, bUseDWrite, bRenderingModeNatural);
233 ::SelectFont(hDC, hOrigFont);
236 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */