LibreOffice Module vcl (master) 1
fontinstance.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21
22#include <hb-ot.h>
23#include <hb-graphite2.h>
24
26#include <fontinstance.hxx>
27#include <impfontcache.hxx>
28
30 : mxFontMetric( new ImplFontMetricData( rFontSelData ))
31 , mpConversion( nullptr )
32 , mnLineHeight( 0 )
33 , mnOwnOrientation( 0 )
34 , mnOrientation( 0 )
35 , mbInit( false )
36 , mpFontCache( nullptr )
37 , m_aFontSelData(rFontSelData)
38 , m_pHbFont(nullptr)
39 , m_nAveWidthFactor(1.0f)
40 , m_pFontFace(&const_cast<vcl::font::PhysicalFontFace&>(rFontFace))
41{
42}
43
45{
47 mpFontCache = nullptr;
48 mxFontMetric = nullptr;
49
50 if (m_pHbFont)
51 hb_font_destroy(m_pHbFont);
52}
53
54hb_font_t* LogicalFontInstance::InitHbFont(hb_face_t* pHbFace)
55{
56 assert(pHbFace);
57 hb_font_t* pHbFont = hb_font_create(pHbFace);
58 unsigned int nUPEM = hb_face_get_upem(pHbFace);
59 hb_font_set_scale(pHbFont, nUPEM, nUPEM);
60 hb_ot_font_set_funcs(pHbFont);
61 // hb_font_t keeps a reference to hb_face_t, so destroy this one.
62 hb_face_destroy(pHbFace);
63 return pHbFont;
64}
65
67{
68 hb_font_t* pHbFont = const_cast<LogicalFontInstance*>(this)->GetHbFont();
69 hb_position_t nWidth = 0;
70 hb_codepoint_t nIndex = 0;
71
72 if (hb_font_get_glyph(pHbFont, 0x0640, 0, &nIndex))
73 {
74 double nXScale = 0;
75 GetScale(&nXScale, nullptr);
76 nWidth = hb_font_get_glyph_h_advance(pHbFont, nIndex) * nXScale;
77 }
78
79 return nWidth;
80}
81
82void LogicalFontInstance::GetScale(double* nXScale, double* nYScale) const
83{
84 hb_face_t* pHbFace = hb_font_get_face(const_cast<LogicalFontInstance*>(this)->GetHbFont());
85 unsigned int nUPEM = hb_face_get_upem(pHbFace);
86
87 double nHeight(m_aFontSelData.mnHeight);
88
89 // On Windows, mnWidth is relative to average char width not font height,
90 // and we need to keep it that way for GDI to correctly scale the glyphs.
91 // Here we compensate for this so that HarfBuzz gives us the correct glyph
92 // positions.
94
95 if (nYScale)
96 *nYScale = nHeight / nUPEM;
97
98 if (nXScale)
99 *nXScale = nWidth / nUPEM;
100}
101
102void LogicalFontInstance::AddFallbackForUnicode(sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName,
103 bool bEmbolden, const ItalicMatrix& rMatrix)
104{
105 MapEntry& rEntry = maUnicodeFallbackList[ std::pair< sal_UCS4, FontWeight >(cChar,eWeight) ];
106 rEntry.sFontName = rFontName;
107 rEntry.bEmbolden = bEmbolden;
108 rEntry.aItalicMatrix = rMatrix;
109}
110
112 OUString* pFontName, bool* pEmbolden, ItalicMatrix* pMatrix) const
113{
114 UnicodeFallbackList::const_iterator it = maUnicodeFallbackList.find( std::pair< sal_UCS4, FontWeight >(cChar,eWeight) );
115 if( it == maUnicodeFallbackList.end() )
116 return false;
117
118 const MapEntry& rEntry = (*it).second;
119 *pFontName = rEntry.sFontName;
120 *pEmbolden = rEntry.bEmbolden;
121 *pMatrix = rEntry.aItalicMatrix;
122 return true;
123}
124
125void LogicalFontInstance::IgnoreFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, std::u16string_view rFontName )
126{
127 UnicodeFallbackList::iterator it = maUnicodeFallbackList.find( std::pair< sal_UCS4,FontWeight >(cChar,eWeight) );
128 if( it == maUnicodeFallbackList.end() )
129 return;
130 const MapEntry& rEntry = (*it).second;
131 if (rEntry.sFontName == rFontName)
132 maUnicodeFallbackList.erase( it );
133}
134
136{
137 if (mpFontCache && mpFontCache->GetCachedGlyphBoundRect(this, nID, rRect))
138 return true;
139
140 bool res = ImplGetGlyphBoundRect(nID, rRect, bVertical);
141 if (mpFontCache && res)
142 mpFontCache->CacheGlyphBoundRect(this, nID, rRect);
143 return res;
144}
145
147{
149 {
150 m_xbIsGraphiteFont = hb_graphite2_face_get_gr_face(hb_font_get_face(GetHbFont())) != nullptr;
151 }
152 return *m_xbIsGraphiteFont;
153}
154
156{
158 {
159 char familyname[10];
160 unsigned int familyname_size = 10;
161
163
164 if (hb_ot_name_get_utf8 (hb_font_get_face(GetHbFont()),
165 HB_OT_NAME_ID_FONT_FAMILY , HB_LANGUAGE_INVALID, &familyname_size, familyname) == 8)
166 {
167 // DFKai-SB (ukai.ttf) is a built-in font under traditional Chinese
168 // Windows. It has wrong extent values in glyf table. The problem results
169 // in wrong positioning of glyphs in vertical writing.
170 // Check https://github.com/harfbuzz/harfbuzz/issues/3521 for reference.
171 if (!strncmp("DFKai-SB", familyname, 8))
173 }
174 }
175
176 bool bRet = true;
177
178 switch (*m_xeFontFamilyEnum)
179 {
181 // -839: optimization for one third of ukai.ttf
182 if (nYOffset == -839)
183 bRet = false;
184 break;
185 default:
186 bRet = false;
187 }
188
189 return bRet;
190}
191
192/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool GetCachedGlyphBoundRect(const LogicalFontInstance *, sal_GlyphId, tools::Rectangle &)
Definition: fontcache.cxx:251
void CacheGlyphBoundRect(const LogicalFontInstance *, sal_GlyphId, tools::Rectangle &)
Definition: fontcache.cxx:268
std::optional< bool > m_xbIsGraphiteFont
hb_font_t * GetHbFont()
void GetScale(double *nXScale, double *nYScale) const
LogicalFontInstance(const vcl::font::PhysicalFontFace &, const vcl::font::FontSelectPattern &)
void AddFallbackForUnicode(sal_UCS4 cChar, FontWeight eWeight, const OUString &rFontName, bool bEmbolden, const ItalicMatrix &rMatrix)
bool GetGlyphBoundRect(sal_GlyphId, tools::Rectangle &, bool) const
ImplFontMetricDataRef mxFontMetric
const vcl::font::FontSelectPattern m_aFontSelData
bool GetFallbackForUnicode(sal_UCS4 cInChar, FontWeight eInWeight, OUString *pOutFontName, bool *pOutEmbolden, ItalicMatrix *pOutItalicMatrix) const
ImplFontCache * mpFontCache
virtual bool ImplGetGlyphBoundRect(sal_GlyphId, tools::Rectangle &, bool) const =0
static hb_font_t * InitHbFont(hb_face_t *pHbFace)
std::optional< FontFamilyEnum > m_xeFontFamilyEnum
bool NeedOffsetCorrection(sal_Int32 nYOffset)
void IgnoreFallbackForUnicode(sal_UCS4, FontWeight eWeight, std::u16string_view rFontName)
int GetKashidaWidth() const
UnicodeFallbackList maUnicodeFallbackList
virtual ~LogicalFontInstance() override
abstract base class for physical font faces
sal_uInt16 sal_GlyphId
Definition: glyphid.hxx:24
sal_Int32 nIndex
FontWeight
sal_uInt32 sal_UCS4
Definition: vclenum.hxx:172