summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2021-08-17 13:10:36 +0200
committerLuboš Luňák <l.lunak@collabora.com>2021-08-23 15:00:30 +0200
commit55422ec895d3014ba0507757870ebdec9ac1a2a9 (patch)
tree0bec620294895d19ae4a3d248a582b35b7cf1bd5
parente3a8826709430f414411d22d98c1fd5e647e1417 (diff)
implement text rendering on Mac using Skia
There may be still small problems (CJK needs checking), but this is already usable. Change-Id: Ic9381c22ca55d9e6320152ffebeae740fd90f796 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120810 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
-rw-r--r--vcl/inc/quartz/salgdi.h14
-rw-r--r--vcl/inc/skia/osx/gdiimpl.hxx5
-rw-r--r--vcl/quartz/salgdi.cxx38
-rw-r--r--vcl/skia/osx/gdiimpl.cxx51
4 files changed, 88 insertions, 20 deletions
diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h
index 6cedf6f09b29..80b79a6ec720 100644
--- a/vcl/inc/quartz/salgdi.h
+++ b/vcl/inc/quartz/salgdi.h
@@ -123,6 +123,8 @@ public:
void AnnounceFonts( PhysicalFontCollection& ) const;
CoreTextFontFace* GetFontDataFromId( sal_IntPtr nFontId ) const;
+ CTFontCollectionRef fontCollection() { return mpCTFontCollection; }
+
private:
CTFontCollectionRef mpCTFontCollection;
CFArrayRef mpCTFontArray;
@@ -170,6 +172,10 @@ struct AquaSharedAttributes
int mnXorMode; // 0: off 1: on 2: invert only
int mnBitmapDepth; // zero unless bitmap
+ Color maTextColor;
+ /// allows text to be rendered without antialiasing
+ bool mbNonAntialiasedText;
+
std::unique_ptr<XorEmulation> mpXorEmulation;
AquaSharedAttributes()
@@ -188,6 +194,8 @@ struct AquaSharedAttributes
, mnHeight(0)
, mnXorMode(0)
, mnBitmapDepth(0)
+ , maTextColor( COL_BLACK )
+ , mbNonAntialiasedText( false )
{}
void unsetClipPath()
@@ -287,6 +295,7 @@ public:
const tools::Rectangle &rControlRegion,
ControlState nState,
const ImplControlValue &aValue) = 0;
+ virtual void drawTextLayout(const GenericSalLayout& layout) = 0;
protected:
static bool performDrawNativeControl(ControlType nType,
ControlPart nPart,
@@ -433,6 +442,8 @@ public:
ControlState nState,
const ImplControlValue &aValue) override;
+ virtual void drawTextLayout(const GenericSalLayout& layout) override;
+
bool supportsOperation(OutDevSupportType eType) const override;
};
@@ -447,9 +458,6 @@ class AquaSalGraphics : public SalGraphicsAutoDelegateToImpl
// Device Font settings
rtl::Reference<CoreTextStyle> mpTextStyle[MAX_FALLBACK];
- RGBAColor maTextColor;
- /// allows text to be rendered without antialiasing
- bool mbNonAntialiasedText;
public:
AquaSalGraphics();
diff --git a/vcl/inc/skia/osx/gdiimpl.hxx b/vcl/inc/skia/osx/gdiimpl.hxx
index e42126cfae46..cc291bd38764 100644
--- a/vcl/inc/skia/osx/gdiimpl.hxx
+++ b/vcl/inc/skia/osx/gdiimpl.hxx
@@ -17,6 +17,8 @@
#include <skia/gdiimpl.hxx>
#include <skia/utils.hxx>
+#include <SkFontMgr.h>
+
class VCL_PLUGIN_PUBLIC AquaSkiaSalGraphicsImpl final : public SkiaSalGraphicsImpl,
public AquaGraphicsBackendBase
{
@@ -38,11 +40,14 @@ public:
const tools::Rectangle& rControlRegion, ControlState nState,
const ImplControlValue& aValue) override;
+ virtual void drawTextLayout(const GenericSalLayout& layout) override;
+
private:
virtual void createWindowContext(bool forceRaster = false) override;
virtual void performFlush() override;
void flushToScreen(const SkIRect& rect);
friend std::unique_ptr<sk_app::WindowContext> createVulkanWindowContext(bool);
+ static inline sk_sp<SkFontMgr> fontManager;
};
#endif // INCLUDED_VCL_INC_SKIA_OSX_GDIIMPL_HXX
diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx
index 1fa3d425a6d4..53b10ab9533c 100644
--- a/vcl/quartz/salgdi.cxx
+++ b/vcl/quartz/salgdi.cxx
@@ -194,8 +194,6 @@ bool CoreTextFontFace::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilit
AquaSalGraphics::AquaSalGraphics()
: mnRealDPIX( 0 )
, mnRealDPIY( 0 )
- , maTextColor( COL_BLACK )
- , mbNonAntialiasedText( false )
{
SAL_INFO( "vcl.quartz", "AquaSalGraphics::AquaSalGraphics() this=" << this );
@@ -250,8 +248,8 @@ SalGraphicsImpl* AquaSalGraphics::GetImpl() const
void AquaSalGraphics::SetTextColor( Color nColor )
{
- maTextColor = RGBAColor( nColor );
- // SAL_ DEBUG(std::hex << nColor << std::dec << "={" << maTextColor.GetRed() << ", " << maTextColor.GetGreen() << ", " << maTextColor.GetBlue() << ", " << maTextColor.GetAlpha() << "}");
+ maShared.maTextColor = nColor;
+ // SAL_ DEBUG(std::hex << nColor << std::dec << "={" << maShared.maTextColor.GetRed() << ", " << maShared.maTextColor.GetGreen() << ", " << maShared.maTextColor.GetBlue() << ", " << maShared.maTextColor.GetAlpha() << "}");
}
void AquaSalGraphics::GetFontMetric(ImplFontMetricDataRef& rxFontMetric, int nFallbackLevel)
@@ -362,8 +360,13 @@ bool AquaSalGraphics::AddTempDevFont( PhysicalFontCollection*,
void AquaSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout)
{
+ mpBackend->drawTextLayout(rLayout);
+}
+
+void AquaGraphicsBackend::drawTextLayout(const GenericSalLayout& rLayout)
+{
#ifdef IOS
- if (!maShared.checkContext())
+ if (!mrShared.checkContext())
{
SAL_WARN("vcl.quartz", "AquaSalGraphics::DrawTextLayout() without context");
return;
@@ -437,20 +440,21 @@ void AquaSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout)
std::cerr << "]\n";
#endif
- maShared.maContextHolder.saveState();
+ mrShared.maContextHolder.saveState();
+ RGBAColor textColor( mrShared.maTextColor );
// The view is vertically flipped (no idea why), flip it back.
- CGContextScaleCTM(maShared.maContextHolder.get(), 1.0, -1.0);
- CGContextSetShouldAntialias(maShared.maContextHolder.get(), !mbNonAntialiasedText);
- CGContextSetFillColor(maShared.maContextHolder.get(), maTextColor.AsArray());
+ CGContextScaleCTM(mrShared.maContextHolder.get(), 1.0, -1.0);
+ CGContextSetShouldAntialias(mrShared.maContextHolder.get(), !mrShared.mbNonAntialiasedText);
+ CGContextSetFillColor(mrShared.maContextHolder.get(), textColor.AsArray());
if (rStyle.mbFauxBold)
{
float fSize = rFontSelect.mnHeight / 23.0f;
- CGContextSetStrokeColor(maShared.maContextHolder.get(), maTextColor.AsArray());
- CGContextSetLineWidth(maShared.maContextHolder.get(), fSize);
- CGContextSetTextDrawingMode(maShared.maContextHolder.get(), kCGTextFillStroke);
+ CGContextSetStrokeColor(mrShared.maContextHolder.get(), textColor.AsArray());
+ CGContextSetLineWidth(mrShared.maContextHolder.get(), fSize);
+ CGContextSetTextDrawingMode(mrShared.maContextHolder.get(), kCGTextFillStroke);
}
auto aIt = aGlyphOrientation.cbegin();
@@ -463,18 +467,18 @@ void AquaSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout)
size_t nStartIndex = std::distance(aGlyphOrientation.cbegin(), aIt);
size_t nLen = std::distance(aIt, aNext);
- maShared.maContextHolder.saveState();
+ mrShared.maContextHolder.saveState();
if (rStyle.mfFontRotation && !bUprightGlyph)
{
- CGContextRotateCTM(maShared.maContextHolder.get(), rStyle.mfFontRotation);
+ CGContextRotateCTM(mrShared.maContextHolder.get(), rStyle.mfFontRotation);
}
- CTFontDrawGlyphs(pFont, &aGlyphIds[nStartIndex], &aGlyphPos[nStartIndex], nLen, maShared.maContextHolder.get());
- maShared.maContextHolder.restoreState();
+ CTFontDrawGlyphs(pFont, &aGlyphIds[nStartIndex], &aGlyphPos[nStartIndex], nLen, mrShared.maContextHolder.get());
+ mrShared.maContextHolder.restoreState();
aIt = aNext;
}
- maShared.maContextHolder.restoreState();
+ mrShared.maContextHolder.restoreState();
}
void AquaSalGraphics::SetFont(LogicalFontInstance* pReqFont, int nFallbackLevel)
diff --git a/vcl/skia/osx/gdiimpl.cxx b/vcl/skia/osx/gdiimpl.cxx
index c5e8911d339e..8a879e2f7788 100644
--- a/vcl/skia/osx/gdiimpl.cxx
+++ b/vcl/skia/osx/gdiimpl.cxx
@@ -23,7 +23,12 @@
#include <skia/osx/rastercontext.hxx>
+#include <quartz/ctfonts.hxx>
+
#include <SkCanvas.h>
+#include <SkFont.h>
+#include <SkFontMgr_mac_ct.h>
+#include <SkTypeface_mac.h>
using namespace SkiaHelper;
@@ -173,6 +178,52 @@ bool AquaSkiaSalGraphicsImpl::drawNativeControl(ControlType nType, ControlPart n
return bOK;
}
+void AquaSkiaSalGraphicsImpl::drawTextLayout(const GenericSalLayout& rLayout)
+{
+ const CoreTextStyle& rStyle = *static_cast<const CoreTextStyle*>(&rLayout.GetFont());
+ const FontSelectPattern& rFontSelect = rStyle.GetFontSelectPattern();
+ int nHeight = rFontSelect.mnHeight;
+ int nWidth = rFontSelect.mnWidth ? rFontSelect.mnWidth : nHeight;
+ if (nWidth == 0 || nHeight == 0)
+ {
+ SAL_WARN("vcl.skia", "DrawTextLayout(): rFontSelect.mnHeight is zero!?");
+ return;
+ }
+
+ if (!fontManager)
+ {
+ SystemFontList* fontList = GetCoretextFontList();
+ if (fontList == nullptr)
+ {
+ SAL_WARN("vcl.skia", "DrawTextLayout(): No coretext font list");
+ fontManager = SkFontMgr_New_CoreText(nullptr);
+ }
+ else
+ {
+ fontManager = SkFontMgr_New_CoreText(fontList->fontCollection());
+ }
+ }
+
+ CTFontRef pFont
+ = static_cast<CTFontRef>(CFDictionaryGetValue(rStyle.GetStyleDict(), kCTFontAttributeName));
+ sk_sp<SkTypeface> typeface = SkMakeTypefaceFromCTFont(pFont);
+ SkFont font(typeface);
+ font.setSize(nHeight);
+ // font.setScaleX(rStyle.mfFontStretch); TODO
+ if (rStyle.mbFauxBold)
+ font.setEmbolden(true);
+ font.setEdging(!mrShared.mbNonAntialiasedText ? SkFont::Edging::kAntiAlias
+ : SkFont::Edging::kAlias);
+
+ // Vertical font, use width as "height".
+ SkFont verticalFont(font);
+ verticalFont.setSize(nHeight);
+ // verticalFont.setSize(nWidth); TODO
+ // verticalFont.setScaleX(1.0 * nHeight / nWidth);
+
+ drawGenericLayout(rLayout, mrShared.maTextColor, font, verticalFont);
+}
+
std::unique_ptr<sk_app::WindowContext> createVulkanWindowContext(bool /*temporary*/)
{
return nullptr;