put floating frames under managed links control
[LibreOffice.git] / vcl / qt5 / QtGraphics_Text.cxx
blobb509c2a946bd1f364a0faa0b3f965322b95f03eb
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>
22 #include <QtGraphics.hxx>
23 #include <QtFontFace.hxx>
24 #include <QtFont.hxx>
25 #include <QtPainter.hxx>
27 #include <fontsubset.hxx>
28 #include <vcl/fontcharmap.hxx>
29 #include <unx/geninst.h>
30 #include <unx/fontmanager.hxx>
31 #include <unx/glyphcache.hxx>
32 #include <unx/genpspgraphics.h>
34 #include <sallayout.hxx>
35 #include <font/PhysicalFontCollection.hxx>
37 #include <QtGui/QGlyphRun>
38 #include <QtGui/QFontDatabase>
39 #include <QtGui/QRawFont>
40 #include <QtCore/QStringList>
42 void QtGraphics::SetTextColor(Color nColor) { m_aTextColor = nColor; }
44 void QtGraphics::SetFont(LogicalFontInstance* pReqFont, int nFallbackLevel)
46 // release the text styles
47 for (int i = nFallbackLevel; i < MAX_FALLBACK; ++i)
49 if (!m_pTextStyle[i])
50 break;
51 m_pTextStyle[i].clear();
54 if (!pReqFont)
55 return;
57 m_pTextStyle[nFallbackLevel] = static_cast<QtFont*>(pReqFont);
60 void QtGraphics::GetFontMetric(ImplFontMetricDataRef& rFMD, int nFallbackLevel)
62 QRawFont aRawFont(QRawFont::fromFont(*m_pTextStyle[nFallbackLevel]));
63 QtFontFace::fillAttributesFromQFont(*m_pTextStyle[nFallbackLevel], *rFMD);
65 rFMD->ImplCalcLineSpacing(m_pTextStyle[nFallbackLevel].get());
67 rFMD->SetSlant(0);
68 rFMD->SetWidth(aRawFont.averageCharWidth());
70 rFMD->SetMinKashida(m_pTextStyle[nFallbackLevel]->GetKashidaWidth());
73 FontCharMapRef QtGraphics::GetFontCharMap() const
75 if (!m_pTextStyle[0])
76 return FontCharMapRef(new FontCharMap());
77 return m_pTextStyle[0]->GetFontFace()->GetFontCharMap();
80 bool QtGraphics::GetFontCapabilities(vcl::FontCapabilities& rFontCapabilities) const
82 if (!m_pTextStyle[0])
83 return false;
84 return m_pTextStyle[0]->GetFontFace()->GetFontCapabilities(rFontCapabilities);
87 void QtGraphics::GetDevFontList(vcl::font::PhysicalFontCollection* pPFC)
89 static const bool bUseFontconfig = (nullptr == getenv("SAL_VCL_QT5_NO_FONTCONFIG"));
91 if (pPFC->Count())
92 return;
94 QFontDatabase aFDB;
95 FreetypeManager& rFontManager = FreetypeManager::get();
96 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
97 ::std::vector<psp::fontID> aList;
98 psp::FastPrintFontInfo aInfo;
100 rMgr.getFontList(aList);
101 for (auto const& elem : aList)
103 if (!rMgr.getFontFastInfo(elem, aInfo))
104 continue;
106 // normalize face number to the FreetypeManager
107 int nFaceNum = rMgr.getFontFaceNumber(aInfo.m_nID);
108 int nVariantNum = rMgr.getFontFaceVariation(aInfo.m_nID);
110 // inform FreetypeManager about this font provided by the PsPrint subsystem
111 FontAttributes aDFA = GenPspGraphics::Info2FontAttributes(aInfo);
112 aDFA.IncreaseQualityBy(4096);
113 const OString& rFileName = rMgr.getFontFileSysPath(aInfo.m_nID);
114 rFontManager.AddFontFile(rFileName, nFaceNum, nVariantNum, aInfo.m_nID, aDFA);
117 if (bUseFontconfig)
118 SalGenericInstance::RegisterFontSubstitutors(pPFC);
120 for (auto& family : aFDB.families())
121 for (auto& style : aFDB.styles(family))
122 pPFC->Add(QtFontFace::fromQFontDatabase(family, style));
125 void QtGraphics::ClearDevFontCache() {}
127 bool QtGraphics::AddTempDevFont(vcl::font::PhysicalFontCollection*, const OUString& /*rFileURL*/,
128 const OUString& /*rFontName*/)
130 return false;
133 namespace
135 class QtTrueTypeFont : public vcl::AbstractTrueTypeFont
137 const QRawFont& m_aRawFont;
138 mutable QByteArray m_aFontTable[vcl::NUM_TAGS];
140 public:
141 QtTrueTypeFont(const QtFontFace& aFontFace, const QRawFont& aRawFont);
143 bool hasTable(sal_uInt32 ord) const override;
144 const sal_uInt8* table(sal_uInt32 ord, sal_uInt32& size) const override;
147 QtTrueTypeFont::QtTrueTypeFont(const QtFontFace& aFontFace, const QRawFont& aRawFont)
148 : vcl::AbstractTrueTypeFont(nullptr, aFontFace.GetFontCharMap())
149 , m_aRawFont(aRawFont)
151 indexGlyphData();
154 const char* vclFontTableAsChar(sal_uInt32 ord)
156 switch (ord)
158 case vcl::O_maxp:
159 return "maxp";
160 case vcl::O_glyf:
161 return "glyf";
162 case vcl::O_head:
163 return "head";
164 case vcl::O_loca:
165 return "loca";
166 case vcl::O_name:
167 return "name";
168 case vcl::O_hhea:
169 return "hhea";
170 case vcl::O_hmtx:
171 return "hmtx";
172 case vcl::O_cmap:
173 return "cmap";
174 case vcl::O_vhea:
175 return "vhea";
176 case vcl::O_vmtx:
177 return "vmtx";
178 case vcl::O_OS2:
179 return "OS/2";
180 case vcl::O_post:
181 return "post";
182 case vcl::O_cvt:
183 return "cvt ";
184 case vcl::O_prep:
185 return "prep";
186 case vcl::O_fpgm:
187 return "fpgm";
188 case vcl::O_gsub:
189 return "gsub";
190 case vcl::O_CFF:
191 return "CFF ";
192 default:
193 return nullptr;
197 bool QtTrueTypeFont::hasTable(sal_uInt32 ord) const
199 const char* table_char = vclFontTableAsChar(ord);
200 if (!table_char)
201 return false;
202 if (m_aFontTable[ord].isEmpty())
203 m_aFontTable[ord] = m_aRawFont.fontTable(table_char);
204 return !m_aFontTable[ord].isEmpty();
207 const sal_uInt8* QtTrueTypeFont::table(sal_uInt32 ord, sal_uInt32& size) const
209 const char* table_char = vclFontTableAsChar(ord);
210 if (!table_char)
211 return nullptr;
212 if (m_aFontTable[ord].isEmpty())
213 m_aFontTable[ord] = m_aRawFont.fontTable(table_char);
214 size = m_aFontTable[ord].size();
215 return reinterpret_cast<const sal_uInt8*>(m_aFontTable[ord].data());
219 bool QtGraphics::CreateFontSubset(const OUString& rToFile,
220 const vcl::font::PhysicalFontFace* pFontFace,
221 const sal_GlyphId* pGlyphIds, const sal_uInt8* pEncoding,
222 sal_Int32* pGlyphWidths, int nGlyphCount, FontSubsetInfo& rInfo)
224 OUString aSysPath;
225 if (osl_File_E_None != osl_getSystemPathFromFileURL(rToFile.pData, &aSysPath.pData))
226 return false;
228 // get the raw-bytes from the font to be subset
229 const QtFontFace* pQtFontFace = static_cast<const QtFontFace*>(pFontFace);
230 const QFont aFont = pQtFontFace->CreateFont();
231 const QRawFont aRawFont(QRawFont::fromFont(aFont));
232 const OString aToFile(OUStringToOString(aSysPath, osl_getThreadTextEncoding()));
234 // handle CFF-subsetting
235 QByteArray aCFFtable = aRawFont.fontTable("CFF ");
236 if (!aCFFtable.isEmpty())
237 return SalGraphics::CreateCFFfontSubset(
238 reinterpret_cast<const sal_uInt8*>(aCFFtable.data()), aCFFtable.size(), aToFile,
239 pGlyphIds, pEncoding, pGlyphWidths, nGlyphCount, rInfo);
241 // fill details about the subsetted font
242 rInfo.m_nFontType = FontType::SFNT_TTF;
243 rInfo.m_aPSName = toOUString(aRawFont.familyName());
244 rInfo.m_nCapHeight = aRawFont.capHeight();
245 rInfo.m_nAscent = aRawFont.ascent();
246 rInfo.m_nDescent = aRawFont.descent();
248 QtTrueTypeFont aTTF(*pQtFontFace, aRawFont);
249 int nXmin, nYmin, nXmax, nYmax;
250 sal_uInt16 nMacStyleFlags;
251 if (GetTTGlobalFontHeadInfo(&aTTF, nXmin, nYmin, nXmax, nYmax, nMacStyleFlags))
252 rInfo.m_aFontBBox = tools::Rectangle(Point(nXmin, nYmin), Point(nXmax, nYmax));
254 return SalGraphics::CreateTTFfontSubset(aTTF, aToFile, false /* use FontSelectPattern? */,
255 pGlyphIds, pEncoding, pGlyphWidths, nGlyphCount);
258 const void* QtGraphics::GetEmbedFontData(const vcl::font::PhysicalFontFace*,
259 tools::Long* /*pDataLen*/)
261 return nullptr;
264 void QtGraphics::FreeEmbedFontData(const void* /*pData*/, tools::Long /*nDataLen*/) {}
266 void QtGraphics::GetGlyphWidths(const vcl::font::PhysicalFontFace* pFontFace, bool bVertical,
267 std::vector<sal_Int32>& rWidths, Ucs2UIntMap& rUnicodeEnc)
269 const QtFontFace* pQtFontFace = static_cast<const QtFontFace*>(pFontFace);
270 const QRawFont aRawFont(QRawFont::fromFont(pQtFontFace->CreateFont()));
271 QtTrueTypeFont aTTF(*pQtFontFace, aRawFont);
272 SalGraphics::GetGlyphWidths(aTTF, *pFontFace, bVertical, rWidths, rUnicodeEnc);
275 namespace
277 class QtCommonSalLayout : public GenericSalLayout
279 public:
280 QtCommonSalLayout(LogicalFontInstance& rLFI)
281 : GenericSalLayout(rLFI)
285 void SetOrientation(Degree10 nOrientation) { mnOrientation = nOrientation; }
289 std::unique_ptr<GenericSalLayout> QtGraphics::GetTextLayout(int nFallbackLevel)
291 assert(m_pTextStyle[nFallbackLevel]);
292 if (!m_pTextStyle[nFallbackLevel])
293 return nullptr;
294 return std::make_unique<QtCommonSalLayout>(*m_pTextStyle[nFallbackLevel]);
297 void QtGraphics::DrawTextLayout(const GenericSalLayout& rLayout)
299 const QtFont* pFont = static_cast<const QtFont*>(&rLayout.GetFont());
300 assert(pFont);
301 QRawFont aRawFont(QRawFont::fromFont(*pFont));
303 QVector<quint32> glyphIndexes;
304 QVector<QPointF> positions;
306 // prevent glyph rotation inside the SalLayout
307 // probably better to add a parameter to GetNextGlyphs?
308 QtCommonSalLayout* pQtLayout
309 = static_cast<QtCommonSalLayout*>(const_cast<GenericSalLayout*>(&rLayout));
310 Degree10 nOrientation = rLayout.GetOrientation();
311 if (nOrientation)
312 pQtLayout->SetOrientation(0_deg10);
314 Point aPos;
315 const GlyphItem* pGlyph;
316 int nStart = 0;
317 while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart))
319 glyphIndexes.push_back(pGlyph->glyphId());
320 positions.push_back(QPointF(aPos.X(), aPos.Y()));
323 // seems to be common to try to layout an empty string...
324 if (positions.empty())
325 return;
327 if (nOrientation)
328 pQtLayout->SetOrientation(nOrientation);
330 QGlyphRun aGlyphRun;
331 aGlyphRun.setPositions(positions);
332 aGlyphRun.setGlyphIndexes(glyphIndexes);
333 aGlyphRun.setRawFont(aRawFont);
335 QtPainter aPainter(*m_pBackend);
336 QColor aColor = toQColor(m_aTextColor);
337 aPainter.setPen(aColor);
339 if (nOrientation)
341 // make text position the center of the rotation
342 // then rotate and move back
343 QRect window = aPainter.window();
344 window.moveTo(-positions[0].x(), -positions[0].y());
345 aPainter.setWindow(window);
347 QTransform p;
348 p.rotate(-static_cast<qreal>(nOrientation.get()) / 10.0);
349 p.translate(-positions[0].x(), -positions[0].y());
350 aPainter.setTransform(p);
353 aPainter.drawGlyphRun(QPointF(), aGlyphRun);
356 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */