Rebased ref, commits from common ancestor: commit 8a4aba454b3c3bb657b837cc6b2296313e28d7b0 Author: Khaled Hosny <khaledho...@eglug.org> Date: Fri Oct 14 02:50:27 2016 -0700
Support font fallback on macOS for CommonSalLayout Change-Id: Ifd26b7f14ed77a3aa2a38e5961cac5f9bbb6d796 diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h index f7e5156..6958541 100644 --- a/vcl/inc/quartz/salgdi.h +++ b/vcl/inc/quartz/salgdi.h @@ -102,6 +102,8 @@ public: hb_font_t* GetHbFont() const { return mpHbFont; } void SetHbFont(hb_font_t* pHbFont) const { mpHbFont = pHbFont; } + CFMutableDictionaryRef GetStyleDict( void ) const { return mpStyleDict; } + const CoreTextFontFace* mpFontData; /// <1.0: font is squeezed, >1.0 font is stretched, else 1.0 float mfFontStretch; @@ -113,11 +115,6 @@ private: /// CoreText text style object CFMutableDictionaryRef mpStyleDict; mutable hb_font_t* mpHbFont; - - friend class CTLayout; - friend class AquaSalGraphics; - friend class CommonSalLayout; - CFMutableDictionaryRef GetStyleDict( void ) const { return mpStyleDict; } }; // TODO: move into cross-platform headers @@ -172,8 +169,8 @@ protected: RGBAColor maFillColor; // Device Font settings - const CoreTextFontFace* mpFontData; - CoreTextStyle* mpTextStyle; + const CoreTextFontFace* mpFontData[MAX_FALLBACK]; + CoreTextStyle* mpTextStyle[MAX_FALLBACK]; RGBAColor maTextColor; /// allows text to be rendered without antialiasing bool mbNonAntialiasedText; diff --git a/vcl/quartz/ctlayout.cxx b/vcl/quartz/ctlayout.cxx index 856e066..983f50b 100644 --- a/vcl/quartz/ctlayout.cxx +++ b/vcl/quartz/ctlayout.cxx @@ -28,7 +28,6 @@ #include "quartz/ctfonts.hxx" #include "CTRunData.hxx" #include "quartz/utils.h" -#include "CommonSalLayout.hxx" class CTLayout : public SalLayout @@ -782,10 +781,7 @@ void CTLayout::Simplify( bool /*bIsBase*/ ) {} SalLayout* CoreTextStyle::GetTextLayout() const { - if (SalLayout::UseCommonLayout()) - return new CommonSalLayout(*this); - else - return new CTLayout(this); + return new CTLayout(this); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx index bb99737..bb28cdf 100644 --- a/vcl/quartz/salgdi.cxx +++ b/vcl/quartz/salgdi.cxx @@ -42,6 +42,8 @@ #include "impfontcharmap.hxx" #include "impfontmetricdata.hxx" #include "CommonSalLayout.hxx" +#include "outdev.h" +#include "PhysicalFontCollection.hxx" #ifdef MACOSX #include "osx/salframe.h" @@ -55,6 +57,49 @@ using namespace vcl; +class CoreTextGlyphFallbackSubstititution +: public ImplGlyphFallbackFontSubstitution +{ +public: + bool FindFontSubstitute(FontSelectPattern&, OUString&) const override; +}; + +bool CoreTextGlyphFallbackSubstititution::FindFontSubstitute(FontSelectPattern& rPattern, + OUString& rMissingChars) const +{ + bool bFound = false; + CoreTextStyle rStyle(rPattern); + CTFontRef pFont = static_cast<CTFontRef>(CFDictionaryGetValue(rStyle.GetStyleDict(), kCTFontAttributeName)); + CFStringRef pStr = CreateCFString(rMissingChars); + if (pStr) + { + CTFontRef pFallback = CTFontCreateForString(pFont, pStr, CFRangeMake(0, CFStringGetLength(pStr))); + if (pFallback) + { + bFound = true; + + CTFontDescriptorRef pDesc = CTFontCopyFontDescriptor(pFallback); + FontAttributes rAttr = DevFontFromCTFontDescriptor(pDesc, nullptr); + + rPattern.maSearchName = rAttr.GetFamilyName(); + + rPattern.SetWeight(rAttr.GetWeight()); + rPattern.SetItalic(rAttr.GetItalic()); + rPattern.SetPitch(rAttr.GetPitch()); + rPattern.SetWidthType(rAttr.GetWidthType()); + + SalData* pSalData = GetSalData(); + if (pSalData->mpFontList != nullptr) + rPattern.mpFontData = pSalData->mpFontList->GetFontDataFromId(reinterpret_cast<sal_IntPtr>(pDesc)); + + CFRelease(pFallback); + } + CFRelease(pStr); + } + + return bFound; +} + CoreTextFontFace::CoreTextFontFace( const CoreTextFontFace& rSrc ) : PhysicalFontFace( rSrc ) , mnFontId( rSrc.mnFontId ) @@ -245,8 +290,6 @@ AquaSalGraphics::AquaSalGraphics() , mxClipPath( nullptr ) , maLineColor( COL_WHITE ) , maFillColor( COL_BLACK ) - , mpFontData( nullptr ) - , mpTextStyle( nullptr ) , maTextColor( COL_BLACK ) , mbNonAntialiasedText( false ) , mbPrinter( false ) @@ -258,6 +301,12 @@ AquaSalGraphics::AquaSalGraphics() #endif { SAL_INFO( "vcl.quartz", "AquaSalGraphics::AquaSalGraphics() this=" << this ); + + for (int i = 0; i < MAX_FALLBACK; ++i) + { + mpTextStyle[i] = nullptr; + mpFontData[i] = nullptr; + } } AquaSalGraphics::~AquaSalGraphics() @@ -270,7 +319,8 @@ AquaSalGraphics::~AquaSalGraphics() CGPathRelease( mxClipPath ); } - delete mpTextStyle; + for (int i = 0; i < MAX_FALLBACK; ++i) + delete mpTextStyle[i]; if( mpXorEmulation ) delete mpXorEmulation; @@ -308,9 +358,12 @@ void AquaSalGraphics::SetTextColor( SalColor nSalColor ) // SAL_ DEBUG(std::hex << nSalColor << std::dec << "={" << maTextColor.GetRed() << ", " << maTextColor.GetGreen() << ", " << maTextColor.GetBlue() << ", " << maTextColor.GetAlpha() << "}"); } -void AquaSalGraphics::GetFontMetric( ImplFontMetricDataRef& rxFontMetric, int /*nFallbackLevel*/ ) +void AquaSalGraphics::GetFontMetric(ImplFontMetricDataRef& rxFontMetric, int nFallbackLevel) { - mpTextStyle->GetFontMetric( rxFontMetric ); + if (nFallbackLevel < MAX_FALLBACK && mpTextStyle[nFallbackLevel] != nullptr) + { + mpTextStyle[nFallbackLevel]->GetFontMetric(rxFontMetric); + } } static bool AddTempDevFont(const OUString& rFontFileURL) @@ -387,6 +440,12 @@ void AquaSalGraphics::GetDevFontList( PhysicalFontCollection* pFontCollection ) // Copy all PhysicalFontFace objects contained in the SystemFontList pSalData->mpFontList->AnnounceFonts( *pFontCollection ); + + if (SalLayout::UseCommonLayout()) + { + static CoreTextGlyphFallbackSubstititution aSubstFallback; + pFontCollection->SetFallbackHook(&aSubstFallback); + } } void AquaSalGraphics::ClearDevFontCache() @@ -404,14 +463,24 @@ bool AquaSalGraphics::AddTempDevFont( PhysicalFontCollection*, bool AquaSalGraphics::GetGlyphOutline( sal_GlyphId aGlyphId, basegfx::B2DPolyPolygon& rPolyPoly ) { - const bool bRC = mpTextStyle->GetGlyphOutline( aGlyphId, rPolyPoly ); - return bRC; + const int nFallbackLevel = aGlyphId >> GF_FONTSHIFT; + if (nFallbackLevel < MAX_FALLBACK && mpTextStyle[nFallbackLevel] != nullptr) + { + const bool bRC = mpTextStyle[nFallbackLevel]->GetGlyphOutline(aGlyphId, rPolyPoly); + return bRC; + } + return false; } bool AquaSalGraphics::GetGlyphBoundRect( sal_GlyphId aGlyphId, Rectangle& rRect ) { - const bool bRC = mpTextStyle->GetGlyphBoundRect( aGlyphId, rRect ); - return bRC; + const int nFallbackLevel = aGlyphId >> GF_FONTSHIFT; + if (nFallbackLevel < MAX_FALLBACK && mpTextStyle[nFallbackLevel] != nullptr) + { + const bool bRC = mpTextStyle[nFallbackLevel]->GetGlyphBoundRect(aGlyphId, rRect); + return bRC; + } + return false; } void AquaSalGraphics::DrawSalLayout(const CommonSalLayout& rLayout) @@ -449,60 +518,71 @@ void AquaSalGraphics::DrawSalLayout(const CommonSalLayout& rLayout) CGContextRestoreGState(context); } -void AquaSalGraphics::SetFont( FontSelectPattern* pReqFont, int /*nFallbackLevel*/ ) +void AquaSalGraphics::SetFont(FontSelectPattern* pReqFont, int nFallbackLevel) { // release the text style - delete mpTextStyle; - mpTextStyle = nullptr; + for (int i = nFallbackLevel; i < MAX_FALLBACK; ++i) + { + delete mpTextStyle[i]; + mpTextStyle[i] = nullptr; + } // handle NULL request meaning: release-font-resources request if( !pReqFont ) { - mpFontData = nullptr; + mpFontData[nFallbackLevel] = nullptr; return; } // update the text style - mpFontData = static_cast<const CoreTextFontFace*>( pReqFont->mpFontData ); - mpTextStyle = new CoreTextStyle( *pReqFont ); + mpFontData[nFallbackLevel] = static_cast<const CoreTextFontFace*>(pReqFont->mpFontData); + mpTextStyle[nFallbackLevel] = new CoreTextStyle(*pReqFont); SAL_INFO("vcl.ct", "SetFont" - " to " << mpFontData->GetFamilyName() - << ", " << mpFontData->GetStyleName() - << " fontid=" << mpFontData->GetFontId() + " to " << mpFontData[nFallbackLevel]->GetFamilyName() + << ", " << mpFontData[nFallbackLevel]->GetStyleName() + << " fontid=" << mpFontData[nFallbackLevel]->GetFontId() << " for " << pReqFont->GetFamilyName() << ", " << pReqFont->GetStyleName() << " weight=" << pReqFont->GetWeight() << " slant=" << pReqFont->GetItalic() << " size=" << pReqFont->mnHeight << "x" << pReqFont->mnWidth << " orientation=" << pReqFont->mnOrientation + << " fallback level " << nFallbackLevel ); } -SalLayout* AquaSalGraphics::GetTextLayout( ImplLayoutArgs& /*rArgs*/, int /*nFallbackLevel*/ ) +SalLayout* AquaSalGraphics::GetTextLayout(ImplLayoutArgs& /*rArgs*/, int nFallbackLevel) { - SalLayout* pSalLayout = mpTextStyle->GetTextLayout(); + SalLayout* pSalLayout = nullptr; + if (mpTextStyle[nFallbackLevel] != nullptr) + { + if (SalLayout::UseCommonLayout()) + pSalLayout = new CommonSalLayout(*mpTextStyle[nFallbackLevel]); + else + pSalLayout = mpTextStyle[nFallbackLevel]->GetTextLayout(); + } return pSalLayout; } const FontCharMapRef AquaSalGraphics::GetFontCharMap() const { - if( !mpFontData ) + if (mpFontData[0] == nullptr) { FontCharMapRef xFontCharMap( new FontCharMap() ); return xFontCharMap; } - return mpFontData->GetFontCharMap(); + return mpFontData[0]->GetFontCharMap(); } bool AquaSalGraphics::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const { - if( !mpFontData ) + if (mpFontData[0] == nullptr) return false; - return mpFontData->GetFontCapabilities(rFontCapabilities); + return mpFontData[0]->GetFontCapabilities(rFontCapabilities); } // fake a SFNT font directory entry for a font table @@ -772,7 +852,8 @@ void AquaSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFontData, bool bV free( const_cast<TTSimpleGlyphMetrics *>(pGlyphMetrics) ); } - FontCharMapRef xFCMap = mpFontData->GetFontCharMap(); + // XXX: mpFontData[0] is most likely wrong here + FontCharMapRef xFCMap = mpFontData[0]->GetFontCharMap(); SAL_WARN_IF( !xFCMap || !xFCMap->GetCharCount(), "vcl", "no charmap" ); // get unicode<->glyph encoding _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits