summaryrefslogtreecommitdiffstats
path: root/vcl/inc/font
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /vcl/inc/font
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vcl/inc/font')
-rw-r--r--vcl/inc/font/DirectFontSubstitution.hxx68
-rw-r--r--vcl/inc/font/EmphasisMark.hxx45
-rw-r--r--vcl/inc/font/FeatureCollector.hxx49
-rw-r--r--vcl/inc/font/FontMetricData.hxx155
-rw-r--r--vcl/inc/font/FontSelectPattern.hxx86
-rw-r--r--vcl/inc/font/LogicalFontInstance.hxx167
-rw-r--r--vcl/inc/font/OpenTypeFeatureDefinitionList.hxx38
-rw-r--r--vcl/inc/font/OpenTypeFeatureStrings.hrc104
-rw-r--r--vcl/inc/font/PhysicalFontCollection.hxx103
-rw-r--r--vcl/inc/font/PhysicalFontFace.hxx213
-rw-r--r--vcl/inc/font/PhysicalFontFaceCollection.hxx48
-rw-r--r--vcl/inc/font/PhysicalFontFamily.hxx111
-rw-r--r--vcl/inc/font/fontsubstitution.hxx68
13 files changed, 1255 insertions, 0 deletions
diff --git a/vcl/inc/font/DirectFontSubstitution.hxx b/vcl/inc/font/DirectFontSubstitution.hxx
new file mode 100644
index 0000000000..150bc37281
--- /dev/null
+++ b/vcl/inc/font/DirectFontSubstitution.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <rtl/ustring.hxx>
+#include <unotools/fontdefs.hxx>
+
+#include <vcl/rendercontext/AddFontSubstituteFlags.hxx>
+
+#include <font/fontsubstitution.hxx>
+
+#include <string_view>
+#include <vector>
+
+namespace vcl::font
+{
+struct FontSubstEntry
+{
+ FontSubstEntry(std::u16string_view rFontName, std::u16string_view rSubstFontName,
+ AddFontSubstituteFlags nSubstFlags)
+ : maSearchName(GetEnglishSearchFontName(rFontName))
+ , maSearchReplaceName(GetEnglishSearchFontName(rSubstFontName))
+ , mnFlags(nSubstFlags)
+ {
+ }
+
+ OUString maSearchName;
+ OUString maSearchReplaceName;
+ AddFontSubstituteFlags mnFlags;
+};
+
+/** DirectFontSubstitution is for Tools->Options->FontReplacement and PsPrinter substitutions
+ The class is just a simple port of the unmaintainable manual-linked-list based mechanism
+ */
+// TODO: get rid of this class when the Tools->Options->FontReplacement tabpage is gone for good
+class DirectFontSubstitution final : public FontSubstitution
+{
+private:
+ std::vector<FontSubstEntry> maFontSubstList;
+
+public:
+ void AddFontSubstitute(const OUString& rFontName, const OUString& rSubstName,
+ AddFontSubstituteFlags nFlags);
+ void RemoveFontsSubstitute();
+ bool FindFontSubstitute(OUString& rSubstName, std::u16string_view rFontName) const;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/vcl/inc/font/EmphasisMark.hxx b/vcl/inc/font/EmphasisMark.hxx
new file mode 100644
index 0000000000..5e902da262
--- /dev/null
+++ b/vcl/inc/font/EmphasisMark.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <tools/fontenum.hxx>
+#include <tools/gen.hxx>
+#include <tools/long.hxx>
+#include <tools/poly.hxx>
+
+#include <vcl/dllapi.h>
+
+namespace vcl::font
+{
+class VCL_DLLPUBLIC EmphasisMark
+{
+public:
+ EmphasisMark(FontEmphasisMark eEmphasis, tools::Long nHeight, sal_Int32 nDPIY);
+
+ tools::PolyPolygon GetShape() const { return maPolyPoly; }
+ bool IsShapePolyLine() const { return mbIsPolyLine; }
+ tools::Rectangle GetRect1() const { return maRect1; }
+ tools::Rectangle GetRect2() const { return maRect2; }
+ tools::Long GetYOffset() const { return mnYOff; }
+ tools::Long GetWidth() const { return mnWidth; }
+
+private:
+ tools::PolyPolygon maPolyPoly;
+ bool mbIsPolyLine;
+ tools::Rectangle maRect1;
+ tools::Rectangle maRect2;
+ tools::Long mnYOff;
+ tools::Long mnWidth;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/vcl/inc/font/FeatureCollector.hxx b/vcl/inc/font/FeatureCollector.hxx
new file mode 100644
index 0000000000..1b71d02159
--- /dev/null
+++ b/vcl/inc/font/FeatureCollector.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include <vcl/font/Feature.hxx>
+#include <hb.h>
+#include <i18nlangtag/languagetag.hxx>
+
+#include <font/PhysicalFontFace.hxx>
+
+namespace vcl::font
+{
+class FeatureCollector
+{
+private:
+ const PhysicalFontFace* m_pFace;
+ hb_face_t* m_pHbFace;
+ std::vector<vcl::font::Feature>& m_rFontFeatures;
+ const LanguageTag& m_rLanguageTag;
+
+public:
+ FeatureCollector(const PhysicalFontFace* pFace, std::vector<vcl::font::Feature>& rFontFeatures,
+ const LanguageTag& rLanguageTag)
+ : m_pFace(pFace)
+ , m_pHbFace(pFace->GetHbFace())
+ , m_rFontFeatures(rFontFeatures)
+ , m_rLanguageTag(rLanguageTag)
+ {
+ }
+
+private:
+ void collectForTable(hb_tag_t aTableTag);
+ bool collectGraphite();
+
+public:
+ bool collect();
+};
+
+} // namespace vcl::font
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/font/FontMetricData.hxx b/vcl/inc/font/FontMetricData.hxx
new file mode 100644
index 0000000000..83eb77d54c
--- /dev/null
+++ b/vcl/inc/font/FontMetricData.hxx
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <vcl/dllapi.h>
+#include <tools/degree.hxx>
+#include <tools/long.hxx>
+#include <tools/ref.hxx>
+#include <fontattributes.hxx>
+
+class FontMetricData;
+typedef tools::SvRef<FontMetricData> FontMetricDataRef;
+
+class OutputDevice;
+namespace vcl::font
+{
+class FontSelectPattern;
+}
+class LogicalFontInstance;
+
+class VCL_DLLPUBLIC FontMetricData final : public FontAttributes, public SvRefBase
+{
+public:
+ explicit FontMetricData( const vcl::font::FontSelectPattern& );
+
+ // font instance attributes from the font request
+ tools::Long GetWidth() const { return mnWidth; }
+ Degree10 GetOrientation() const { return mnOrientation; }
+
+ void SetWidth(tools::Long nWidth) { mnWidth=nWidth; }
+ void SetOrientation(Degree10 nOrientation) { mnOrientation=nOrientation; }
+
+ // font metrics measured for the font instance
+ tools::Long GetAscent() const { return mnAscent; }
+ tools::Long GetDescent() const { return mnDescent; }
+ tools::Long GetInternalLeading() const { return mnIntLeading; }
+ tools::Long GetExternalLeading() const { return mnExtLeading; }
+ int GetSlant() const { return mnSlant; }
+ double GetMinKashida() const { return mnMinKashida; }
+ tools::Long GetHangingBaseline() const { return mnHangingBaseline; }
+
+ void SetSlant(int nSlant) { mnSlant=nSlant; }
+ void SetMinKashida(double nMinKashida ) { mnMinKashida=nMinKashida; }
+
+ // font attributes queried from the font instance
+ bool IsFullstopCentered() const { return mbFullstopCentered; }
+ tools::Long GetBulletOffset() const { return mnBulletOffset; }
+
+ void SetFullstopCenteredFlag(bool bFullstopCentered) { mbFullstopCentered = bFullstopCentered; }
+
+ // font metrics that are usually derived from the measurements
+ tools::Long GetUnderlineSize() const { return mnUnderlineSize; }
+ tools::Long GetUnderlineOffset() const { return mnUnderlineOffset; }
+ tools::Long GetBoldUnderlineSize() const { return mnBUnderlineSize; }
+ tools::Long GetBoldUnderlineOffset() const { return mnBUnderlineOffset; }
+ tools::Long GetDoubleUnderlineSize() const { return mnDUnderlineSize; }
+ tools::Long GetDoubleUnderlineOffset1() const { return mnDUnderlineOffset1; }
+ tools::Long GetDoubleUnderlineOffset2() const { return mnDUnderlineOffset2; }
+ tools::Long GetWavelineUnderlineSize() const { return mnWUnderlineSize; }
+ tools::Long GetWavelineUnderlineOffset() const { return mnWUnderlineOffset; }
+ tools::Long GetAboveUnderlineSize() const { return mnAboveUnderlineSize; }
+ tools::Long GetAboveUnderlineOffset() const { return mnAboveUnderlineOffset; }
+ tools::Long GetAboveBoldUnderlineSize() const { return mnAboveBUnderlineSize; }
+ tools::Long GetAboveBoldUnderlineOffset() const { return mnAboveBUnderlineOffset; }
+ tools::Long GetAboveDoubleUnderlineSize() const { return mnAboveDUnderlineSize; }
+ tools::Long GetAboveDoubleUnderlineOffset1() const { return mnAboveDUnderlineOffset1; }
+ tools::Long GetAboveDoubleUnderlineOffset2() const { return mnAboveDUnderlineOffset2; }
+ tools::Long GetAboveWavelineUnderlineSize() const { return mnAboveWUnderlineSize; }
+ tools::Long GetAboveWavelineUnderlineOffset() const { return mnAboveWUnderlineOffset; }
+ tools::Long GetStrikeoutSize() const { return mnStrikeoutSize; }
+ tools::Long GetStrikeoutOffset() const { return mnStrikeoutOffset; }
+ tools::Long GetBoldStrikeoutSize() const { return mnBStrikeoutSize; }
+ tools::Long GetBoldStrikeoutOffset() const { return mnBStrikeoutOffset; }
+ tools::Long GetDoubleStrikeoutSize() const { return mnDStrikeoutSize; }
+ tools::Long GetDoubleStrikeoutOffset1() const { return mnDStrikeoutOffset1; }
+ tools::Long GetDoubleStrikeoutOffset2() const { return mnDStrikeoutOffset2; }
+
+ void ImplInitTextLineSize( const OutputDevice* pDev );
+ void ImplInitAboveTextLineSize( const OutputDevice* pDev );
+ void ImplInitFlags( const OutputDevice* pDev );
+ void ImplCalcLineSpacing(LogicalFontInstance *pFontInstance);
+ void ImplInitBaselines(LogicalFontInstance *pFontInstance);
+
+private:
+ bool ShouldNotUseUnderlineMetrics() const;
+ bool ImplInitTextLineSizeHarfBuzz(LogicalFontInstance *pFontInstance);
+ bool ShouldUseWinMetrics(int, int, int, int, int, int) const;
+
+ // font instance attributes from the font request
+ tools::Long mnHeight; // Font size
+ tools::Long mnWidth; // Reference Width
+ Degree10 mnOrientation; // Rotation in 1/10 degrees
+
+ // font metrics measured for the font instance
+ tools::Long mnAscent; // Ascent
+ tools::Long mnDescent; // Descent
+ tools::Long mnIntLeading; // Internal Leading
+ tools::Long mnExtLeading; // External Leading
+ int mnSlant; // Slant (Italic/Oblique)
+ double mnMinKashida; // Minimal width of kashida (Arabic)
+ tools::Long mnHangingBaseline; // Offset of hanging baseline to Romn baseline
+
+ // font attributes queried from the font instance
+ bool mbFullstopCentered;
+ tools::Long mnBulletOffset; // Offset to position non-print character
+
+ // font metrics that are usually derived from the measurements
+ tools::Long mnUnderlineSize; // Lineheight of Underline
+ tools::Long mnUnderlineOffset; // Offset from Underline to Baseline
+ tools::Long mnBUnderlineSize; // Height of bold underline
+ tools::Long mnBUnderlineOffset; // Offset from bold underline to baseline
+ tools::Long mnDUnderlineSize; // Height of double underline
+ tools::Long mnDUnderlineOffset1; // Offset from double underline to baseline
+ tools::Long mnDUnderlineOffset2; // Offset from double underline to baseline
+ tools::Long mnWUnderlineSize; // Height of WaveLine underline
+ tools::Long mnWUnderlineOffset; // Offset from WaveLine underline to baseline, but centrered to WaveLine
+ tools::Long mnAboveUnderlineSize; // Height of single underline (for Vertical Right)
+ tools::Long mnAboveUnderlineOffset; // Offset from single underline to baseline (for Vertical Right)
+ tools::Long mnAboveBUnderlineSize; // Height of bold underline (for Vertical Right)
+ tools::Long mnAboveBUnderlineOffset; // Offset from bold underline to baseline (for Vertical Right)
+ tools::Long mnAboveDUnderlineSize; // Height of double underline (for Vertical Right)
+ tools::Long mnAboveDUnderlineOffset1; // Offset from double underline to baseline (for Vertical Right)
+ tools::Long mnAboveDUnderlineOffset2; // Offset from double underline to baseline (for Vertical Right)
+ tools::Long mnAboveWUnderlineSize; // Height of WaveLine-strike-out (for Vertical Right)
+ tools::Long mnAboveWUnderlineOffset; // Offset from WaveLine-strike-out to baseline, but centrered to the WaveLine (for Vertical Right)
+ tools::Long mnStrikeoutSize; // Height of single strike-out
+ tools::Long mnStrikeoutOffset; // Offset from single strike-out to baseline
+ tools::Long mnBStrikeoutSize; // Height of bold strike-out
+ tools::Long mnBStrikeoutOffset; // Offset of bold strike-out to baseline
+ tools::Long mnDStrikeoutSize; // Height of double strike-out
+ tools::Long mnDStrikeoutOffset1; // Offset of double strike-out to baseline
+ tools::Long mnDStrikeoutOffset2; // Offset of double strike-out to baseline
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/font/FontSelectPattern.hxx b/vcl/inc/font/FontSelectPattern.hxx
new file mode 100644
index 0000000000..8e21cf5696
--- /dev/null
+++ b/vcl/inc/font/FontSelectPattern.hxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <i18nlangtag/lang.h>
+#include <tools/degree.hxx>
+
+#include <vcl/vclenum.hxx>
+
+#include <fontattributes.hxx>
+
+#include <ostream>
+
+namespace vcl { class Font; }
+
+class LogicalFontInstance;
+class Size;
+
+namespace vcl::font
+{
+class PhysicalFontFace;
+
+class VCL_DLLPUBLIC FontSelectPattern : public FontAttributes
+{
+public:
+ FontSelectPattern(const vcl::Font&, OUString aSearchName,
+ const Size&, float fExactHeight, bool bNonAntialias = false);
+#ifdef _WIN32
+ FontSelectPattern( const PhysicalFontFace&, const Size&,
+ float fExactHeight, int nOrientation, bool bVertical );
+#endif
+
+ size_t hashCode() const;
+ bool operator==(const FontSelectPattern& rOther) const;
+ bool operator!=(const FontSelectPattern& rOther) const
+ {
+ return !(*this == rOther);
+ }
+
+ static const char FEAT_PREFIX;
+ static const char FEAT_SEPARATOR;
+
+public:
+ OUString maTargetName; // name of the font name token that is chosen
+ OUString maSearchName; // name of the font that matches best
+ int mnWidth; // width of font in pixel units
+ int mnHeight; // height of font in pixel units
+ float mfExactHeight; // requested height (in pixels with subpixel details)
+ Degree10 mnOrientation; // text orientation in 1/10 degree (0-3600)
+ LanguageType meLanguage; // text language
+ bool mbVertical; // vertical mode of requested font
+ bool mbNonAntialiased; // true if antialiasing is disabled
+
+ bool mbEmbolden; // Force emboldening
+ ItalicMatrix maItalicMatrix; // Force matrix for slant
+};
+}
+
+template< typename charT, typename traits >
+inline std::basic_ostream<charT, traits> & operator <<(
+ std::basic_ostream<charT, traits> & stream, const vcl::font::FontSelectPattern & rFSP)
+{
+ stream << (rFSP.maTargetName.isEmpty() ? "<default>" : rFSP.maTargetName)
+ << " (" << rFSP.maSearchName << ") w: " << rFSP.mnWidth << " h: "
+ << rFSP.mnHeight << " alias: " << rFSP.mbNonAntialiased;
+ return stream;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/font/LogicalFontInstance.hxx b/vcl/inc/font/LogicalFontInstance.hxx
new file mode 100644
index 0000000000..40d3c57c4e
--- /dev/null
+++ b/vcl/inc/font/LogicalFontInstance.hxx
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <o3tl/hash_combine.hxx>
+#include <rtl/ref.hxx>
+#include <salhelper/simplereferenceobject.hxx>
+#include <tools/gen.hxx>
+#include <tools/fontenum.hxx>
+#include <tools/degree.hxx>
+
+#include <font/FontSelectPattern.hxx>
+#include <font/FontMetricData.hxx>
+#include <glyphid.hxx>
+
+#include <optional>
+#include <unordered_map>
+
+#include <hb.h>
+
+class ConvertChar;
+class ImplFontCache;
+
+constexpr float ARTIFICIAL_ITALIC_MATRIX_XX = 1 << 16;
+constexpr float ARTIFICIAL_ITALIC_MATRIX_XY = (1 << 16) / 3.f;
+constexpr float ARTIFICIAL_ITALIC_SKEW = ARTIFICIAL_ITALIC_MATRIX_XY / ARTIFICIAL_ITALIC_MATRIX_XX;
+
+// extend std namespace to add custom hash needed for LogicalFontInstance
+
+namespace std
+{
+template <> struct hash<pair<sal_UCS4, FontWeight>>
+{
+ size_t operator()(const pair<sal_UCS4, FontWeight>& rData) const
+ {
+ std::size_t seed = 0;
+ o3tl::hash_combine(seed, rData.first);
+ o3tl::hash_combine(seed, rData.second);
+ return seed;
+ }
+};
+}
+
+// TODO: allow sharing of metrics for related fonts
+
+class VCL_PLUGIN_PUBLIC LogicalFontInstance : public salhelper::SimpleReferenceObject
+{
+ // just declaring the factory function doesn't work AKA
+ // friend LogicalFontInstance* PhysicalFontFace::CreateFontInstance(const FontSelectPattern&) const;
+ friend class vcl::font::PhysicalFontFace;
+ friend class ImplFontCache;
+
+public: // TODO: make data members private
+ virtual ~LogicalFontInstance() override;
+
+ FontMetricDataRef mxFontMetric; // Font attributes
+ const ConvertChar* mpConversion; // used e.g. for StarBats->StarSymbol
+
+ tools::Long mnLineHeight;
+ Degree10 mnOwnOrientation; // text angle if lower layers don't rotate text themselves
+ Degree10 mnOrientation; // text angle in 3600 system
+ bool mbInit; // true if maFontMetric member is valid
+
+ void AddFallbackForUnicode(sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName,
+ bool bEmbolden, const ItalicMatrix& rMatrix);
+ bool GetFallbackForUnicode(sal_UCS4 cInChar, FontWeight eInWeight, OUString* pOutFontName,
+ bool* pOutEmbolden, ItalicMatrix* pOutItalicMatrix) const;
+ void IgnoreFallbackForUnicode(sal_UCS4, FontWeight eWeight, std::u16string_view rFontName);
+
+ inline hb_font_t* GetHbFont();
+ bool IsGraphiteFont();
+ // NeedOffsetCorrection: Return if the font need offset correction in TTB direction.
+ // nYOffset is the original offset. It is used to check if the correction is necessary.
+ bool NeedOffsetCorrection(sal_Int32 nYOffset);
+ void SetAverageWidthFactor(double nFactor) { m_nAveWidthFactor = std::abs(nFactor); }
+ double GetAverageWidthFactor() const { return m_nAveWidthFactor; }
+ const vcl::font::FontSelectPattern& GetFontSelectPattern() const { return m_aFontSelData; }
+
+ const vcl::font::PhysicalFontFace* GetFontFace() const { return m_pFontFace.get(); }
+ vcl::font::PhysicalFontFace* GetFontFace() { return m_pFontFace.get(); }
+ const ImplFontCache* GetFontCache() const { return mpFontCache; }
+
+ bool GetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) const;
+ virtual bool GetGlyphOutline(sal_GlyphId, basegfx::B2DPolyPolygon&, bool) const = 0;
+ basegfx::B2DPolyPolygon GetGlyphOutlineUntransformed(sal_GlyphId) const;
+
+ sal_GlyphId GetGlyphIndex(uint32_t, uint32_t = 0) const;
+
+ double GetGlyphWidth(sal_GlyphId, bool = false, bool = true) const;
+
+ double GetKashidaWidth() const;
+
+ void GetScale(double* nXScale, double* nYScale) const;
+
+ bool NeedsArtificialItalic() const;
+ bool NeedsArtificialBold() const;
+
+protected:
+ explicit LogicalFontInstance(const vcl::font::PhysicalFontFace&,
+ const vcl::font::FontSelectPattern&);
+
+ hb_font_t* InitHbFont();
+ virtual void ImplInitHbFont(hb_font_t*) {}
+
+private:
+ hb_font_t* GetHbFontUntransformed() const;
+
+ struct MapEntry
+ {
+ OUString sFontName;
+ bool bEmbolden;
+ ItalicMatrix aItalicMatrix;
+ };
+ // cache of Unicode characters and replacement font names and attributes
+ // TODO: a fallback map can be shared with many other ImplFontEntries
+ // TODO: at least the ones which just differ in orientation, stretching or height
+ typedef ::std::unordered_map<::std::pair<sal_UCS4, FontWeight>, MapEntry> UnicodeFallbackList;
+ UnicodeFallbackList maUnicodeFallbackList;
+ mutable ImplFontCache* mpFontCache;
+ const vcl::font::FontSelectPattern m_aFontSelData;
+ hb_font_t* m_pHbFont;
+ mutable hb_font_t* m_pHbFontUntransformed = nullptr;
+ double m_nAveWidthFactor;
+ rtl::Reference<vcl::font::PhysicalFontFace> m_pFontFace;
+ std::optional<bool> m_xbIsGraphiteFont;
+
+ enum class FontFamilyEnum
+ {
+ Unclassified,
+ DFKaiSB
+ };
+
+ // The value is initialized and used in NeedOffsetCorrection().
+ std::optional<FontFamilyEnum> m_xeFontFamilyEnum;
+
+ mutable hb_draw_funcs_t* m_pHbDrawFuncs = nullptr;
+ basegfx::B2DPolygon m_aDrawPolygon;
+};
+
+inline hb_font_t* LogicalFontInstance::GetHbFont()
+{
+ if (!m_pHbFont)
+ m_pHbFont = InitHbFont();
+ return m_pHbFont;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/font/OpenTypeFeatureDefinitionList.hxx b/vcl/inc/font/OpenTypeFeatureDefinitionList.hxx
new file mode 100644
index 0000000000..1ae634deab
--- /dev/null
+++ b/vcl/inc/font/OpenTypeFeatureDefinitionList.hxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <vcl/dllapi.h>
+#include <vcl/font/Feature.hxx>
+#include <vector>
+#include <unordered_map>
+
+namespace vcl::font
+{
+class OpenTypeFeatureDefinitionListPrivate
+{
+private:
+ std::vector<FeatureDefinition> m_aFeatureDefinition;
+ std::unordered_map<sal_uInt32, size_t> m_aCodeToIndex;
+ std::vector<sal_uInt32> m_aRequiredFeatures;
+
+ void init();
+
+public:
+ OpenTypeFeatureDefinitionListPrivate();
+ FeatureDefinition getDefinition(vcl::font::Feature& rFeature);
+ bool isRequired(sal_uInt32 nFeatureCode);
+};
+
+VCL_DLLPUBLIC OpenTypeFeatureDefinitionListPrivate& OpenTypeFeatureDefinitionList();
+
+} // namespace vcl::font
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/font/OpenTypeFeatureStrings.hrc b/vcl/inc/font/OpenTypeFeatureStrings.hrc
new file mode 100644
index 0000000000..086d7d500c
--- /dev/null
+++ b/vcl/inc/font/OpenTypeFeatureStrings.hrc
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_VCL_INC_FONT_OPENTYPEFEATRESTRINGS_HRC
+#define INCLUDED_VCL_INC_FONT_OPENTYPEFEATRESTRINGS_HRC
+
+#define NC_(Context, String) TranslateId(Context, u8##String)
+
+#define STR_FONT_FEATURE_ID_AALT NC_("STR_FONT_FEATURE_ID_AALT", "Access All Alternates")
+#define STR_FONT_FEATURE_ID_AFRC NC_("STR_FONT_FEATURE_ID_AFRC", "Alternative (Vertical) Fractions")
+#define STR_FONT_FEATURE_ID_ALIG NC_("STR_FONT_FEATURE_ID_ALIG", "Ancient Ligatures")
+#define STR_FONT_FEATURE_ID_C2PC NC_("STR_FONT_FEATURE_ID_C2PC", "Capitals to Petite Capitals")
+#define STR_FONT_FEATURE_ID_C2SC NC_("STR_FONT_FEATURE_ID_C2SC", "Capitals to Small Capitals")
+#define STR_FONT_FEATURE_ID_CALT NC_("STR_FONT_FEATURE_ID_CALT", "Contextual Alternates")
+#define STR_FONT_FEATURE_ID_CASE NC_("STR_FONT_FEATURE_ID_CASE", "Case-Sensitive Forms")
+#define STR_FONT_FEATURE_ID_CLIG NC_("STR_FONT_FEATURE_ID_CLIG", "Contextual Ligatures")
+#define STR_FONT_FEATURE_ID_CPCT NC_("STR_FONT_FEATURE_ID_CPCT", "Centered CJK Punctuation")
+#define STR_FONT_FEATURE_ID_CPSP NC_("STR_FONT_FEATURE_ID_CPSP", "Capital Spacing")
+#define STR_FONT_FEATURE_ID_CSWH NC_("STR_FONT_FEATURE_ID_CSWH", "Contextual Swash")
+#define STR_FONT_FEATURE_ID_CVXX NC_("STR_FONT_FEATURE_ID_CVXX", "Character Variant %1")
+#define STR_FONT_FEATURE_ID_DCAP NC_("STR_FONT_FEATURE_ID_DCAP", "Drop Caps")
+#define STR_FONT_FEATURE_ID_DLIG NC_("STR_FONT_FEATURE_ID_DLIG", "Discretionary Ligatures")
+#define STR_FONT_FEATURE_ID_DNOM NC_("STR_FONT_FEATURE_ID_DNOM", "Denominators")
+#define STR_FONT_FEATURE_ID_DPNG NC_("STR_FONT_FEATURE_ID_DPNG", "Diphthongs (Obsolete)")
+#define STR_FONT_FEATURE_ID_EXPT NC_("STR_FONT_FEATURE_ID_EXPT", "Expert Forms")
+#define STR_FONT_FEATURE_ID_FALT NC_("STR_FONT_FEATURE_ID_FALT", "Final Glyph on Line Alternates")
+#define STR_FONT_FEATURE_ID_FRAC NC_("STR_FONT_FEATURE_ID_FRAC", "Fraction style")
+#define STR_FONT_FEATURE_ID_FWID NC_("STR_FONT_FEATURE_ID_FWID", "Full Widths")
+#define STR_FONT_FEATURE_ID_HALT NC_("STR_FONT_FEATURE_ID_HALT", "Alternate Half Widths")
+#define STR_FONT_FEATURE_ID_HIST NC_("STR_FONT_FEATURE_ID_HIST", "Historical Forms")
+#define STR_FONT_FEATURE_ID_HKNA NC_("STR_FONT_FEATURE_ID_HKNA", "Horizontal Kana Alternates")
+#define STR_FONT_FEATURE_ID_HLIG NC_("STR_FONT_FEATURE_ID_HLIG", "Historical Ligatures")
+#define STR_FONT_FEATURE_ID_HNGL NC_("STR_FONT_FEATURE_ID_HNGL", "Hanja to Hangul (Obsolete)")
+#define STR_FONT_FEATURE_ID_HOJO NC_("STR_FONT_FEATURE_ID_HOJO", "Hojo Kanji Forms (JIS X 0212-1990 Kanji Forms)")
+#define STR_FONT_FEATURE_ID_HWID NC_("STR_FONT_FEATURE_ID_HWID", "Half Widths")
+#define STR_FONT_FEATURE_ID_ITAL NC_("STR_FONT_FEATURE_ID_ITAL", "Italics")
+#define STR_FONT_FEATURE_ID_JALT NC_("STR_FONT_FEATURE_ID_JALT", "Justification Alternates")
+#define STR_FONT_FEATURE_ID_JP04 NC_("STR_FONT_FEATURE_ID_JP04", "JIS2004 Forms")
+#define STR_FONT_FEATURE_ID_JP78 NC_("STR_FONT_FEATURE_ID_JP78", "JIS78 Forms")
+#define STR_FONT_FEATURE_ID_JP83 NC_("STR_FONT_FEATURE_ID_JP83", "JIS83 Forms")
+#define STR_FONT_FEATURE_ID_JP90 NC_("STR_FONT_FEATURE_ID_JP90", "JIS90 Forms")
+#define STR_FONT_FEATURE_ID_KERN NC_("STR_FONT_FEATURE_ID_KERN", "Horizontal Kerning")
+#define STR_FONT_FEATURE_ID_LFBD NC_("STR_FONT_FEATURE_ID_LFBD", "Left Bounds")
+#define STR_FONT_FEATURE_ID_LIGA NC_("STR_FONT_FEATURE_ID_LIGA", "Standard Ligatures")
+#define STR_FONT_FEATURE_ID_LNUM NC_("STR_FONT_FEATURE_ID_LNUM", "Lining Figures")
+#define STR_FONT_FEATURE_ID_MGRK NC_("STR_FONT_FEATURE_ID_MGRK", "Mathematical Greek")
+#define STR_FONT_FEATURE_ID_NALT NC_("STR_FONT_FEATURE_ID_NALT", "Alternate Annotation Forms")
+#define STR_FONT_FEATURE_ID_NLCK NC_("STR_FONT_FEATURE_ID_NLCK", "NLC Kanji Forms")
+#define STR_FONT_FEATURE_ID_NUMR NC_("STR_FONT_FEATURE_ID_NUMR", "Numerators")
+#define STR_FONT_FEATURE_ID_ONUM NC_("STR_FONT_FEATURE_ID_ONUM", "Oldstyle Figures")
+#define STR_FONT_FEATURE_ID_OPBD NC_("STR_FONT_FEATURE_ID_OPBD", "Optical Bounds")
+#define STR_FONT_FEATURE_ID_ORDN NC_("STR_FONT_FEATURE_ID_ORDN", "Ordinals")
+#define STR_FONT_FEATURE_ID_ORNM NC_("STR_FONT_FEATURE_ID_ORNM", "Ornaments")
+#define STR_FONT_FEATURE_ID_PALT NC_("STR_FONT_FEATURE_ID_PALT", "Proportional Alternate Metrics")
+#define STR_FONT_FEATURE_ID_PCAP NC_("STR_FONT_FEATURE_ID_PCAP", "Lowercase to Petite Capitals")
+#define STR_FONT_FEATURE_ID_PKNA NC_("STR_FONT_FEATURE_ID_PKNA", "Proportional Kana")
+#define STR_FONT_FEATURE_ID_PNUM NC_("STR_FONT_FEATURE_ID_PNUM", "Proportional Numbers")
+#define STR_FONT_FEATURE_ID_PWID NC_("STR_FONT_FEATURE_ID_PWID", "Proportional Widths")
+#define STR_FONT_FEATURE_ID_QWID NC_("STR_FONT_FEATURE_ID_QWID", "Quarter Widths")
+#define STR_FONT_FEATURE_ID_RTBD NC_("STR_FONT_FEATURE_ID_RTBD", "Right Bounds")
+#define STR_FONT_FEATURE_ID_RUBY NC_("STR_FONT_FEATURE_ID_RUBY", "Ruby Notation Forms")
+#define STR_FONT_FEATURE_ID_SALT NC_("STR_FONT_FEATURE_ID_SALT", "Stylistic Alternates")
+#define STR_FONT_FEATURE_ID_SINF NC_("STR_FONT_FEATURE_ID_SINF", "Scientific Inferiors")
+#define STR_FONT_FEATURE_ID_SMCP NC_("STR_FONT_FEATURE_ID_SMCP", "Lowercase to Small Capitals")
+#define STR_FONT_FEATURE_ID_SMPL NC_("STR_FONT_FEATURE_ID_SMPL", "Simplified Forms")
+#define STR_FONT_FEATURE_ID_SSXX NC_("STR_FONT_FEATURE_ID_SSXX", "Stylistic Set %1")
+#define STR_FONT_FEATURE_ID_SUBS NC_("STR_FONT_FEATURE_ID_SUBS", "Subscript")
+#define STR_FONT_FEATURE_ID_SUPS NC_("STR_FONT_FEATURE_ID_SUPS", "Superscript")
+#define STR_FONT_FEATURE_ID_SWSH NC_("STR_FONT_FEATURE_ID_SWSH", "Swash")
+#define STR_FONT_FEATURE_ID_TITL NC_("STR_FONT_FEATURE_ID_TITL", "Titling")
+#define STR_FONT_FEATURE_ID_TNAM NC_("STR_FONT_FEATURE_ID_TNAM", "Traditional Name Forms")
+#define STR_FONT_FEATURE_ID_TNUM NC_("STR_FONT_FEATURE_ID_TNUM", "Tabular Numbers")
+#define STR_FONT_FEATURE_ID_TRAD NC_("STR_FONT_FEATURE_ID_TRAD", "Traditional Forms")
+#define STR_FONT_FEATURE_ID_TWID NC_("STR_FONT_FEATURE_ID_TWID", "Third Widths")
+#define STR_FONT_FEATURE_ID_UNIC NC_("STR_FONT_FEATURE_ID_UNIC", "Unicase")
+#define STR_FONT_FEATURE_ID_VALT NC_("STR_FONT_FEATURE_ID_VALT", "Alternate Vertical Metrics")
+#define STR_FONT_FEATURE_ID_VHAL NC_("STR_FONT_FEATURE_ID_VHAL", "Alternate Vertical Half Metrics")
+#define STR_FONT_FEATURE_ID_VKNA NC_("STR_FONT_FEATURE_ID_VKNA", "Vertical Kana Alternates")
+#define STR_FONT_FEATURE_ID_VKRN NC_("STR_FONT_FEATURE_ID_VKRN", "Vertical Kerning")
+#define STR_FONT_FEATURE_ID_VPAL NC_("STR_FONT_FEATURE_ID_VPAL", "Proportional Alternate Vertical Metrics")
+#define STR_FONT_FEATURE_ID_VRT2 NC_("STR_FONT_FEATURE_ID_VRT2", "Vertical Alternates and Rotation")
+#define STR_FONT_FEATURE_ID_VRTR NC_("STR_FONT_FEATURE_ID_VRTR", "Vertical Alternates for Rotation")
+#define STR_FONT_FEATURE_ID_ZERO NC_("STR_FONT_FEATURE_ID_ZERO", "Slashed Zero")
+#define STR_FONT_FEATURE_PARAM_NONE NC_("STR_FONT_FEATURE_PARAM_NONE", "None")
+
+#endif // INCLUDED_VCL_INC_STRINGS_HRC
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/font/PhysicalFontCollection.hxx b/vcl/inc/font/PhysicalFontCollection.hxx
new file mode 100644
index 0000000000..d791f7b692
--- /dev/null
+++ b/vcl/inc/font/PhysicalFontCollection.hxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <vcl/dllapi.h>
+
+#include <font/LogicalFontInstance.hxx>
+
+#include "PhysicalFontFamily.hxx"
+
+#include <array>
+#include <string_view>
+
+#define MAX_GLYPHFALLBACK 16
+
+namespace vcl::font
+{
+class GlyphFallbackFontSubstitution;
+class PreMatchFontSubstitution;
+}
+
+// TODO: merge with ImplFontCache
+// TODO: rename to LogicalFontManager
+
+namespace vcl::font
+{
+
+class VCL_PLUGIN_PUBLIC PhysicalFontCollection final
+{
+public:
+ explicit PhysicalFontCollection();
+ ~PhysicalFontCollection();
+
+ // fill the list with device font faces
+ void Add( vcl::font::PhysicalFontFace* );
+ void Clear();
+ int Count() const { return maPhysicalFontFamilies.size(); }
+
+ // find the device font family
+ vcl::font::PhysicalFontFamily* FindFontFamily( std::u16string_view rFontName ) const;
+ vcl::font::PhysicalFontFamily* FindOrCreateFontFamily( const OUString &rFamilyName );
+ vcl::font::PhysicalFontFamily* FindFontFamily( vcl::font::FontSelectPattern& ) const;
+ vcl::font::PhysicalFontFamily* FindFontFamilyByTokenNames(std::u16string_view rTokenStr) const;
+ vcl::font::PhysicalFontFamily* FindFontFamilyByAttributes(ImplFontAttrs nSearchType, FontWeight, FontWidth,
+ FontItalic, std::u16string_view rSearchFamily) const;
+
+ // suggest fonts for glyph fallback
+ vcl::font::PhysicalFontFamily* GetGlyphFallbackFont( vcl::font::FontSelectPattern&,
+ LogicalFontInstance* pLogicalFont,
+ OUString& rMissingCodes, int nFallbackLevel ) const;
+
+ // prepare platform specific font substitutions
+ void SetPreMatchHook( vcl::font::PreMatchFontSubstitution* );
+ void SetFallbackHook( vcl::font::GlyphFallbackFontSubstitution* );
+
+ // misc utilities
+ std::shared_ptr<PhysicalFontCollection> Clone() const;
+ std::unique_ptr<vcl::font::PhysicalFontFaceCollection> GetFontFaceCollection() const;
+
+private:
+ mutable bool mbMatchData; // true if matching attributes are initialized
+
+ typedef std::unordered_map<OUString, std::unique_ptr<vcl::font::PhysicalFontFamily>> PhysicalFontFamilies;
+ PhysicalFontFamilies maPhysicalFontFamilies;
+
+ vcl::font::PreMatchFontSubstitution* mpPreMatchHook; // device specific prematch substitution
+ vcl::font::GlyphFallbackFontSubstitution* mpFallbackHook; // device specific glyph fallback substitution
+
+ mutable std::unique_ptr<std::array<vcl::font::PhysicalFontFamily*,MAX_GLYPHFALLBACK>> mpFallbackList;
+ mutable int mnFallbackCount;
+
+ void ImplInitMatchData() const;
+ void ImplInitGenericGlyphFallback() const;
+
+ vcl::font::PhysicalFontFamily* ImplFindFontFamilyBySearchName( const OUString& ) const;
+ vcl::font::PhysicalFontFamily* ImplFindFontFamilyBySubstFontAttr( const utl::FontNameAttr& ) const;
+
+ vcl::font::PhysicalFontFamily* ImplFindFontFamilyOfDefaultFont() const;
+
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/vcl/inc/font/PhysicalFontFace.hxx b/vcl/inc/font/PhysicalFontFace.hxx
new file mode 100644
index 0000000000..1fce6a6cba
--- /dev/null
+++ b/vcl/inc/font/PhysicalFontFace.hxx
@@ -0,0 +1,213 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <i18nlangtag/languagetag.hxx>
+#include <rtl/ref.hxx>
+#include <salhelper/simplereferenceobject.hxx>
+#include <tools/color.hxx>
+#include <vcl/dllapi.h>
+#include <vcl/fontcapabilities.hxx>
+#include <vcl/fontcharmap.hxx>
+
+#include <fontattributes.hxx>
+#include <fontsubset.hxx>
+
+#include <hb.h>
+#include <hb-ot.h>
+
+class LogicalFontInstance;
+struct FontMatchStatus;
+namespace vcl::font
+{
+class FontSelectPattern;
+}
+
+namespace vcl
+{
+class PhysicalFontFamily;
+}
+
+namespace vcl::font
+{
+class FontSelectPattern;
+
+struct FontMatchStatus
+{
+public:
+ int mnFaceMatch;
+ const OUString* mpTargetStyleName;
+};
+
+struct RawFontData
+{
+public:
+ RawFontData(hb_blob_t* pBlob = nullptr)
+ : mpBlob(pBlob ? pBlob : hb_blob_get_empty())
+ {
+ }
+
+ RawFontData(const RawFontData& rOther)
+ : mpBlob(hb_blob_reference(rOther.mpBlob))
+ {
+ }
+
+ ~RawFontData() { hb_blob_destroy(mpBlob); }
+
+ RawFontData& operator=(const RawFontData& rOther)
+ {
+ hb_blob_destroy(mpBlob);
+ mpBlob = hb_blob_reference(rOther.mpBlob);
+ return *this;
+ }
+
+ size_t size() const { return hb_blob_get_length(mpBlob); }
+ bool empty() const { return size() == 0; }
+ const uint8_t* data() const
+ {
+ return reinterpret_cast<const uint8_t*>(hb_blob_get_data(mpBlob, nullptr));
+ }
+
+private:
+ hb_blob_t* mpBlob;
+};
+
+struct ColorLayer
+{
+ sal_GlyphId nGlyphIndex;
+ uint32_t nColorIndex;
+};
+
+typedef std::vector<Color> ColorPalette;
+
+// https://learn.microsoft.com/en-us/typography/opentype/spec/name#name-ids
+typedef enum : hb_ot_name_id_t {
+ NAME_ID_COPYRIGHT = 0,
+ NAME_ID_FONT_FAMILY = 1,
+ NAME_ID_FONT_SUBFAMILY = 2,
+ NAME_ID_UNIQUE_ID = 3,
+ NAME_ID_FULL_NAME = 4,
+ NAME_ID_VERSION_STRING = 5,
+ NAME_ID_POSTSCRIPT_NAME = 6,
+ NAME_ID_TRADEMARK = 7,
+ NAME_ID_MANUFACTURER = 8,
+ NAME_ID_DESIGNER = 9,
+ NAME_ID_DESCRIPTION = 10,
+ NAME_ID_VENDOR_URL = 11,
+ NAME_ID_DESIGNER_URL = 12,
+ NAME_ID_LICENSE = 13,
+ NAME_ID_LICENSE_URL = 14,
+ //NAME_ID_RESERVED = 15,
+ NAME_ID_TYPOGRAPHIC_FAMILY = 16,
+ NAME_ID_TYPOGRAPHIC_SUBFAMILY = 17,
+ NAME_ID_MAC_FULL_NAME = 18,
+ NAME_ID_SAMPLE_TEXT = 19,
+ NAME_ID_CID_FINDFONT_NAME = 20,
+ NAME_ID_WWS_FAMILY = 21,
+ NAME_ID_WWS_SUBFAMILY = 22,
+ NAME_ID_LIGHT_BACKGROUND = 23,
+ NAME_ID_DARK_BACKGROUND = 24,
+ NAME_ID_VARIATIONS_PS_PREFIX = 25,
+} NameID;
+
+// TODO: no more direct access to members
+// TODO: get rid of height/width for scalable fonts
+// TODO: make cloning cheaper
+
+/**
+ * abstract base class for physical font faces
+ *
+ * It acts as a factory for its corresponding LogicalFontInstances and
+ * can be extended to cache device and font instance specific data.
+ */
+class VCL_PLUGIN_PUBLIC PhysicalFontFace : public FontAttributes,
+ public salhelper::SimpleReferenceObject
+{
+public:
+ ~PhysicalFontFace();
+
+ virtual rtl::Reference<LogicalFontInstance>
+ CreateFontInstance(const vcl::font::FontSelectPattern&) const = 0;
+
+ virtual sal_IntPtr GetFontId() const = 0;
+ virtual FontCharMapRef GetFontCharMap() const;
+ virtual bool GetFontCapabilities(vcl::FontCapabilities&) const;
+
+ RawFontData GetRawFontData(uint32_t) const;
+
+ bool IsBetterMatch(const vcl::font::FontSelectPattern&, FontMatchStatus&) const;
+ sal_Int32 CompareIgnoreSize(const PhysicalFontFace&) const;
+
+ // CreateFontSubset: a method to get a subset of glyphs of a font inside a
+ // new valid font file
+ // returns true if creation of subset was successful
+ // parameters: rOutBuffer: vector to write the subset to
+ // pGlyphIDs: the glyph ids to be extracted
+ // pEncoding: the character code corresponding to each glyph
+ // nGlyphs: the number of glyphs
+ // rInfo: additional outgoing information
+ // implementation note: encoding 0 with glyph id 0 should be added implicitly
+ // as "undefined character"
+ bool CreateFontSubset(std::vector<sal_uInt8>&, const sal_GlyphId*, const sal_uInt8*, const int,
+ FontSubsetInfo&) const;
+
+ bool IsColorFont() const { return HasColorLayers() || HasColorBitmaps(); }
+
+ bool HasColorLayers() const;
+ std::vector<ColorLayer> GetGlyphColorLayers(sal_GlyphId) const;
+
+ const std::vector<ColorPalette>& GetColorPalettes() const;
+
+ bool HasColorBitmaps() const;
+ RawFontData GetGlyphColorBitmap(sal_GlyphId, tools::Rectangle&) const;
+
+ OString GetGlyphName(sal_GlyphId, bool = false) const;
+
+ uint32_t UnitsPerEm() const { return hb_face_get_upem(GetHbFace()); }
+
+ OUString GetName(NameID, const LanguageTag&) const;
+ OUString GetName(NameID aNameID) const { return GetName(aNameID, LanguageTag(LANGUAGE_NONE)); }
+
+ virtual hb_face_t* GetHbFace() const;
+ virtual hb_blob_t* GetHbTable(hb_tag_t) const
+ {
+ assert(false);
+ return nullptr;
+ }
+
+ virtual const std::vector<hb_variation_t>& GetVariations(const LogicalFontInstance&) const;
+
+protected:
+ mutable hb_face_t* mpHbFace;
+ mutable hb_font_t* mpHbUnscaledFont;
+ mutable FontCharMapRef mxCharMap;
+ mutable std::optional<vcl::FontCapabilities> mxFontCapabilities;
+ mutable std::optional<std::vector<ColorPalette>> mxColorPalettes;
+ mutable std::optional<std::vector<hb_variation_t>> mxVariations;
+
+ explicit PhysicalFontFace(const FontAttributes&);
+
+ hb_font_t* GetHbUnscaledFont() const;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/font/PhysicalFontFaceCollection.hxx b/vcl/inc/font/PhysicalFontFaceCollection.hxx
new file mode 100644
index 0000000000..8208af44c4
--- /dev/null
+++ b/vcl/inc/font/PhysicalFontFaceCollection.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include "PhysicalFontFace.hxx"
+
+#include <vector>
+
+/**
+ A PhysicalFontFaceCollection is created by a PhysicalFontCollection and
+ becomes invalid when original PhysicalFontCollection is modified.
+ */
+
+namespace vcl::font
+{
+class PhysicalFontFaceCollection
+{
+private:
+ std::vector<rtl::Reference<PhysicalFontFace>> maDevFontVector;
+
+public:
+ PhysicalFontFaceCollection() { maDevFontVector.reserve(1024); }
+ void Add(PhysicalFontFace* pFace) { maDevFontVector.push_back(pFace); }
+ PhysicalFontFace* Get(int nIndex) const { return maDevFontVector[nIndex].get(); }
+ int Count() const { return maDevFontVector.size(); }
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/vcl/inc/font/PhysicalFontFamily.hxx b/vcl/inc/font/PhysicalFontFamily.hxx
new file mode 100644
index 0000000000..a944ed72fe
--- /dev/null
+++ b/vcl/inc/font/PhysicalFontFamily.hxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <vcl/dllapi.h>
+#include <vcl/outdev.hxx>
+
+#include <unotools/fontcfg.hxx>
+
+namespace vcl::font
+{
+// flags for mnTypeFaces member
+enum class FontTypeFaces
+{
+ NONE = 0x00,
+ Scalable = 0x01,
+ Symbol = 0x02,
+ NoneSymbol = 0x04,
+ Light = 0x08,
+ Bold = 0x10,
+ Normal = 0x20,
+ NoneItalic = 0x40,
+ Italic = 0x80
+};
+}
+namespace o3tl
+{
+template <>
+struct typed_flags<vcl::font::FontTypeFaces> : is_typed_flags<vcl::font::FontTypeFaces, 0xff>
+{
+};
+};
+
+namespace vcl::font
+{
+class FontSelectPattern;
+class PhysicalFontCollection;
+class PhysicalFontFace;
+class PhysicalFontFaceCollection;
+
+class VCL_PLUGIN_PUBLIC PhysicalFontFamily
+{
+public:
+ PhysicalFontFamily(OUString aSearchName);
+ ~PhysicalFontFamily();
+
+ // Avoid implicitly defined copy constructors/assignments for the DLLPUBLIC class (they may
+ // require forward-declared classes used internally to be defined in places using this)
+ PhysicalFontFamily(const PhysicalFontFamily&) = delete;
+ PhysicalFontFamily(PhysicalFontFamily&&) = delete;
+ PhysicalFontFamily& operator=(const PhysicalFontFamily&) = delete;
+ PhysicalFontFamily& operator=(PhysicalFontFamily&&) = delete;
+
+ const OUString& GetFamilyName() const { return maFamilyName; }
+ const OUString& GetSearchName() const { return maSearchName; }
+ int GetMinQuality() const { return mnMinQuality; }
+ FontTypeFaces GetTypeFaces() const { return mnTypeFaces; }
+
+ const OUString& GetMatchFamilyName() const { return maMatchFamilyName; }
+ ImplFontAttrs GetMatchType() const { return mnMatchType; }
+ FontWeight GetMatchWeight() const { return meMatchWeight; }
+ FontWidth GetMatchWidth() const { return meMatchWidth; }
+ void InitMatchData(const utl::FontSubstConfiguration&, const OUString& rSearchName);
+
+ void AddFontFace(PhysicalFontFace*);
+
+ PhysicalFontFace* FindBestFontFace(const vcl::font::FontSelectPattern& rFSD) const;
+
+ void UpdateDevFontList(PhysicalFontFaceCollection&) const;
+ void UpdateCloneFontList(PhysicalFontCollection&) const;
+
+ static void CalcType(ImplFontAttrs& rType, FontWeight& rWeight, FontWidth& rWidth,
+ FontFamily eFamily, const utl::FontNameAttr* pFontAttr);
+
+private:
+ std::vector<rtl::Reference<PhysicalFontFace>> maFontFaces;
+
+ OUString maFamilyName; // original font family name
+ OUString maSearchName; // normalized font family name
+ FontTypeFaces mnTypeFaces; // Typeface Flags
+ FontFamily meFamily;
+ FontPitch mePitch;
+ int mnMinQuality; // quality of the worst font face
+
+ ImplFontAttrs mnMatchType; // MATCH - Type
+ OUString maMatchFamilyName; // MATCH - FamilyName
+ FontWeight meMatchWeight; // MATCH - Weight
+ FontWidth meMatchWidth; // MATCH - Width
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/vcl/inc/font/fontsubstitution.hxx b/vcl/inc/font/fontsubstitution.hxx
new file mode 100644
index 0000000000..f7befca4c3
--- /dev/null
+++ b/vcl/inc/font/fontsubstitution.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+// nowadays these substitutions are needed for backward compatibility and tight platform integration:
+// - substitutions from configuration entries (Tools->Options->FontReplacement and/or fontconfig)
+// - device specific substitutions (e.g. for PS printer builtin fonts)
+// - substitutions for missing fonts defined by configuration entries (generic and/or platform dependent fallbacks)
+// - substitutions for missing fonts defined by multi-token fontnames (e.g. fontname="SpecialFont;FallbackA;FallbackB")
+// - substitutions for incomplete fonts (implicit, generic, EUDC and/or platform dependent fallbacks)
+// - substitutions for missing symbol fonts by translating code points into other symbol fonts
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <rtl/ustring.hxx>
+
+#include <font/FontSelectPattern.hxx>
+
+namespace vcl::font
+{
+class FontSelectPattern;
+
+class FontSubstitution
+{
+ // TODO: there is more commonality between the different substitutions
+protected:
+ virtual ~FontSubstitution() {}
+};
+
+/// Abstracts the concept of finding the best font to support an incomplete font
+class GlyphFallbackFontSubstitution : public FontSubstitution
+{
+public:
+ virtual bool FindFontSubstitute(vcl::font::FontSelectPattern&,
+ LogicalFontInstance* pLogicalFont,
+ OUString& rMissingCodes) const = 0;
+};
+
+/** Abstracts the concept of a configured font substitution before the
+ availability of the originally selected font has been checked.
+ */
+class PreMatchFontSubstitution : public FontSubstitution
+{
+public:
+ virtual bool FindFontSubstitute(vcl::font::FontSelectPattern&) const = 0;
+};
+
+void ImplFontSubstitute(OUString& rFontName);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */