1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
)
51 m_pTextStyle
[i
].clear();
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());
68 rFMD
->SetWidth(aRawFont
.averageCharWidth());
70 rFMD
->SetMinKashida(m_pTextStyle
[nFallbackLevel
]->GetKashidaWidth());
73 FontCharMapRef
QtGraphics::GetFontCharMap() const
76 return FontCharMapRef(new FontCharMap());
77 return m_pTextStyle
[0]->GetFontFace()->GetFontCharMap();
80 bool QtGraphics::GetFontCapabilities(vcl::FontCapabilities
& rFontCapabilities
) const
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"));
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
))
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
);
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*/)
135 class QtTrueTypeFont
: public vcl::AbstractTrueTypeFont
137 const QRawFont
& m_aRawFont
;
138 mutable QByteArray m_aFontTable
[vcl::NUM_TAGS
];
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
)
154 const char* vclFontTableAsChar(sal_uInt32 ord
)
197 bool QtTrueTypeFont::hasTable(sal_uInt32 ord
) const
199 const char* table_char
= vclFontTableAsChar(ord
);
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
);
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
)
225 if (osl_File_E_None
!= osl_getSystemPathFromFileURL(rToFile
.pData
, &aSysPath
.pData
))
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*/)
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
);
277 class QtCommonSalLayout
: public GenericSalLayout
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
])
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());
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();
312 pQtLayout
->SetOrientation(0_deg10
);
315 const GlyphItem
* pGlyph
;
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())
328 pQtLayout
->SetOrientation(nOrientation
);
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
);
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
);
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: */