diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2020-08-14 05:53:26 +0200 |
---|---|---|
committer | Jan-Marek Glogowski <glogow@fbihome.de> | 2020-08-15 13:18:43 +0200 |
commit | 5a888c5fd295f9b98dee9ce930e653cb63a02857 (patch) | |
tree | 06dd986e0d30a8caf38e3565d481ec8cf82d8003 /vcl/qt5 | |
parent | 4c05d61a4393d38834254f03a83aa01b7582060b (diff) |
tdf#125234 Qt5 implement CreateFontSubset
This abstracts the just refactored vcl::TrueTypeFont class, so the
Qt5 backend can provide it's own QRawFont based font table access.
Change-Id: Ic71bc95bc8fe39bc7a32086d4adc78cfa00d15be
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100718
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
Diffstat (limited to 'vcl/qt5')
-rw-r--r-- | vcl/qt5/Qt5FontFace.cxx | 7 | ||||
-rw-r--r-- | vcl/qt5/Qt5Graphics_Text.cxx | 160 |
2 files changed, 162 insertions, 5 deletions
diff --git a/vcl/qt5/Qt5FontFace.cxx b/vcl/qt5/Qt5FontFace.cxx index 8ac2f87d1843..d02e61955103 100644 --- a/vcl/qt5/Qt5FontFace.cxx +++ b/vcl/qt5/Qt5FontFace.cxx @@ -149,6 +149,13 @@ Qt5FontFace::Qt5FontFace(const FontAttributes& rFA, const QString& rFontID) sal_IntPtr Qt5FontFace::GetFontId() const { return reinterpret_cast<sal_IntPtr>(&m_aFontId); } +QFont Qt5FontFace::CreateFont() const +{ + QFont aFont; + aFont.fromString(m_aFontId); + return aFont; +} + rtl::Reference<LogicalFontInstance> Qt5FontFace::CreateFontInstance(const FontSelectPattern& rFSD) const { diff --git a/vcl/qt5/Qt5Graphics_Text.cxx b/vcl/qt5/Qt5Graphics_Text.cxx index 4ba009106d26..8ee299debfd0 100644 --- a/vcl/qt5/Qt5Graphics_Text.cxx +++ b/vcl/qt5/Qt5Graphics_Text.cxx @@ -22,6 +22,7 @@ #include <Qt5Font.hxx> #include <Qt5Painter.hxx> +#include <fontsubset.hxx> #include <vcl/fontcharmap.hxx> #include <unx/geninst.h> #include <unx/fontmanager.hxx> @@ -129,12 +130,161 @@ bool Qt5Graphics::AddTempDevFont(PhysicalFontCollection*, const OUString& /*rFil return false; } -bool Qt5Graphics::CreateFontSubset(const OUString& /*rToFile*/, const PhysicalFontFace* /*pFont*/, - const sal_GlyphId* /*pGlyphIds*/, const sal_uInt8* /*pEncoding*/, - sal_Int32* /*pWidths*/, int /*nGlyphs*/, - FontSubsetInfo& /*rInfo*/) +namespace { - return false; +class Qt5TrueTypeFont : public vcl::AbstractTrueTypeFont +{ + const QRawFont& m_aRawFont; + mutable QByteArray m_aFontTable[vcl::NUM_TAGS]; + +public: + Qt5TrueTypeFont(const QRawFont& aRawFont); + + bool hasTable(sal_uInt32 ord) const override; + const sal_uInt8* table(sal_uInt32 ord, sal_uInt32& size) const override; +}; + +Qt5TrueTypeFont::Qt5TrueTypeFont(const QRawFont& aRawFont) + : m_aRawFont(aRawFont) +{ + indexGlyphData(); +} + +const char* vclFontTableAsChar(sal_uInt32 ord) +{ + switch (ord) + { + case vcl::O_maxp: + return "maxp"; + case vcl::O_glyf: + return "glyf"; + case vcl::O_head: + return "head"; + case vcl::O_loca: + return "loca"; + case vcl::O_name: + return "name"; + case vcl::O_hhea: + return "hhea"; + case vcl::O_hmtx: + return "hmtx"; + case vcl::O_cmap: + return "cmap"; + case vcl::O_vhea: + return "vhea"; + case vcl::O_vmtx: + return "vmtx"; + case vcl::O_OS2: + return "OS/2"; + case vcl::O_post: + return "post"; + case vcl::O_cvt: + return "cvt "; + case vcl::O_prep: + return "prep"; + case vcl::O_fpgm: + return "fpgm"; + case vcl::O_gsub: + return "gsub"; + case vcl::O_CFF: + return "CFF "; + default: + return nullptr; + } +} + +bool Qt5TrueTypeFont::hasTable(sal_uInt32 ord) const +{ + const char* table_char = vclFontTableAsChar(ord); + if (!table_char) + return false; + if (m_aFontTable[ord].isEmpty()) + m_aFontTable[ord] = m_aRawFont.fontTable(table_char); + return !m_aFontTable[ord].isEmpty(); +} + +const sal_uInt8* Qt5TrueTypeFont::table(sal_uInt32 ord, sal_uInt32& size) const +{ + const char* table_char = vclFontTableAsChar(ord); + if (!table_char) + return nullptr; + if (m_aFontTable[ord].isEmpty()) + m_aFontTable[ord] = m_aRawFont.fontTable(table_char); + size = m_aFontTable[ord].size(); + return reinterpret_cast<const sal_uInt8*>(m_aFontTable[ord].data()); +} +} + +bool Qt5Graphics::CreateFontSubset(const OUString& rToFile, const PhysicalFontFace* pFontFace, + const sal_GlyphId* pGlyphIds, const sal_uInt8* pEncoding, + sal_Int32* pGlyphWidths, int nGlyphCount, FontSubsetInfo& rInfo) +{ + // prepare the requested file name for writing the font-subset file + OUString aSysPath; + if (osl_File_E_None != osl_getSystemPathFromFileURL(rToFile.pData, &aSysPath.pData)) + return false; + + // get the raw-bytes from the font to be subset + const QFont aFont = static_cast<const Qt5FontFace*>(pFontFace)->CreateFont(); + const QRawFont aRawFont(QRawFont::fromFont(aFont)); + const QFontInfo aFontInfo(aFont); + const OString aToFile(OUStringToOString(aSysPath, osl_getThreadTextEncoding())); + const int nOrigGlyphCount = nGlyphCount; + + // get details about the subsetted font + rInfo.m_nFontType = FontType::SFNT_TTF; + rInfo.m_aPSName = toOUString(aRawFont.familyName()); + rInfo.m_nCapHeight = aRawFont.capHeight(); + rInfo.m_nAscent = aRawFont.ascent(); + rInfo.m_nDescent = aRawFont.descent(); + + sal_uInt16 aShortIDs[nGlyphCount + 1]; + sal_uInt8 aTempEncs[nGlyphCount + 1]; + quint32 aQtGlyphId[nGlyphCount + 1]; + + int nNotDef = -1; + + for (int i = 0; i < nGlyphCount; ++i) + { + aTempEncs[i] = pEncoding[i]; + + sal_GlyphId aGlyphId(pGlyphIds[i]); + aShortIDs[i] = static_cast<sal_uInt16>(aGlyphId); + aQtGlyphId[i] = aShortIDs[i]; + if (!aGlyphId && nNotDef < 0) + nNotDef = i; // first NotDef glyph found + } + + if (nNotDef != 0) + { + // add fake NotDef glyph if needed + if (nNotDef < 0) + nNotDef = nGlyphCount++; + // NotDef glyph must be in pos 0 => swap glyphids + aShortIDs[nNotDef] = aShortIDs[0]; + aTempEncs[nNotDef] = aTempEncs[0]; + aQtGlyphId[nNotDef] = aQtGlyphId[0]; + aShortIDs[0] = 0; + aTempEncs[0] = 0; + aQtGlyphId[0] = 0; + } + + QPointF anAdvanceList[nGlyphCount]; + if (!aRawFont.advancesForGlyphIndexes(aQtGlyphId, anAdvanceList, nGlyphCount)) + return false; + + QPointF nNotDefAdv = anAdvanceList[0]; + anAdvanceList[0] = anAdvanceList[nNotDef]; + anAdvanceList[nNotDef] = nNotDefAdv; + + for (int i = 0; i < nOrigGlyphCount; ++i) + pGlyphWidths[i] = round(anAdvanceList[i].x()); + + // write subset into destination file + Qt5TrueTypeFont aTTF(aRawFont); + vcl::SFErrCodes nRC + = vcl::CreateTTFromTTGlyphs(&aTTF, aToFile.getStr(), aShortIDs, aTempEncs, nGlyphCount); + return (nRC == vcl::SFErrCodes::Ok); } const void* Qt5Graphics::GetEmbedFontData(const PhysicalFontFace*, long* /*pDataLen*/) |