Kaydet (Commit) 2bfd8391 authored tarafından Khaled Hosny's avatar Khaled Hosny

Support font fallback on macOS for CommonSalLayout

Change-Id: Ifd26b7f14ed77a3aa2a38e5961cac5f9bbb6d796
üst 9cea34ee
...@@ -102,6 +102,8 @@ public: ...@@ -102,6 +102,8 @@ public:
hb_font_t* GetHbFont() const { return mpHbFont; } hb_font_t* GetHbFont() const { return mpHbFont; }
void SetHbFont(hb_font_t* pHbFont) const { mpHbFont = pHbFont; } void SetHbFont(hb_font_t* pHbFont) const { mpHbFont = pHbFont; }
CFMutableDictionaryRef GetStyleDict( void ) const { return mpStyleDict; }
const CoreTextFontFace* mpFontData; const CoreTextFontFace* mpFontData;
/// <1.0: font is squeezed, >1.0 font is stretched, else 1.0 /// <1.0: font is squeezed, >1.0 font is stretched, else 1.0
float mfFontStretch; float mfFontStretch;
...@@ -113,11 +115,6 @@ private: ...@@ -113,11 +115,6 @@ private:
/// CoreText text style object /// CoreText text style object
CFMutableDictionaryRef mpStyleDict; CFMutableDictionaryRef mpStyleDict;
mutable hb_font_t* mpHbFont; 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 // TODO: move into cross-platform headers
...@@ -172,8 +169,8 @@ protected: ...@@ -172,8 +169,8 @@ protected:
RGBAColor maFillColor; RGBAColor maFillColor;
// Device Font settings // Device Font settings
const CoreTextFontFace* mpFontData; const CoreTextFontFace* mpFontData[MAX_FALLBACK];
CoreTextStyle* mpTextStyle; CoreTextStyle* mpTextStyle[MAX_FALLBACK];
RGBAColor maTextColor; RGBAColor maTextColor;
/// allows text to be rendered without antialiasing /// allows text to be rendered without antialiasing
bool mbNonAntialiasedText; bool mbNonAntialiasedText;
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include "quartz/ctfonts.hxx" #include "quartz/ctfonts.hxx"
#include "CTRunData.hxx" #include "CTRunData.hxx"
#include "quartz/utils.h" #include "quartz/utils.h"
#include "CommonSalLayout.hxx"
class CTLayout : public SalLayout class CTLayout : public SalLayout
...@@ -782,10 +781,7 @@ void CTLayout::Simplify( bool /*bIsBase*/ ) {} ...@@ -782,10 +781,7 @@ void CTLayout::Simplify( bool /*bIsBase*/ ) {}
SalLayout* CoreTextStyle::GetTextLayout() const SalLayout* CoreTextStyle::GetTextLayout() const
{ {
if (SalLayout::UseCommonLayout()) return new CTLayout( this);
return new CommonSalLayout(*this);
else
return new CTLayout( this);
} }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
#include "impfontcharmap.hxx" #include "impfontcharmap.hxx"
#include "impfontmetricdata.hxx" #include "impfontmetricdata.hxx"
#include "CommonSalLayout.hxx" #include "CommonSalLayout.hxx"
#include "outdev.h"
#include "PhysicalFontCollection.hxx"
#ifdef MACOSX #ifdef MACOSX
#include "osx/salframe.h" #include "osx/salframe.h"
...@@ -55,6 +57,49 @@ ...@@ -55,6 +57,49 @@
using namespace vcl; 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)
rPattern.mpFontData = pSalData->mpFontList->GetFontDataFromId(reinterpret_cast<sal_IntPtr>(pDesc));
CFRelease(pFallback);
}
CFRelease(pStr);
}
return bFound;
}
CoreTextFontFace::CoreTextFontFace( const CoreTextFontFace& rSrc ) CoreTextFontFace::CoreTextFontFace( const CoreTextFontFace& rSrc )
: PhysicalFontFace( rSrc ) : PhysicalFontFace( rSrc )
, mnFontId( rSrc.mnFontId ) , mnFontId( rSrc.mnFontId )
...@@ -245,8 +290,6 @@ AquaSalGraphics::AquaSalGraphics() ...@@ -245,8 +290,6 @@ AquaSalGraphics::AquaSalGraphics()
, mxClipPath( nullptr ) , mxClipPath( nullptr )
, maLineColor( COL_WHITE ) , maLineColor( COL_WHITE )
, maFillColor( COL_BLACK ) , maFillColor( COL_BLACK )
, mpFontData( nullptr )
, mpTextStyle( nullptr )
, maTextColor( COL_BLACK ) , maTextColor( COL_BLACK )
, mbNonAntialiasedText( false ) , mbNonAntialiasedText( false )
, mbPrinter( false ) , mbPrinter( false )
...@@ -258,6 +301,12 @@ AquaSalGraphics::AquaSalGraphics() ...@@ -258,6 +301,12 @@ AquaSalGraphics::AquaSalGraphics()
#endif #endif
{ {
SAL_INFO( "vcl.quartz", "AquaSalGraphics::AquaSalGraphics() this=" << this ); SAL_INFO( "vcl.quartz", "AquaSalGraphics::AquaSalGraphics() this=" << this );
for (int i = 0; i < MAX_FALLBACK; ++i)
{
mpTextStyle[i] = nullptr;
mpFontData[i] = nullptr;
}
} }
AquaSalGraphics::~AquaSalGraphics() AquaSalGraphics::~AquaSalGraphics()
...@@ -270,7 +319,8 @@ AquaSalGraphics::~AquaSalGraphics() ...@@ -270,7 +319,8 @@ AquaSalGraphics::~AquaSalGraphics()
CGPathRelease( mxClipPath ); CGPathRelease( mxClipPath );
} }
delete mpTextStyle; for (int i = 0; i < MAX_FALLBACK; ++i)
delete mpTextStyle[i];
if( mpXorEmulation ) if( mpXorEmulation )
delete mpXorEmulation; delete mpXorEmulation;
...@@ -308,9 +358,12 @@ void AquaSalGraphics::SetTextColor( SalColor nSalColor ) ...@@ -308,9 +358,12 @@ void AquaSalGraphics::SetTextColor( SalColor nSalColor )
// SAL_ DEBUG(std::hex << nSalColor << std::dec << "={" << maTextColor.GetRed() << ", " << maTextColor.GetGreen() << ", " << maTextColor.GetBlue() << ", " << maTextColor.GetAlpha() << "}"); // 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])
{
mpTextStyle[nFallbackLevel]->GetFontMetric(rxFontMetric);
}
} }
static bool AddTempDevFont(const OUString& rFontFileURL) static bool AddTempDevFont(const OUString& rFontFileURL)
...@@ -387,6 +440,12 @@ void AquaSalGraphics::GetDevFontList( PhysicalFontCollection* pFontCollection ) ...@@ -387,6 +440,12 @@ void AquaSalGraphics::GetDevFontList( PhysicalFontCollection* pFontCollection )
// Copy all PhysicalFontFace objects contained in the SystemFontList // Copy all PhysicalFontFace objects contained in the SystemFontList
pSalData->mpFontList->AnnounceFonts( *pFontCollection ); pSalData->mpFontList->AnnounceFonts( *pFontCollection );
if (SalLayout::UseCommonLayout())
{
static CoreTextGlyphFallbackSubstititution aSubstFallback;
pFontCollection->SetFallbackHook(&aSubstFallback);
}
} }
void AquaSalGraphics::ClearDevFontCache() void AquaSalGraphics::ClearDevFontCache()
...@@ -404,14 +463,24 @@ bool AquaSalGraphics::AddTempDevFont( PhysicalFontCollection*, ...@@ -404,14 +463,24 @@ bool AquaSalGraphics::AddTempDevFont( PhysicalFontCollection*,
bool AquaSalGraphics::GetGlyphOutline( sal_GlyphId aGlyphId, basegfx::B2DPolyPolygon& rPolyPoly ) bool AquaSalGraphics::GetGlyphOutline( sal_GlyphId aGlyphId, basegfx::B2DPolyPolygon& rPolyPoly )
{ {
const bool bRC = mpTextStyle->GetGlyphOutline( aGlyphId, rPolyPoly ); const int nFallbackLevel = aGlyphId >> GF_FONTSHIFT;
return bRC; if (nFallbackLevel < MAX_FALLBACK && mpTextStyle[nFallbackLevel])
{
const bool bRC = mpTextStyle[nFallbackLevel]->GetGlyphOutline(aGlyphId, rPolyPoly);
return bRC;
}
return false;
} }
bool AquaSalGraphics::GetGlyphBoundRect( sal_GlyphId aGlyphId, Rectangle& rRect ) bool AquaSalGraphics::GetGlyphBoundRect( sal_GlyphId aGlyphId, Rectangle& rRect )
{ {
const bool bRC = mpTextStyle->GetGlyphBoundRect( aGlyphId, rRect ); const int nFallbackLevel = aGlyphId >> GF_FONTSHIFT;
return bRC; if (nFallbackLevel < MAX_FALLBACK && mpTextStyle[nFallbackLevel])
{
const bool bRC = mpTextStyle[nFallbackLevel]->GetGlyphBoundRect(aGlyphId, rRect);
return bRC;
}
return false;
} }
void AquaSalGraphics::DrawSalLayout(const CommonSalLayout& rLayout) void AquaSalGraphics::DrawSalLayout(const CommonSalLayout& rLayout)
...@@ -449,60 +518,71 @@ void AquaSalGraphics::DrawSalLayout(const CommonSalLayout& rLayout) ...@@ -449,60 +518,71 @@ void AquaSalGraphics::DrawSalLayout(const CommonSalLayout& rLayout)
CGContextRestoreGState(context); CGContextRestoreGState(context);
} }
void AquaSalGraphics::SetFont( FontSelectPattern* pReqFont, int /*nFallbackLevel*/ ) void AquaSalGraphics::SetFont(FontSelectPattern* pReqFont, int nFallbackLevel)
{ {
// release the text style // release the text style
delete mpTextStyle; for (int i = nFallbackLevel; i < MAX_FALLBACK; ++i)
mpTextStyle = nullptr; {
delete mpTextStyle[i];
mpTextStyle[i] = nullptr;
}
// handle NULL request meaning: release-font-resources request // handle NULL request meaning: release-font-resources request
if( !pReqFont ) if( !pReqFont )
{ {
mpFontData = nullptr; mpFontData[nFallbackLevel] = nullptr;
return; return;
} }
// update the text style // update the text style
mpFontData = static_cast<const CoreTextFontFace*>( pReqFont->mpFontData ); mpFontData[nFallbackLevel] = static_cast<const CoreTextFontFace*>(pReqFont->mpFontData);
mpTextStyle = new CoreTextStyle( *pReqFont ); mpTextStyle[nFallbackLevel] = new CoreTextStyle(*pReqFont);
SAL_INFO("vcl.ct", SAL_INFO("vcl.ct",
"SetFont" "SetFont"
" to " << mpFontData->GetFamilyName() " to " << mpFontData[nFallbackLevel]->GetFamilyName()
<< ", " << mpFontData->GetStyleName() << ", " << mpFontData[nFallbackLevel]->GetStyleName()
<< " fontid=" << mpFontData->GetFontId() << " fontid=" << mpFontData[nFallbackLevel]->GetFontId()
<< " for " << pReqFont->GetFamilyName() << " for " << pReqFont->GetFamilyName()
<< ", " << pReqFont->GetStyleName() << ", " << pReqFont->GetStyleName()
<< " weight=" << pReqFont->GetWeight() << " weight=" << pReqFont->GetWeight()
<< " slant=" << pReqFont->GetItalic() << " slant=" << pReqFont->GetItalic()
<< " size=" << pReqFont->mnHeight << "x" << pReqFont->mnWidth << " size=" << pReqFont->mnHeight << "x" << pReqFont->mnWidth
<< " orientation=" << pReqFont->mnOrientation << " 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])
{
if (SalLayout::UseCommonLayout())
pSalLayout = new CommonSalLayout(*mpTextStyle[nFallbackLevel]);
else
pSalLayout = mpTextStyle[nFallbackLevel]->GetTextLayout();
}
return pSalLayout; return pSalLayout;
} }
const FontCharMapRef AquaSalGraphics::GetFontCharMap() const const FontCharMapRef AquaSalGraphics::GetFontCharMap() const
{ {
if( !mpFontData ) if (!mpFontData[0])
{ {
FontCharMapRef xFontCharMap( new FontCharMap() ); FontCharMapRef xFontCharMap( new FontCharMap() );
return xFontCharMap; return xFontCharMap;
} }
return mpFontData->GetFontCharMap(); return mpFontData[0]->GetFontCharMap();
} }
bool AquaSalGraphics::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const bool AquaSalGraphics::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
{ {
if( !mpFontData ) if (!mpFontData[0])
return false; return false;
return mpFontData->GetFontCapabilities(rFontCapabilities); return mpFontData[0]->GetFontCapabilities(rFontCapabilities);
} }
// fake a SFNT font directory entry for a font table // fake a SFNT font directory entry for a font table
...@@ -772,7 +852,8 @@ void AquaSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFontData, bool bV ...@@ -772,7 +852,8 @@ void AquaSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFontData, bool bV
free( const_cast<TTSimpleGlyphMetrics *>(pGlyphMetrics) ); free( const_cast<TTSimpleGlyphMetrics *>(pGlyphMetrics) );
} }
FontCharMapRef xFCMap = mpFontData->GetFontCharMap(); CoreTextFontFace rCTFontData(*pFontData, pFontData->GetFontId());
FontCharMapRef xFCMap = rCTFontData.GetFontCharMap();
SAL_WARN_IF( !xFCMap.Is() || !xFCMap->GetCharCount(), "vcl", "no charmap" ); SAL_WARN_IF( !xFCMap.Is() || !xFCMap->GetCharCount(), "vcl", "no charmap" );
// get unicode<->glyph encoding // get unicode<->glyph encoding
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment