diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2021-08-17 13:10:36 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2021-08-23 15:00:30 +0200 |
commit | 55422ec895d3014ba0507757870ebdec9ac1a2a9 (patch) | |
tree | 0bec620294895d19ae4a3d248a582b35b7cf1bd5 | |
parent | e3a8826709430f414411d22d98c1fd5e647e1417 (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.h | 14 | ||||
-rw-r--r-- | vcl/inc/skia/osx/gdiimpl.hxx | 5 | ||||
-rw-r--r-- | vcl/quartz/salgdi.cxx | 38 | ||||
-rw-r--r-- | vcl/skia/osx/gdiimpl.cxx | 51 |
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; |