solenv/clang-format/excludelist     |    2 
 vcl/Library_vcl.mk                  |    4 
 vcl/Library_vclplug_osx.mk          |    4 
 vcl/inc/quartz/CoreTextFont.hxx     |   74 ++++++++++
 vcl/inc/quartz/CoreTextFontFace.hxx |   69 +++++++++
 vcl/inc/quartz/SystemFontList.hxx   |   50 ++++++-
 vcl/inc/quartz/salgdi.h             |   73 ----------
 vcl/osx/saldata.cxx                 |    1 
 vcl/quartz/CoreTextFont.cxx         |  235 +++++++++++++++++++++++++++++++++
 vcl/quartz/CoreTextFontFace.cxx     |   98 ++++++++++++++
 vcl/quartz/SystemFontList.cxx       |  251 ------------------------------------
 vcl/quartz/salgdi.cxx               |   22 ---
 vcl/skia/osx/gdiimpl.cxx            |    3 
 13 files changed, 536 insertions(+), 350 deletions(-)

New commits:
commit 3b7eb222411da48a9b7a585b39ef7a240f6222bc
Author:     Khaled Hosny <[email protected]>
AuthorDate: Wed Aug 9 12:03:06 2023 +0300
Commit:     خالد حسني <[email protected]>
CommitDate: Wed Aug 9 12:42:57 2023 +0200

    vcl: Organize CoreText font code a bit
    
    The code was all over the place with classes split between files or
    grouped in some files and I couldn’t make a head or tail of it. Move
    each class to a dedicated source/header file.
    
    Change-Id: I35daa05b4684c13339c637819dc30fa47a60cf65
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155503
    Tested-by: Jenkins
    Reviewed-by: خالد حسني <[email protected]>

diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist
index 64eded82acab..ce890e04fb61 100644
--- a/solenv/clang-format/excludelist
+++ b/solenv/clang-format/excludelist
@@ -14558,7 +14558,7 @@ vcl/qa/cppunit/graphicfilter/filters-tga-test.cxx
 vcl/qa/cppunit/lifecycle.cxx
 vcl/qa/cppunit/svm/svmtest.cxx
 vcl/qa/cppunit/timer.cxx
-vcl/quartz/ctfonts.cxx
+vcl/quartz/SystemFontList.cxx
 vcl/quartz/salbmp.cxx
 vcl/quartz/salgdi.cxx
 vcl/quartz/salgdicommon.cxx
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index c29801fe58a3..f56c913f656f 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -688,7 +688,9 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/ios/iOSTransferable \
     vcl/ios/DataFlavorMapping \
     vcl/ios/HtmlFmtFlt \
-    vcl/quartz/ctfonts \
+    vcl/quartz/CoreTextFont \
+    vcl/quartz/CoreTextFontFace \
+    vcl/quartz/SystemFontList \
     vcl/quartz/salbmp \
     vcl/quartz/salgdi \
     vcl/quartz/salgdicommon \
diff --git a/vcl/Library_vclplug_osx.mk b/vcl/Library_vclplug_osx.mk
index fbb0e68ec904..0545af8dd33a 100644
--- a/vcl/Library_vclplug_osx.mk
+++ b/vcl/Library_vclplug_osx.mk
@@ -134,7 +134,9 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_osx,\
     vcl/osx/salsys \
     vcl/osx/saltimer \
     vcl/osx/service_entry \
-    vcl/quartz/ctfonts \
+    vcl/quartz/CoreTextFont \
+    vcl/quartz/CoreTextFontFace \
+    vcl/quartz/SystemFontList \
     vcl/quartz/salbmp \
     vcl/quartz/salgdi \
     vcl/quartz/salgdicommon \
diff --git a/vcl/inc/quartz/CoreTextFont.hxx b/vcl/inc/quartz/CoreTextFont.hxx
new file mode 100644
index 000000000000..90cf6416772c
--- /dev/null
+++ b/vcl/inc/quartz/CoreTextFont.hxx
@@ -0,0 +1,74 @@
+/* -*- 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 <premac.h>
+#ifdef MACOSX
+#include <ApplicationServices/ApplicationServices.h>
+#include <osx/osxvcltypes.h>
+#include <osx/salframe.h>
+#else
+#include <CoreGraphics/CoreGraphics.h>
+#include <CoreText/CoreText.h>
+#endif
+#include <postmac.h>
+
+#ifdef IOS
+// iOS defines a different Point class so include salgeom.hxx after postmac.h
+// so that it will use the Point class in tools/gen.hxx
+#include "salgeom.hxx"
+#endif
+
+#include <font/LogicalFontInstance.hxx>
+#include <font/FontMetricData.hxx>
+#include <salgdi.hxx>
+
+#include <quartz/salgdicommon.hxx>
+
+#include <quartz/CGHelpers.hxx>
+#include <quartz/CoreTextFontFace.hxx>
+
+class CoreTextFont final : public LogicalFontInstance
+{
+    friend rtl::Reference<LogicalFontInstance>
+    CoreTextFontFace::CreateFontInstance(const vcl::font::FontSelectPattern&) 
const;
+
+public:
+    ~CoreTextFont() override;
+
+    void GetFontMetric(FontMetricDataRef const&);
+    bool GetGlyphOutline(sal_GlyphId, basegfx::B2DPolyPolygon&, bool) const 
override;
+
+    CTFontRef GetCTFont() const { return mpCTFont; }
+
+    /// <1.0: font is squeezed, >1.0 font is stretched, else 1.0
+    float mfFontStretch;
+    /// text rotation in radian
+    float mfFontRotation;
+
+private:
+    explicit CoreTextFont(const CoreTextFontFace&, const 
vcl::font::FontSelectPattern&);
+
+    CTFontRef mpCTFont;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/quartz/CoreTextFontFace.hxx 
b/vcl/inc/quartz/CoreTextFontFace.hxx
new file mode 100644
index 000000000000..482b0b700dae
--- /dev/null
+++ b/vcl/inc/quartz/CoreTextFontFace.hxx
@@ -0,0 +1,69 @@
+/* -*- 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 <vector>
+
+#include <premac.h>
+#ifdef MACOSX
+#include <ApplicationServices/ApplicationServices.h>
+#include <osx/osxvcltypes.h>
+#include <osx/salframe.h>
+#else
+#include <CoreGraphics/CoreGraphics.h>
+#include <CoreText/CoreText.h>
+#endif
+#include <postmac.h>
+
+#include <font/LogicalFontInstance.hxx>
+#include <font/PhysicalFontFace.hxx>
+#include <salgdi.hxx>
+
+#include <quartz/salgdicommon.hxx>
+#include <hb.h>
+
+class AquaSalFrame;
+class FontAttributes;
+
+// CoreText-specific physically available font face
+class CoreTextFontFace final : public vcl::font::PhysicalFontFace
+{
+public:
+    CoreTextFontFace(const FontAttributes&, CTFontDescriptorRef xRef);
+    ~CoreTextFontFace() override;
+
+    sal_IntPtr GetFontId() const override;
+
+    CTFontDescriptorRef GetFontDescriptorRef() const { return 
mxFontDescriptor; }
+
+    rtl::Reference<LogicalFontInstance>
+    CreateFontInstance(const vcl::font::FontSelectPattern&) const override;
+
+    hb_blob_t* GetHbTable(hb_tag_t nTag) const override;
+
+    const std::vector<hb_variation_t>& GetVariations(const 
LogicalFontInstance&) const override;
+
+private:
+    CTFontDescriptorRef mxFontDescriptor;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/quartz/ctfonts.hxx b/vcl/inc/quartz/SystemFontList.hxx
similarity index 53%
rename from vcl/inc/quartz/ctfonts.hxx
rename to vcl/inc/quartz/SystemFontList.hxx
index be68dea71c9a..f923b47998a7 100644
--- a/vcl/inc/quartz/ctfonts.hxx
+++ b/vcl/inc/quartz/SystemFontList.hxx
@@ -17,15 +17,51 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#ifndef INCLUDED_VCL_INC_QUARTZ_CTFONTS_HXX
-#define INCLUDED_VCL_INC_QUARTZ_CTFONTS_HXX
+#pragma once
 
-#include <quartz/salgdi.h>
-#include <sallayout.hxx>
+#include <sal/config.h>
 
-std::unique_ptr<SystemFontList> GetCoretextFontList();
-FontAttributes DevFontFromCTFontDescriptor(CTFontDescriptorRef, bool*);
+#include <premac.h>
+#ifdef MACOSX
+#include <ApplicationServices/ApplicationServices.h>
+#include <osx/osxvcltypes.h>
+#include <osx/salframe.h>
+#else
+#include <CoreGraphics/CoreGraphics.h>
+#include <CoreText/CoreText.h>
+#endif
+#include <postmac.h>
+
+#include <font/PhysicalFontFace.hxx>
+
+#include <unordered_map>
+
+// TODO: move into cross-platform headers
+
+class CoreTextFontFace;
+
+class SystemFontList
+{
+public:
+    SystemFontList();
+    ~SystemFontList();
 
-#endif // INCLUDED_VCL_INC_QUARTZ_CTFONTS_HXX
+    bool Init();
+    void AddFont(CoreTextFontFace*);
+
+    void AnnounceFonts(vcl::font::PhysicalFontCollection&) const;
+    CoreTextFontFace* GetFontDataFromId(sal_IntPtr nFontId) const;
+
+    CTFontCollectionRef fontCollection() { return mpCTFontCollection; }
+
+private:
+    CTFontCollectionRef mpCTFontCollection;
+    CFArrayRef mpCTFontArray;
+
+    std::unordered_map<sal_IntPtr, rtl::Reference<CoreTextFontFace>> 
maFontContainer;
+};
+
+FontAttributes DevFontFromCTFontDescriptor(CTFontDescriptorRef, bool*);
+std::unique_ptr<SystemFontList> GetCoretextFontList();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h
index 24b657e10886..c8befcc50280 100644
--- a/vcl/inc/quartz/salgdi.h
+++ b/vcl/inc/quartz/salgdi.h
@@ -23,7 +23,6 @@
 
 #include <vector>
 
-#include <basegfx/polygon/b2dpolypolygon.hxx>
 #include <tools/long.hxx>
 
 #include <premac.h>
@@ -49,85 +48,15 @@
 
 #include <font/LogicalFontInstance.hxx>
 #include <font/FontMetricData.hxx>
-#include <font/PhysicalFontFace.hxx>
 #include <salgdi.hxx>
 
 #include <quartz/salgdicommon.hxx>
-#include <unordered_map>
-#include <hb-ot.h>
 
 #include <quartz/CGHelpers.hxx>
 
 class AquaSalFrame;
-class FontAttributes;
 class XorEmulation;
-
-// CoreText-specific physically available font face
-class CoreTextFontFace final : public vcl::font::PhysicalFontFace
-{
-public:
-                                    CoreTextFontFace( const FontAttributes&, 
CTFontDescriptorRef xRef );
-                                    ~CoreTextFontFace() override;
-
-    sal_IntPtr                      GetFontId() const override;
-
-    CTFontDescriptorRef             GetFontDescriptorRef() const { return 
mxFontDescriptor; }
-
-    rtl::Reference<LogicalFontInstance> CreateFontInstance(const 
vcl::font::FontSelectPattern&) const override;
-
-    hb_blob_t* GetHbTable(hb_tag_t nTag) const override;
-
-    const std::vector<hb_variation_t>& GetVariations(const 
LogicalFontInstance&) const override;
-
-private:
-    CTFontDescriptorRef             mxFontDescriptor;
-};
-
-class CoreTextFont final : public LogicalFontInstance
-{
-    friend rtl::Reference<LogicalFontInstance> 
CoreTextFontFace::CreateFontInstance(const vcl::font::FontSelectPattern&) const;
-
-public:
-    ~CoreTextFont() override;
-
-    void       GetFontMetric( FontMetricDataRef const & );
-    bool GetGlyphOutline(sal_GlyphId, basegfx::B2DPolyPolygon&, bool) const 
override;
-
-    CTFontRef GetCTFont() const { return mpCTFont; }
-
-    /// <1.0: font is squeezed, >1.0 font is stretched, else 1.0
-    float mfFontStretch;
-    /// text rotation in radian
-    float mfFontRotation;
-
-private:
-    explicit CoreTextFont(const CoreTextFontFace&, const 
vcl::font::FontSelectPattern&);
-
-    CTFontRef mpCTFont;
-};
-
-// TODO: move into cross-platform headers
-
-class SystemFontList
-{
-public:
-    SystemFontList( void );
-    ~SystemFontList( void );
-
-    bool        Init( void );
-    void        AddFont( CoreTextFontFace* );
-
-    void    AnnounceFonts( vcl::font::PhysicalFontCollection& ) const;
-    CoreTextFontFace* GetFontDataFromId( sal_IntPtr nFontId ) const;
-
-    CTFontCollectionRef fontCollection() { return mpCTFontCollection; }
-
-private:
-    CTFontCollectionRef mpCTFontCollection;
-    CFArrayRef mpCTFontArray;
-
-    std::unordered_map<sal_IntPtr, rtl::Reference<CoreTextFontFace>> 
maFontContainer;
-};
+class CoreTextFont;
 
 namespace sal::aqua
 {
diff --git a/vcl/osx/saldata.cxx b/vcl/osx/saldata.cxx
index e3b6703d0878..1f49d1ef1e14 100644
--- a/vcl/osx/saldata.cxx
+++ b/vcl/osx/saldata.cxx
@@ -32,6 +32,7 @@
 #include <bitmaps.hlst>
 #include <cursor_hotspots.hxx>
 #include <quartz/salgdi.h>
+#include <quartz/SystemFontList.hxx>
 
 #import "apple_remote/RemoteMainController.h"
 
diff --git a/vcl/quartz/CoreTextFont.cxx b/vcl/quartz/CoreTextFont.cxx
new file mode 100644
index 000000000000..6248a255c64e
--- /dev/null
+++ b/vcl/quartz/CoreTextFont.cxx
@@ -0,0 +1,235 @@
+/* -*- 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 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+#ifdef MACOSX
+#include <osx/saldata.hxx>
+#include <osx/salinst.h>
+#endif
+#include <font/LogicalFontInstance.hxx>
+#include <impglyphitem.hxx>
+#include <quartz/CoreTextFont.hxx>
+#include <quartz/CoreTextFontFace.hxx>
+#include <quartz/salgdi.h>
+#include <quartz/utils.h>
+#include <hb.h>
+
+CoreTextFont::CoreTextFont(const CoreTextFontFace& rPFF, const 
vcl::font::FontSelectPattern& rFSP)
+    : LogicalFontInstance(rPFF, rFSP)
+    , mfFontStretch(1.0)
+    , mfFontRotation(0.0)
+    , mpCTFont(nullptr)
+{
+    double fScaledFontHeight = rFSP.mfExactHeight;
+
+    // convert font rotation to radian
+    mfFontRotation = toRadians(rFSP.mnOrientation);
+
+    // dummy matrix so we can use CGAffineTransformConcat() below
+    CGAffineTransform aMatrix = CGAffineTransformMakeTranslation(0, 0);
+
+    // handle font stretching if any
+    if ((rFSP.mnWidth != 0) && (rFSP.mnWidth != rFSP.mnHeight))
+    {
+        mfFontStretch = float(rFSP.mnWidth) / rFSP.mnHeight;
+        aMatrix = CGAffineTransformConcat(aMatrix, 
CGAffineTransformMakeScale(mfFontStretch, 1.0F));
+    }
+
+    // artificial italic
+    if (NeedsArtificialItalic())
+        aMatrix = CGAffineTransformConcat(
+            aMatrix, CGAffineTransformMake(1, 0, ARTIFICIAL_ITALIC_SKEW, 1, 0, 
0));
+
+    CTFontDescriptorRef pFontDesc = rPFF.GetFontDescriptorRef();
+    mpCTFont = CTFontCreateWithFontDescriptor(pFontDesc, fScaledFontHeight, 
&aMatrix);
+}
+
+CoreTextFont::~CoreTextFont()
+{
+    if (mpCTFont)
+        CFRelease(mpCTFont);
+}
+
+void CoreTextFont::GetFontMetric(FontMetricDataRef const& rxFontMetric)
+{
+    rxFontMetric->ImplCalcLineSpacing(this);
+    rxFontMetric->ImplInitBaselines(this);
+
+    // since FontMetricData::mnWidth is only used for stretching/squeezing 
fonts
+    // setting this width to the pixel height of the fontsize is good enough
+    // it also makes the calculation of the stretch factor simple
+    rxFontMetric->SetWidth(lrint(CTFontGetSize(mpCTFont) * mfFontStretch));
+
+    rxFontMetric->SetMinKashida(GetKashidaWidth());
+}
+
+namespace
+{
+// callbacks from CTFontCreatePathForGlyph+CGPathApply for GetGlyphOutline()
+struct GgoData
+{
+    basegfx::B2DPolygon maPolygon;
+    basegfx::B2DPolyPolygon* mpPolyPoly;
+};
+}
+
+static void MyCGPathApplierFunc(void* pData, const CGPathElement* pElement)
+{
+    basegfx::B2DPolygon& rPolygon = static_cast<GgoData*>(pData)->maPolygon;
+    const int nPointCount = rPolygon.count();
+
+    switch (pElement->type)
+    {
+        case kCGPathElementCloseSubpath:
+        case kCGPathElementMoveToPoint:
+            if (nPointCount > 0)
+            {
+                static_cast<GgoData*>(pData)->mpPolyPoly->append(rPolygon);
+                rPolygon.clear();
+            }
+            // fall through for kCGPathElementMoveToPoint:
+            if (pElement->type != kCGPathElementMoveToPoint)
+            {
+                break;
+            }
+            [[fallthrough]];
+        case kCGPathElementAddLineToPoint:
+            rPolygon.append(basegfx::B2DPoint(+pElement->points[0].x, 
-pElement->points[0].y));
+            break;
+
+        case kCGPathElementAddCurveToPoint:
+            rPolygon.append(basegfx::B2DPoint(+pElement->points[2].x, 
-pElement->points[2].y));
+            rPolygon.setNextControlPoint(
+                nPointCount - 1, basegfx::B2DPoint(pElement->points[0].x, 
-pElement->points[0].y));
+            rPolygon.setPrevControlPoint(
+                nPointCount + 0, basegfx::B2DPoint(pElement->points[1].x, 
-pElement->points[1].y));
+            break;
+
+        case kCGPathElementAddQuadCurveToPoint:
+        {
+            const basegfx::B2DPoint aStartPt = 
rPolygon.getB2DPoint(nPointCount - 1);
+            const basegfx::B2DPoint aCtrPt1((aStartPt.getX() + 2 * 
pElement->points[0].x) / 3.0,
+                                            (aStartPt.getY() - 2 * 
pElement->points[0].y) / 3.0);
+            const basegfx::B2DPoint aCtrPt2(
+                (+2 * pElement->points[0].x + pElement->points[1].x) / 3.0,
+                (-2 * pElement->points[0].y - pElement->points[1].y) / 3.0);
+            rPolygon.append(basegfx::B2DPoint(+pElement->points[1].x, 
-pElement->points[1].y));
+            rPolygon.setNextControlPoint(nPointCount - 1, aCtrPt1);
+            rPolygon.setPrevControlPoint(nPointCount + 0, aCtrPt2);
+        }
+        break;
+    }
+}
+
+bool CoreTextFont::GetGlyphOutline(sal_GlyphId nId, basegfx::B2DPolyPolygon& 
rResult, bool) const
+{
+    rResult.clear();
+
+    CGGlyph nCGGlyph = nId;
+
+    SAL_WNODEPRECATED_DECLARATIONS_PUSH
+    const CTFontOrientation aFontOrientation = kCTFontDefaultOrientation;
+    SAL_WNODEPRECATED_DECLARATIONS_POP
+    CGRect aCGRect
+        = CTFontGetBoundingRectsForGlyphs(mpCTFont, aFontOrientation, 
&nCGGlyph, nullptr, 1);
+
+    if (!CGRectIsNull(aCGRect) && CGRectIsEmpty(aCGRect))
+    {
+        // CTFontCreatePathForGlyph returns NULL for blank glyphs, but we want
+        // to return true for them.
+        return true;
+    }
+
+    CGPathRef xPath = CTFontCreatePathForGlyph(mpCTFont, nCGGlyph, nullptr);
+    if (!xPath)
+    {
+        return false;
+    }
+
+    GgoData aGgoData;
+    aGgoData.mpPolyPoly = &rResult;
+    CGPathApply(xPath, static_cast<void*>(&aGgoData), MyCGPathApplierFunc);
+#if 0 // TODO: does OSX ensure that the last polygon is always closed?
+    const CGPathElement aClosingElement = { kCGPathElementCloseSubpath, NULL };
+    MyCGPathApplierFunc( (void*)&aGgoData, &aClosingElement );
+#endif
+    CFRelease(xPath);
+
+    return true;
+}
+
+hb_blob_t* CoreTextFontFace::GetHbTable(hb_tag_t nTag) const
+{
+    hb_blob_t* pBlob = nullptr;
+    CTFontRef pFont = CTFontCreateWithFontDescriptor(mxFontDescriptor, 0.0, 
nullptr);
+
+    if (!nTag)
+    {
+        // If nTag is 0, the whole font data is requested. CoreText does not
+        // give us that, so we will construct an HarfBuzz face from CoreText
+        // table data and return the blob of that face.
+
+        auto pTags = CTFontCopyAvailableTables(pFont, 
kCTFontTableOptionNoOptions);
+        CFIndex nTags = pTags ? CFArrayGetCount(pTags) : 0;
+        if (nTags > 0)
+        {
+            hb_face_t* pHbFace = hb_face_builder_create();
+            for (CFIndex i = 0; i < nTags; i++)
+            {
+                auto nTable = 
reinterpret_cast<intptr_t>(CFArrayGetValueAtIndex(pTags, i));
+                assert(nTable);
+                auto pTable = GetHbTable(nTable);
+                assert(pTable);
+                hb_face_builder_add_table(pHbFace, nTable, pTable);
+            }
+            pBlob = hb_face_reference_blob(pHbFace);
+
+            hb_face_destroy(pHbFace);
+        }
+        if (pTags)
+            CFRelease(pTags);
+    }
+    else
+    {
+        CFDataRef pData = CTFontCopyTable(pFont, nTag, 
kCTFontTableOptionNoOptions);
+        const CFIndex nLength = pData ? CFDataGetLength(pData) : 0;
+        if (nLength > 0)
+        {
+            auto pBuffer = new UInt8[nLength];
+            const CFRange aRange = CFRangeMake(0, nLength);
+            CFDataGetBytes(pData, aRange, pBuffer);
+
+            pBlob = hb_blob_create(reinterpret_cast<const char*>(pBuffer), 
nLength,
+                                   HB_MEMORY_MODE_READONLY, pBuffer,
+                                   [](void* data) { delete[] 
static_cast<UInt8*>(data); });
+        }
+        if (pData)
+            CFRelease(pData);
+    }
+
+    CFRelease(pFont);
+    return pBlob;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/quartz/CoreTextFontFace.cxx b/vcl/quartz/CoreTextFontFace.cxx
new file mode 100644
index 000000000000..662b439a9eae
--- /dev/null
+++ b/vcl/quartz/CoreTextFontFace.cxx
@@ -0,0 +1,98 @@
+/* -*- 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 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#ifdef MACOSX
+#include <osx/saldata.hxx>
+#include <osx/salinst.h>
+#endif
+#include <font/LogicalFontInstance.hxx>
+#include <quartz/CoreTextFont.hxx>
+#include <quartz/CoreTextFontFace.hxx>
+#include <quartz/salgdi.h>
+#include <quartz/utils.h>
+
+CoreTextFontFace::CoreTextFontFace(const FontAttributes& rDFA, 
CTFontDescriptorRef xFontDescriptor)
+    : vcl::font::PhysicalFontFace(rDFA)
+    , mxFontDescriptor(xFontDescriptor)
+{
+    CFRetain(mxFontDescriptor);
+}
+
+CoreTextFontFace::~CoreTextFontFace() { CFRelease(mxFontDescriptor); }
+
+sal_IntPtr CoreTextFontFace::GetFontId() const
+{
+    return reinterpret_cast<sal_IntPtr>(mxFontDescriptor);
+}
+
+const std::vector<hb_variation_t>& CoreTextFontFace::GetVariations(const 
LogicalFontInstance&) const
+{
+    CTFontRef pFont = CTFontCreateWithFontDescriptor(mxFontDescriptor, 0.0, 
nullptr);
+
+    if (!mxVariations)
+    {
+        mxVariations.emplace();
+        CFArrayRef pAxes = CTFontCopyVariationAxes(pFont);
+        if (pAxes)
+        {
+            CFDictionaryRef pVariations = CTFontCopyVariation(pFont);
+            if (pVariations)
+            {
+                CFIndex nAxes = CFArrayGetCount(pAxes);
+                for (CFIndex i = 0; i < nAxes; ++i)
+                {
+                    auto pAxis = 
static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(pAxes, i));
+                    if (pAxis)
+                    {
+                        hb_tag_t nTag;
+                        auto pTag = static_cast<CFNumberRef>(
+                            CFDictionaryGetValue(pAxis, 
kCTFontVariationAxisIdentifierKey));
+                        if (!pTag)
+                            continue;
+                        CFNumberGetValue(pTag, kCFNumberIntType, &nTag);
+
+                        float fValue;
+                        auto pValue
+                            = 
static_cast<CFNumberRef>(CFDictionaryGetValue(pVariations, pTag));
+                        if (!pValue)
+                            continue;
+                        CFNumberGetValue(pValue, kCFNumberFloatType, &fValue);
+
+                        mxVariations->push_back({ nTag, fValue });
+                    }
+                }
+                CFRelease(pVariations);
+            }
+            CFRelease(pAxes);
+        }
+    }
+
+    return *mxVariations;
+}
+
+rtl::Reference<LogicalFontInstance>
+CoreTextFontFace::CreateFontInstance(const vcl::font::FontSelectPattern& rFSD) 
const
+{
+    return new CoreTextFont(*this, rFSD);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/quartz/ctfonts.cxx b/vcl/quartz/SystemFontList.cxx
similarity index 52%
rename from vcl/quartz/ctfonts.cxx
rename to vcl/quartz/SystemFontList.cxx
index 3d3298f6f50f..2bc7544c8010 100644
--- a/vcl/quartz/ctfonts.cxx
+++ b/vcl/quartz/SystemFontList.cxx
@@ -20,269 +20,22 @@
 #include <sal/config.h>
 #include <sal/log.hxx>
 
-#include <basegfx/polygon/b2dpolygon.hxx>
-#include <basegfx/matrix/b2dhommatrix.hxx>
 #include <tools/long.hxx>
-#include <vcl/settings.hxx>
 
 
-#include <quartz/ctfonts.hxx>
+#include <quartz/SystemFontList.hxx>
 #include <impfont.hxx>
 #ifdef MACOSX
 #include <osx/saldata.hxx>
 #include <osx/salinst.h>
 #endif
-#include <font/LogicalFontInstance.hxx>
 #include <fontattributes.hxx>
-#include <impglyphitem.hxx>
 #include <font/PhysicalFontCollection.hxx>
+#include <quartz/CoreTextFontFace.hxx>
 #include <quartz/salgdi.h>
 #include <quartz/utils.h>
 #include <sallayout.hxx>
-#include <hb-coretext.h>
 
-CoreTextFont::CoreTextFont(const CoreTextFontFace& rPFF, const 
vcl::font::FontSelectPattern& rFSP)
-    : LogicalFontInstance(rPFF, rFSP)
-    , mfFontStretch( 1.0 )
-    , mfFontRotation( 0.0 )
-    , mpCTFont(nullptr)
-{
-    double fScaledFontHeight = rFSP.mfExactHeight;
-
-    // convert font rotation to radian
-    mfFontRotation = toRadians(rFSP.mnOrientation);
-
-    // dummy matrix so we can use CGAffineTransformConcat() below
-    CGAffineTransform aMatrix = CGAffineTransformMakeTranslation(0, 0);
-
-    // handle font stretching if any
-    if( (rFSP.mnWidth != 0) && (rFSP.mnWidth != rFSP.mnHeight) )
-    {
-        mfFontStretch = float(rFSP.mnWidth) / rFSP.mnHeight;
-        aMatrix = CGAffineTransformConcat(aMatrix, 
CGAffineTransformMakeScale(mfFontStretch, 1.0F));
-    }
-
-    // artificial italic
-    if (NeedsArtificialItalic())
-        aMatrix = CGAffineTransformConcat(aMatrix, CGAffineTransformMake(1, 0, 
ARTIFICIAL_ITALIC_SKEW, 1, 0, 0));
-
-    CTFontDescriptorRef pFontDesc = rPFF.GetFontDescriptorRef();
-    mpCTFont = CTFontCreateWithFontDescriptor( pFontDesc, fScaledFontHeight, 
&aMatrix );
-}
-
-CoreTextFont::~CoreTextFont()
-{
-    if (mpCTFont)
-        CFRelease(mpCTFont);
-}
-
-void CoreTextFont::GetFontMetric( FontMetricDataRef const & rxFontMetric )
-{
-    rxFontMetric->ImplCalcLineSpacing(this);
-    rxFontMetric->ImplInitBaselines(this);
-
-    // since FontMetricData::mnWidth is only used for stretching/squeezing 
fonts
-    // setting this width to the pixel height of the fontsize is good enough
-    // it also makes the calculation of the stretch factor simple
-    rxFontMetric->SetWidth( lrint( CTFontGetSize(mpCTFont) * mfFontStretch) );
-
-    rxFontMetric->SetMinKashida(GetKashidaWidth());
-}
-
-namespace {
-
-// callbacks from CTFontCreatePathForGlyph+CGPathApply for GetGlyphOutline()
-struct GgoData { basegfx::B2DPolygon maPolygon; basegfx::B2DPolyPolygon* 
mpPolyPoly; };
-
-}
-
-static void MyCGPathApplierFunc( void* pData, const CGPathElement* pElement )
-{
-    basegfx::B2DPolygon& rPolygon = static_cast<GgoData*>(pData)->maPolygon;
-    const int nPointCount = rPolygon.count();
-
-    switch( pElement->type )
-    {
-    case kCGPathElementCloseSubpath:
-    case kCGPathElementMoveToPoint:
-        if( nPointCount > 0 )
-        {
-            static_cast<GgoData*>(pData)->mpPolyPoly->append( rPolygon );
-            rPolygon.clear();
-        }
-        // fall through for kCGPathElementMoveToPoint:
-        if( pElement->type != kCGPathElementMoveToPoint )
-        {
-            break;
-        }
-        [[fallthrough]];
-    case kCGPathElementAddLineToPoint:
-        rPolygon.append( basegfx::B2DPoint( +pElement->points[0].x, 
-pElement->points[0].y ) );
-        break;
-
-    case kCGPathElementAddCurveToPoint:
-        rPolygon.append( basegfx::B2DPoint( +pElement->points[2].x, 
-pElement->points[2].y ) );
-        rPolygon.setNextControlPoint( nPointCount - 1,
-                                      basegfx::B2DPoint( pElement->points[0].x,
-                                                         
-pElement->points[0].y ) );
-        rPolygon.setPrevControlPoint( nPointCount + 0,
-                                      basegfx::B2DPoint( pElement->points[1].x,
-                                                         
-pElement->points[1].y ) );
-        break;
-
-    case kCGPathElementAddQuadCurveToPoint:
-        {
-            const basegfx::B2DPoint aStartPt = rPolygon.getB2DPoint( 
nPointCount-1 );
-            const basegfx::B2DPoint aCtrPt1( (aStartPt.getX() + 2 * 
pElement->points[0].x) / 3.0,
-                                             (aStartPt.getY() - 2 * 
pElement->points[0].y) / 3.0 );
-            const basegfx::B2DPoint aCtrPt2( (+2 * pElement->points[0].x + 
pElement->points[1].x) / 3.0,
-                                             (-2 * pElement->points[0].y - 
pElement->points[1].y) / 3.0 );
-            rPolygon.append( basegfx::B2DPoint( +pElement->points[1].x, 
-pElement->points[1].y ) );
-            rPolygon.setNextControlPoint( nPointCount-1, aCtrPt1 );
-            rPolygon.setPrevControlPoint( nPointCount+0, aCtrPt2 );
-        }
-        break;
-    }
-}
-
-bool CoreTextFont::GetGlyphOutline(sal_GlyphId nId, basegfx::B2DPolyPolygon& 
rResult, bool) const
-{
-    rResult.clear();
-
-    CGGlyph nCGGlyph = nId;
-
-    SAL_WNODEPRECATED_DECLARATIONS_PUSH
-    const CTFontOrientation aFontOrientation = kCTFontDefaultOrientation;
-    SAL_WNODEPRECATED_DECLARATIONS_POP
-    CGRect aCGRect = CTFontGetBoundingRectsForGlyphs(mpCTFont, 
aFontOrientation, &nCGGlyph, nullptr, 1);
-
-    if (!CGRectIsNull(aCGRect) && CGRectIsEmpty(aCGRect))
-    {
-        // CTFontCreatePathForGlyph returns NULL for blank glyphs, but we want
-        // to return true for them.
-        return true;
-    }
-
-    CGPathRef xPath = CTFontCreatePathForGlyph(mpCTFont, nCGGlyph, nullptr);
-    if (!xPath)
-    {
-        return false;
-    }
-
-    GgoData aGgoData;
-    aGgoData.mpPolyPoly = &rResult;
-    CGPathApply( xPath, static_cast<void*>(&aGgoData), MyCGPathApplierFunc );
-#if 0 // TODO: does OSX ensure that the last polygon is always closed?
-    const CGPathElement aClosingElement = { kCGPathElementCloseSubpath, NULL };
-    MyCGPathApplierFunc( (void*)&aGgoData, &aClosingElement );
-#endif
-    CFRelease( xPath );
-
-    return true;
-}
-
-hb_blob_t* CoreTextFontFace::GetHbTable(hb_tag_t nTag) const
-{
-    hb_blob_t* pBlob = nullptr;
-    CTFontRef pFont = CTFontCreateWithFontDescriptor(mxFontDescriptor, 0.0, 
nullptr);
-
-    if (!nTag)
-    {
-        // If nTag is 0, the whole font data is requested. CoreText does not
-        // give us that, so we will construct an HarfBuzz face from CoreText
-        // table data and return the blob of that face.
-
-        auto pTags = CTFontCopyAvailableTables(pFont, 
kCTFontTableOptionNoOptions);
-        CFIndex nTags = pTags ? CFArrayGetCount(pTags) : 0;
-        if (nTags > 0)
-        {
-            hb_face_t* pHbFace = hb_face_builder_create();
-            for (CFIndex i = 0; i < nTags; i++)
-            {
-                auto nTable = 
reinterpret_cast<intptr_t>(CFArrayGetValueAtIndex(pTags, i));
-                assert(nTable);
-                auto pTable = GetHbTable(nTable);
-                assert(pTable);
-                hb_face_builder_add_table(pHbFace, nTable, pTable);
-            }
-            pBlob = hb_face_reference_blob(pHbFace);
-
-            hb_face_destroy(pHbFace);
-        }
-        if (pTags)
-            CFRelease(pTags);
-    }
-    else
-    {
-        CFDataRef pData = CTFontCopyTable(pFont, nTag, 
kCTFontTableOptionNoOptions);
-        const CFIndex nLength = pData ? CFDataGetLength(pData) : 0;
-        if (nLength > 0)
-        {
-            auto pBuffer = new UInt8[nLength];
-            const CFRange aRange = CFRangeMake(0, nLength);
-            CFDataGetBytes(pData, aRange, pBuffer);
-
-            pBlob = hb_blob_create(reinterpret_cast<const char*>(pBuffer), 
nLength,
-                                   HB_MEMORY_MODE_READONLY, pBuffer,
-                                   [](void* data) { delete[] 
static_cast<UInt8*>(data); });
-        }
-        if (pData)
-            CFRelease(pData);
-    }
-
-    CFRelease(pFont);
-    return pBlob;
-}
-
-const std::vector<hb_variation_t>& CoreTextFontFace::GetVariations(const 
LogicalFontInstance&) const
-{
-    CTFontRef pFont = CTFontCreateWithFontDescriptor(mxFontDescriptor, 0.0, 
nullptr);
-
-    if (!mxVariations)
-    {
-        mxVariations.emplace();
-        CFArrayRef pAxes = CTFontCopyVariationAxes(pFont);
-        if (pAxes)
-        {
-            CFDictionaryRef pVariations = CTFontCopyVariation(pFont);
-            if (pVariations)
-            {
-                CFIndex nAxes = CFArrayGetCount(pAxes);
-                for (CFIndex i = 0; i < nAxes; ++i)
-                {
-                    auto pAxis = 
static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(pAxes, i));
-                    if (pAxis)
-                    {
-                        hb_tag_t nTag;
-                        auto pTag = static_cast<CFNumberRef>(
-                            CFDictionaryGetValue(pAxis, 
kCTFontVariationAxisIdentifierKey));
-                        if (!pTag)
-                            continue;
-                        CFNumberGetValue(pTag, kCFNumberIntType, &nTag);
-
-                        float fValue;
-                        auto pValue
-                            = 
static_cast<CFNumberRef>(CFDictionaryGetValue(pVariations, pTag));
-                        if (!pValue)
-                            continue;
-                        CFNumberGetValue(pValue, kCFNumberFloatType, &fValue);
-
-                        mxVariations->push_back({ nTag, fValue });
-                    }
-                }
-                CFRelease(pVariations);
-            }
-            CFRelease(pAxes);
-        }
-    }
-
-    return *mxVariations;
-}
-
-rtl::Reference<LogicalFontInstance> CoreTextFontFace::CreateFontInstance(const 
vcl::font::FontSelectPattern& rFSD) const
-{
-    return new CoreTextFont(*this, rFSD);
-}
 
 FontAttributes DevFontFromCTFontDescriptor( CTFontDescriptorRef pFD, bool* 
bFontEnabled )
 {
diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx
index 26f1cc32184a..f800e3c15829 100644
--- a/vcl/quartz/salgdi.cxx
+++ b/vcl/quartz/salgdi.cxx
@@ -39,7 +39,6 @@
 #include <vcl/svapp.hxx>
 #include <vcl/sysdata.hxx>
 
-#include <quartz/ctfonts.hxx>
 #include <fontsubset.hxx>
 #include <impfont.hxx>
 #include <font/FontMetricData.hxx>
@@ -61,6 +60,10 @@
 #include <skia/osx/gdiimpl.hxx>
 #endif
 
+#include <quartz/SystemFontList.hxx>
+#include <quartz/CoreTextFont.hxx>
+#include <quartz/CoreTextFontFace.hxx>
+
 using namespace vcl;
 
 namespace {
@@ -120,23 +123,6 @@ bool 
CoreTextGlyphFallbackSubstititution::FindFontSubstitute(vcl::font::FontSele
     return bFound;
 }
 
-CoreTextFontFace::CoreTextFontFace( const FontAttributes& rDFA, 
CTFontDescriptorRef xFontDescriptor )
-  : vcl::font::PhysicalFontFace( rDFA )
-  , mxFontDescriptor( xFontDescriptor )
-{
-    CFRetain(mxFontDescriptor);
-}
-
-CoreTextFontFace::~CoreTextFontFace()
-{
-    CFRelease(mxFontDescriptor);
-}
-
-sal_IntPtr CoreTextFontFace::GetFontId() const
-{
-    return reinterpret_cast<sal_IntPtr>(mxFontDescriptor);
-}
-
 AquaSalGraphics::AquaSalGraphics(bool bPrinter)
     : mnRealDPIX( 0 )
     , mnRealDPIY( 0 )
diff --git a/vcl/skia/osx/gdiimpl.cxx b/vcl/skia/osx/gdiimpl.cxx
index 89ae4224fb8e..d774077b4168 100644
--- a/vcl/skia/osx/gdiimpl.cxx
+++ b/vcl/skia/osx/gdiimpl.cxx
@@ -25,7 +25,8 @@
 
 #include <tools/sk_app/mac/WindowContextFactory_mac.h>
 
-#include <quartz/ctfonts.hxx>
+#include <quartz/CoreTextFont.hxx>
+#include <quartz/SystemFontList.hxx>
 #include <skia/quartz/cgutils.h>
 
 #include <SkBitmap.h>

Reply via email to