summaryrefslogtreecommitdiff
path: root/vcl/quartz
diff options
context:
space:
mode:
authorKhaled Hosny <khaledhosny@eglug.org>2016-11-25 14:00:07 +0200
committerKhaled Hosny <khaledhosny@eglug.org>2016-11-26 14:28:39 +0000
commitd761d952f460e1943e94c5a7556b3b01d2259666 (patch)
treecde2940e406e8451aa8acc8cd8d4305caaf6b626 /vcl/quartz
parent30ebc895c95ee66adf172717249aa1789b309eff (diff)
Kill old Core Text layout engine
Change-Id: If80d65899255d8be72f374fbec232d103a08a006 Reviewed-on: https://gerrit.libreoffice.org/31232 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Khaled Hosny <khaledhosny@eglug.org>
Diffstat (limited to 'vcl/quartz')
-rw-r--r--vcl/quartz/CTRunData.cxx94
-rw-r--r--vcl/quartz/CTRunData.hxx42
-rw-r--r--vcl/quartz/ctfonts.cxx17
-rw-r--r--vcl/quartz/ctlayout.cxx787
-rw-r--r--vcl/quartz/salgdi.cxx18
5 files changed, 7 insertions, 951 deletions
diff --git a/vcl/quartz/CTRunData.cxx b/vcl/quartz/CTRunData.cxx
deleted file mode 100644
index 8f58d478646d..000000000000
--- a/vcl/quartz/CTRunData.cxx
+++ /dev/null
@@ -1,94 +0,0 @@
-/* -*- 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/.
- */
-
-#include <sal/config.h>
-#include <sal/types.h>
-
-#include <cassert>
-
-#include "CTRunData.hxx"
-#include "quartz/utils.h"
-
-
-CTRunData::CTRunData( CTRunRef pRun, int start)
- : ownership_flags(0)
- , m_StartPos(start)
- , m_pRun(pRun)
-{
- assert(pRun);
-
- CFDictionaryRef pRunAttributes = CTRunGetAttributes( m_pRun );
- m_pFont = static_cast<CTFontRef>(CFDictionaryGetValue( pRunAttributes, kCTFontAttributeName ));
-
- m_nGlyphs = CTRunGetGlyphCount(m_pRun);
- m_EndPos = m_StartPos + m_nGlyphs;
- const CFRange aAll = CFRangeMake( 0, m_nGlyphs );
-
- m_pAdvances = CTRunGetAdvancesPtr( pRun );
- if( !m_pAdvances )
- {
- m_pAdvances = new CGSize[m_nGlyphs];
- ownership_flags |= CTRUNDATA_F_OWN_ADVANCES;
- CTRunGetAdvances( pRun, aAll, const_cast<CGSize*>(m_pAdvances) );
- }
-
- m_pGlyphs = CTRunGetGlyphsPtr( m_pRun );
- if( !m_pGlyphs )
- {
- m_pGlyphs = new CGGlyph[m_nGlyphs];
- ownership_flags |= CTRUNDATA_F_OWN_GLYPHS;
- CTRunGetGlyphs( pRun, aAll, const_cast<CGGlyph*>(m_pGlyphs));
- }
-
- m_pStringIndices = CTRunGetStringIndicesPtr( pRun );
- if( !m_pStringIndices )
- {
- m_pStringIndices = new CFIndex[m_nGlyphs];
- ownership_flags |= CTRUNDATA_F_OWN_INDICES;
- CTRunGetStringIndices( pRun, aAll, const_cast<CFIndex*>(m_pStringIndices) );
- }
-
- m_pPositions = CTRunGetPositionsPtr( pRun );
- if( !m_pPositions )
- {
- m_pPositions = new CGPoint[m_nGlyphs];
- ownership_flags |= CTRUNDATA_F_OWN_POSITIONS;
- CTRunGetPositions( pRun, aAll, const_cast<CGPoint*>(m_pPositions) );
- }
- for(int i = 0; i < m_nGlyphs; i++)
- {
- SAL_INFO( "vcl.ct", "CTRunData Adv:" << (double)m_pAdvances[i].width << " s-idx:" << m_pStringIndices[i] << " pos:(" <<
- m_pPositions[i].x << ":" << m_pPositions[i].y << ")");
- }
-}
-
-CTRunData::~CTRunData()
-{
- if(ownership_flags & CTRUNDATA_F_OWN_ADVANCES)
- {
- delete [] m_pAdvances;
- }
-
- if(ownership_flags & CTRUNDATA_F_OWN_GLYPHS)
- {
- delete [] m_pGlyphs;
- }
-
- if(ownership_flags & CTRUNDATA_F_OWN_INDICES)
- {
- delete [] m_pStringIndices;
- }
-
- if(ownership_flags & CTRUNDATA_F_OWN_POSITIONS)
- {
- delete [] m_pPositions;
- }
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/quartz/CTRunData.hxx b/vcl/quartz/CTRunData.hxx
deleted file mode 100644
index 3201acf08373..000000000000
--- a/vcl/quartz/CTRunData.hxx
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- 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/.
- */
-#ifndef CTRunData_Included
-#define CTRunData_Included
-
-#include "premac.h"
-#include <CoreGraphics/CoreGraphics.h>
-#include <CoreText/CoreText.h>
-#include "postmac.h"
-
-class CTRunData
-{
-public:
- int ownership_flags;
-#define CTRUNDATA_F_OWN_ADVANCES (1<<0)
-#define CTRUNDATA_F_OWN_GLYPHS (1<<1)
-#define CTRUNDATA_F_OWN_INDICES (1<<2)
-#define CTRUNDATA_F_OWN_POSITIONS (1<<3)
-
- int m_nGlyphs;
- int m_StartPos;
- int m_EndPos;
- CTRunRef m_pRun;
- CTFontRef m_pFont;
- const CGGlyph* m_pGlyphs;
- const CGPoint* m_pPositions;
- const CGSize* m_pAdvances;
- const CFIndex* m_pStringIndices;
-
- CTRunData(CTRunRef pRun, int start);
- ~CTRunData();
-};
-
-#endif /* NDef CTRunData_Included */
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/quartz/ctfonts.cxx b/vcl/quartz/ctfonts.cxx
index 20f5414b2508..d5f29b5c073d 100644
--- a/vcl/quartz/ctfonts.cxx
+++ b/vcl/quartz/ctfonts.cxx
@@ -100,17 +100,6 @@ CoreTextStyle::CoreTextStyle( const FontSelectPattern& rFSD )
CTFontRef pNewCTFont = CTFontCreateWithFontDescriptor( pFontDesc, fScaledFontHeight, &aMatrix );
CFDictionarySetValue( mpStyleDict, kCTFontAttributeName, pNewCTFont );
CFRelease( pNewCTFont);
-
- // allow delayed setting the font color, i.e. after the text layout
- CFDictionarySetValue( mpStyleDict, kCTForegroundColorFromContextAttributeName, kCFBooleanTrue );
-
-#if 0 // LastResort is implicit in CoreText's font cascading
- const void* aGFBDescriptors[] = { CTFontDescriptorCreateWithNameAndSize( CFSTR("LastResort"), 0) }; // TODO: use the full GFB list
- const int nGfbCount = sizeof(aGFBDescriptors) / sizeof(*aGFBDescriptors);
- CFArrayRef pGfbList = CFArrayCreate( NULL, aGFBDescriptors, nGfbCount, &kCFTypeArrayCallBacks);
- CFDictionaryAddValue( mpStyleDict, kCTFontCascadeListAttribute, pGfbList);
- CFRelease( pGfbList);
-#endif
}
CoreTextStyle::~CoreTextStyle()
@@ -171,7 +160,6 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
bool CoreTextStyle::GetGlyphBoundRect( sal_GlyphId aGlyphId, Rectangle& rRect ) const
{
CGGlyph nCGGlyph = aGlyphId & GF_IDXMASK;
- // XXX: this is broken if the glyph came from fallback font
CTFontRef aCTFontRef = static_cast<CTFontRef>(CFDictionaryGetValue( mpStyleDict, kCTFontAttributeName ));
SAL_WNODEPRECATED_DECLARATIONS_PUSH //TODO: 10.11 kCTFontDefaultOrientation
@@ -247,7 +235,6 @@ bool CoreTextStyle::GetGlyphOutline( sal_GlyphId aGlyphId, basegfx::B2DPolyPolyg
rResult.clear();
CGGlyph nCGGlyph = aGlyphId & GF_IDXMASK;
- // XXX: this is broken if the glyph came from fallback font
CTFontRef pCTFont = static_cast<CTFontRef>(CFDictionaryGetValue( mpStyleDict, kCTFontAttributeName ));
CGPathRef xPath = CTFontCreatePathForGlyph( pCTFont, nCGGlyph, nullptr );
if (!xPath)
@@ -368,9 +355,9 @@ FontAttributes DevFontFromCTFontDescriptor( CTFontDescriptorRef pFD, bool* bFont
// get font attributes
CFDictionaryRef pAttrDict = static_cast<CFDictionaryRef>(CTFontDescriptorCopyAttribute( pFD, kCTFontTraitsAttribute ));
- if (bFontEnabled && *bFontEnabled && SalLayout::UseCommonLayout())
+ if (bFontEnabled && *bFontEnabled)
{
- // Ignore font formats not supported by CommonSalLayout.
+ // Ignore font formats not supported.
int nFormat;
CFNumberRef pFormat = static_cast<CFNumberRef>(CTFontDescriptorCopyAttribute(pFD, kCTFontFormatAttribute));
CFNumberGetValue(pFormat, kCFNumberIntType, &nFormat);
diff --git a/vcl/quartz/ctlayout.cxx b/vcl/quartz/ctlayout.cxx
deleted file mode 100644
index fcf474edd617..000000000000
--- a/vcl/quartz/ctlayout.cxx
+++ /dev/null
@@ -1,787 +0,0 @@
-/* -*- 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 .
- */
-
-#include <sal/config.h>
-
-#include <memory>
-#include <vector>
-
-#include <sal/types.h>
-#include <tools/debug.hxx>
-
-#include "quartz/ctfonts.hxx"
-#include "CTRunData.hxx"
-#include "quartz/utils.h"
-
-
-class CTLayout : public SalLayout
-{
-public:
- explicit CTLayout( const CoreTextStyle* );
- virtual ~CTLayout() override;
-
- virtual bool LayoutText( ImplLayoutArgs& ) override;
- virtual void AdjustLayout( ImplLayoutArgs& ) override;
- virtual void DrawText( SalGraphics& ) const override;
- virtual bool DrawTextSpecial( SalGraphics& rGraphics, sal_uInt32 flags ) const override;
-
- virtual int GetNextGlyphs( int nLen, sal_GlyphId* pOutGlyphIds, Point& rPos, int&,
- DeviceCoordinate* pGlyphAdvances = nullptr, int* pCharIndexes = nullptr,
- const PhysicalFontFace** pFallbackFonts = nullptr ) const override;
-
- virtual DeviceCoordinate GetTextWidth() const override;
- virtual DeviceCoordinate FillDXArray( DeviceCoordinate* pDXArray ) const override;
- virtual sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const override;
- virtual void GetCaretPositions( int nArraySize, long* pCaretXArray ) const override;
- virtual bool GetBoundRect( SalGraphics&, Rectangle& ) const override;
-
- virtual void InitFont() const override;
- virtual void MoveGlyph( int nStart, long nNewXPos ) override;
- virtual void DropGlyph( int nStart ) override;
- virtual void Simplify( bool bIsBase ) override;
-
-private:
- void drawCTLine(AquaSalGraphics& rAquaGraphics, CTLineRef ctline, const CoreTextStyle* const pStyle) const;
- CGPoint GetTextDrawPosition() const;
- bool CacheGlyphLayout() const;
-
- const CoreTextStyle* const mpTextStyle;
-
- // CoreText specific objects
- CFAttributedStringRef mpAttrString;
- CTLineRef mpCTLine;
-
- int mnCharCount; // ==mnEndCharPos-mnMinCharPos
- int mnTrailingSpaceCount;
- double mfTrailingSpaceWidth;
-
- // cached details about the resulting layout
- // mutable members since these details are all lazy initialized
- mutable double mfCachedWidth; // cached value of resulting typographical width
-
- // x-offset relative to layout origin
- // currently only used in RTL-layouts
- mutable double mfBaseAdv;
-
- mutable bool bLayouted; // true if the glyph layout information are cached and current;
- mutable std::vector<std::unique_ptr<CTRunData>> m_vRunData;
-
-};
-
-CTLayout::CTLayout( const CoreTextStyle* pTextStyle )
- : mpTextStyle( pTextStyle )
- , mpAttrString( nullptr )
- , mpCTLine( nullptr )
- , mnCharCount( 0 )
- , mnTrailingSpaceCount( 0 )
- , mfTrailingSpaceWidth( 0.0 )
- , mfCachedWidth( -1 )
- , mfBaseAdv( 0 )
- , bLayouted( false )
-{
-}
-
-CTLayout::~CTLayout()
-{
- if( mpCTLine )
- {
- SAL_INFO( "vcl.ct", "CFRelease(" << mpCTLine << ")" );
- CFRelease( mpCTLine );
- }
- if( mpAttrString )
- CFRelease( mpAttrString );
-}
-
-bool CTLayout::LayoutText( ImplLayoutArgs& rArgs )
-{
- m_vRunData.clear();
- bLayouted = false;
-
- // release an eventual older layout
- if( mpAttrString )
- CFRelease( mpAttrString );
- mpAttrString = nullptr;
- if( mpCTLine )
- {
- SAL_INFO( "vcl.ct", "CFRelease(" << mpCTLine << ")" );
- CFRelease( mpCTLine );
- }
- mpCTLine = nullptr;
-
- // initialize the new layout
- SalLayout::AdjustLayout( rArgs );
- mnCharCount = mnEndCharPos - mnMinCharPos;
-
- // short circuit if there is nothing to do
- if( mnCharCount <= 0 )
- return false;
-
- const sal_Unicode *pStr = rArgs.mrStr.getStr();
-
- // create the CoreText line layout
- CFStringRef aCFText = CFStringCreateWithCharactersNoCopy( nullptr,
- reinterpret_cast<UniChar const *>(pStr + mnMinCharPos),
- mnCharCount,
- kCFAllocatorNull );
- // CFAttributedStringCreate copies the attribues parameter
- mpAttrString = CFAttributedStringCreate( nullptr, aCFText, mpTextStyle->GetStyleDict() );
- mpCTLine = CTLineCreateWithAttributedString( mpAttrString );
- SAL_INFO( "vcl.ct", "CTLineCreateWithAttributedString(\"" << GetOUString(aCFText) << "\") =p " << mpCTLine );
- CFRelease( aCFText);
-
- mnTrailingSpaceCount = 0;
- // reverse search for first 'non-space'...
- for( int i = mnEndCharPos - 1; i >= mnMinCharPos; i--)
- {
- sal_Unicode nChar = pStr[i];
- if ((nChar <= 0x0020) || // blank
- (nChar == 0x00A0) || // non breaking space
- (nChar >= 0x2000 && nChar <= 0x200F) || // whitespace
- (nChar == 0x3000)) // ideographic space
- {
- mnTrailingSpaceCount += 1;
- }
- else
- {
- break;
- }
- }
- return true;
-}
-
-void CTLayout::AdjustLayout( ImplLayoutArgs& rArgs )
-{
- if( !mpCTLine)
- {
- return;
- }
-
-
- int nPixelWidth = rArgs.mpDXArray ? rArgs.mpDXArray[ mnCharCount - 1 ] : rArgs.mnLayoutWidth;
- if( nPixelWidth <= 0)
- return;
-
- // HACK: justification requests which change the width by just one pixel are probably
- // #i86038# introduced by lossy conversions between integer based coordinate system
- int fuzz = (nPixelWidth - GetTextWidth()) / 2;
- if (!fuzz)
- {
- return;
- }
-
- // if the text to be justified has whitespace in it then
- // - Writer goes crazy with its HalfSpace magic
- // - CoreText handles spaces specially (in particular at the text end)
- if( mnTrailingSpaceCount )
- {
- if(rArgs.mpDXArray)
- {
- int nFullPixelWidth = nPixelWidth;
- nPixelWidth = mnTrailingSpaceCount == mnCharCount
- ? 0 : rArgs.mpDXArray[ mnCharCount - mnTrailingSpaceCount - 1];
- mfTrailingSpaceWidth = nFullPixelWidth - nPixelWidth;
- }
- else
- {
- if(mfTrailingSpaceWidth <= 0.0)
- {
- mfTrailingSpaceWidth = CTLineGetTrailingWhitespaceWidth( mpCTLine );
- nPixelWidth -= rint(mfTrailingSpaceWidth);
- }
- }
- if(nPixelWidth <= 0)
- {
- return;
- }
- // recreate the CoreText line layout without trailing spaces
- SAL_INFO( "vcl.ct", "CFRelease(" << mpCTLine << ")" );
- CFRelease( mpCTLine );
- const sal_Unicode *pStr = rArgs.mrStr.getStr();
- CFStringRef aCFText = CFStringCreateWithCharactersNoCopy( nullptr,
- reinterpret_cast<UniChar const *>(pStr + mnMinCharPos),
- mnCharCount - mnTrailingSpaceCount,
- kCFAllocatorNull );
- CFAttributedStringRef pAttrStr = CFAttributedStringCreate( nullptr,
- aCFText,
- mpTextStyle->GetStyleDict() );
- mpCTLine = CTLineCreateWithAttributedString( pAttrStr );
- SAL_INFO( "vcl.ct", "CTLineCreateWithAttributedString(\"" << GetOUString(aCFText) << "\") = " << mpCTLine );
- CFRelease( pAttrStr );
- CFRelease( aCFText );
-
-
- // in RTL-layouts trailing spaces are leftmost
- // TODO: use BiDi-algorithm to thoroughly check this assumption
- if( rArgs.mnFlags & SalLayoutFlags::BiDiRtl)
- {
- mfBaseAdv = mfTrailingSpaceWidth;
- }
- }
-
- CTLineRef pNewCTLine = CTLineCreateJustifiedLine( mpCTLine, 1.0, nPixelWidth);
- SAL_INFO( "vcl.ct", "CTLineCreateJustifiedLine(" << mpCTLine << ",1.0," << nPixelWidth << ") = " << pNewCTLine );
-
- if( !pNewCTLine )
- {
- // CTLineCreateJustifiedLine can and does fail
- // handle failure by keeping the unjustified layout
- // TODO: a better solution such as
- // - forcing glyph overlap
- // - changing the font size
- // - changing the CTM matrix
- return;
- }
- SAL_INFO( "vcl.ct", "CFRelease(" << mpCTLine << ")" );
- CFRelease( mpCTLine );
- mpCTLine = pNewCTLine;
- mfCachedWidth = nPixelWidth + mfTrailingSpaceWidth;
-}
-
-// When drawing right aligned text, rounding errors in the position returned by
-// GetDrawPosition() cause the right margin of the text to change whenever text
-// width changes causing "jumping letters" effect. So here we calculate the
-// drawing position relative to the right margin on our own to avoid the
-// rounding errors. That is basically a hack, and it should go away if one day
-// we managed to get rid of those rounding errors.
-
-// We continue using GetDrawPosition() for non-right aligned text, to minimize
-// any unforeseen side effects.
-CGPoint CTLayout::GetTextDrawPosition() const
-{
- CGFloat fPosX, fPosY;
-
- if (mnLayoutFlags & SalLayoutFlags::RightAlign)
- {
- // text is always drawn at its leftmost point
- const Point aPos = DrawBase();
- fPosX = aPos.X() + mfBaseAdv - GetTextWidth();
- fPosY = aPos.Y();
- }
- else
- {
- const Point aPos = GetDrawPosition(Point(mfBaseAdv, 0));
- fPosX = aPos.X();
- fPosY = aPos.Y();
- }
-
- CGPoint aTextPos = { +fPosX, -fPosY };
- return aTextPos;
-}
-
-/* use to deal with special font decoration like 'outline' drawing
- * return true if it was able to handle the drawing
- * false if not, in which case the caller
- * is supposed to fallback to 'generic' method
- */
-bool CTLayout::DrawTextSpecial( SalGraphics& rGraphics, sal_uInt32 flags ) const
-{
- AquaSalGraphics& rAquaGraphics = static_cast<AquaSalGraphics&>(rGraphics);
-
- // short circuit if there is nothing to do
- if( (mnCharCount <= 0) || !rAquaGraphics.CheckContext() )
- return true;
-#if 0 /* temporarely revert to the 'old way' */
- if (flags & DRAWTEXT_F_OUTLINE)
- {
- CFMutableDictionaryRef styledict = CFDictionaryCreateMutableCopy(
- CFAllocatorGetDefault(),
- CFDictionaryGetCount(mpTextStyle->GetStyleDict()),
- mpTextStyle->GetStyleDict());
-
- int nStroke = 2;
- CFNumberRef rStroke = CFNumberCreate(NULL, kCFNumberSInt32Type, &nStroke);
- CFDictionarySetValue(styledict, kCTStrokeWidthAttributeName, rStroke);
-
- CFAttributedStringRef pAttrStr = CFAttributedStringCreate(
- NULL,
- CFAttributedStringGetString(mpAttrString),
- styledict);
- CTLineRef pCTLine = CTLineCreateWithAttributedString( pAttrStr );
- SAL_INFO( "vcl.ct", "CTLineCreateWithAttributedString(" << GetOUString(CFAttributedStringGetString(mpAttrSring)) << ") = " << pCTLine );
- CFRelease( pAttrStr );
-
- /* draw the text in 'outline' */
- drawCTLine(rAquaGraphics, pCTLine, mpTextStyle);
- SAL_INFO( "vcl.ct", "CFRelease(" << pCTLine << ")" );
- CFRelease(pCTLine);
- return true;
- }
- else
-#endif
- {
- return SalLayout::DrawTextSpecial(rGraphics, flags);
- }
-}
-
-void CTLayout::drawCTLine(AquaSalGraphics& rAquaGraphics, CTLineRef ctline, const CoreTextStyle* const pStyle) const
-{
- // the view is vertically flipped => flipped glyphs
- // so apply a temporary transformation that it flips back
- // also compensate if the font was size limited
- CGContextRef context = rAquaGraphics.mrContext;
- SAL_INFO( "vcl.ct", "CGContextSaveGState(" << context << ")" );
- CGContextSaveGState( context );
- SAL_INFO( "vcl.ct", "CGContextScaleCTM(" << context << ",1.0,-1.0)" );
- CGContextScaleCTM( context, 1.0, -1.0 );
- CGContextSetShouldAntialias( context, !rAquaGraphics.mbNonAntialiasedText );
-
- // set the text transformation (e.g. position)
- CGPoint aTextPos = GetTextDrawPosition();
-
- if( pStyle->mfFontRotation != 0.0 )
- {
- const CGFloat fRadians = pStyle->mfFontRotation;
- SAL_INFO( "vcl.ct", "CGContextRotateCTM(" << context << "," << +fRadians << ")" );
- CGContextRotateCTM( context, +fRadians );
-
- const CGAffineTransform aInvMatrix = CGAffineTransformMakeRotation( -fRadians );
- aTextPos = CGPointApplyAffineTransform( aTextPos, aInvMatrix );
- }
-
- SAL_INFO( "vcl.ct", "CGContextSetTextPosition(" << context << "," << aTextPos << ")" );
- CGContextSetTextPosition( context, aTextPos.x, aTextPos.y );
-
-#ifndef IOS
- // request an update of the to-be-changed window area
- if( rAquaGraphics.IsWindowGraphics() )
- {
- const CGRect aInkRect = CTLineGetImageBounds( mpCTLine, context );
- const CGRect aRefreshRect = CGContextConvertRectToDeviceSpace( context, aInkRect );
- rAquaGraphics.RefreshRect( aRefreshRect );
- }
-#endif
-
- // set the text color as fill color (see kCTForegroundColorFromContextAttributeName)
- CGContextSetFillColor( context, rAquaGraphics.maTextColor.AsArray() );
-
- SAL_INFO( "vcl.ct", "CTLineDraw(" << ctline << "," << context << ")" );
- // draw the text
- CTLineDraw( ctline, context );
-
- if(mnLayoutFlags & SalLayoutFlags::DrawBullet)
- {
- CFArrayRef runArray = CTLineGetGlyphRuns(ctline);
- CFIndex runCount = CFArrayGetCount(runArray);
-
- for (CFIndex runIndex = 0; runIndex < runCount; runIndex++)
- {
- CTRunRef run = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, runIndex));
- CFIndex runGlyphCount = CTRunGetGlyphCount(run);
- CGPoint position;
- CGSize advance;
- CFIndex runGlyphIndex = 0;
- CFIndex stringIndice = 0;
-
- for (; runGlyphIndex < runGlyphCount; runGlyphIndex++)
- {
- CFRange glyphRange = CFRangeMake(runGlyphIndex, 1);
- CTRunGetStringIndices( run, glyphRange, &stringIndice );
- UniChar curChar = CFStringGetCharacterAtIndex (CFAttributedStringGetString(mpAttrString), stringIndice);
- if(curChar == ' ')
- {
- CGFloat ascent;
- CGFloat descent;
- CGFloat leading;
- CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(CTRunGetAttributes(run),
- kCTFontAttributeName));
- CGFloat baseSize = CTFontGetSize(runFont);
- CTRunGetTypographicBounds ( run, glyphRange,
- &ascent, &descent, &leading);
- CTRunGetPositions(run, glyphRange, &position);
- CTRunGetAdvances(run, glyphRange, &advance);
- CGRect bulletRect;
- if(mnLayoutFlags & SalLayoutFlags::Vertical)
- {
- bulletRect = CGRectMake(position.x - advance.width / 4,
- -position.y, baseSize / 5, baseSize / 5 );
- }
- else
- {
- bulletRect = CGRectMake(position.x + advance.width / 4,
- position.y + ascent / 3 - baseSize / 5, baseSize / 5, baseSize / 5 );
- }
-
- CGContextSaveGState(context);
- CGContextTranslateCTM(context, aTextPos.x, aTextPos.y);
- RGBAColor bulletColor(MAKE_SALCOLOR(0x26, 0x8b, 0xd2 )); // NON_PRINTING_CHARACTER_COLOR
- CGContextSetFillColor( context, bulletColor.AsArray() );
- CGContextSetStrokeColor(context, bulletColor.AsArray());
- if(mnLayoutFlags & SalLayoutFlags::Vertical)
- {
- CGContextRotateCTM( context, -F_PI/2 );
- }
-
- CGContextBeginPath(context);
- CGContextAddEllipseInRect(context, bulletRect);
- CGContextDrawPath(context, kCGPathFillStroke); // Or kCGPathFill
- CGContextRestoreGState(context);
- }
- }
- }
- }
- // restore the original graphic context transformations
- SAL_INFO( "vcl.ct", "CGContextRestoreGState(" << context << ")" );
- CGContextRestoreGState( context );
-}
-
-void CTLayout::DrawText( SalGraphics& rGraphics ) const
-{
- AquaSalGraphics& rAquaGraphics = static_cast<AquaSalGraphics&>(rGraphics);
-
- // short circuit if there is nothing to do
- if( (mnCharCount <= 0) || !rAquaGraphics.CheckContext() )
- return;
-
- drawCTLine(rAquaGraphics, mpCTLine, mpTextStyle);
-}
-
-bool CTLayout::CacheGlyphLayout() const // eew!
-{
- m_vRunData.clear();
- if(!mpCTLine)
- {
- return false;
- }
- CFArrayRef aRuns = CTLineGetGlyphRuns( mpCTLine );
- const int nRun = CFArrayGetCount( aRuns );
- int nPos = 0;
-
- for( int i = 0; i < nRun; ++i )
- {
- CTRunRef pRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex( aRuns, i ));
- CTRunData* pRunData = new CTRunData(pRun, nPos);
- m_vRunData.push_back(std::unique_ptr<CTRunData>(pRunData));
- nPos += pRunData->m_nGlyphs;
- }
- bLayouted = true;
- return true;
-}
-
-int CTLayout::GetNextGlyphs( int nLen, sal_GlyphId* pOutGlyphIds, Point& rPos, int& nStart,
- DeviceCoordinate* pGlyphAdvances, int* pCharIndexes,
- const PhysicalFontFace** pFallbackFonts ) const
-{
- if( !mpCTLine )
- {
- return 0;
- }
- if(!bLayouted)
- {
- CacheGlyphLayout();
- }
-
- if( nStart < 0 ) // first glyph requested?
- {
- nStart = 0;
- }
- const PhysicalFontFace* pFallbackFont = nullptr;
- CTFontRef pFont = nullptr;
- CTFontDescriptorRef pFontDesc = nullptr;
- FontAttributes rDevFontAttr;
-
- auto iter = m_vRunData.begin();
-
- while (iter != m_vRunData.end() && (*iter)->m_EndPos <= nStart)
- {
- ++iter;
- }
- if(iter == m_vRunData.end())
- {
- return 0;
- }
- else
- {
- if( pFallbackFonts )
- {
- pFont = static_cast<CTFontRef>(CFDictionaryGetValue( mpTextStyle->GetStyleDict(), kCTFontAttributeName ));
- pFontDesc = CTFontCopyFontDescriptor( (*iter)->m_pFont );
- rDevFontAttr = DevFontFromCTFontDescriptor( pFontDesc, nullptr );
- }
- }
- int i = nStart;
- int count = 0;
- while( i < nStart + nLen )
- {
- // convert glyph details for VCL
- int j = i - (*iter)->m_StartPos;
- *(pOutGlyphIds++) = (*iter)->m_pGlyphs[ j ];
- if( pGlyphAdvances )
- {
- *(pGlyphAdvances++) = lrint((*iter)->m_pAdvances[ j ].width);
- }
- if( pCharIndexes )
- {
- *(pCharIndexes++) = (*iter)->m_pStringIndices[ j ] + mnMinCharPos;
- }
- if( pFallbackFonts )
- {
- if (!CFEqual((*iter)->m_pFont, pFont))
- {
- pFallbackFont = new CoreTextFontFace( rDevFontAttr, reinterpret_cast<sal_IntPtr>(pFontDesc) );
- *(pFallbackFonts++) = pFallbackFont;
- }
- else
- {
- *(pFallbackFonts++) = nullptr;
- }
- }
- if( i == nStart )
- {
- const CGPoint& rFirstPos = (*iter)->m_pPositions[ j ];
- rPos = GetDrawPosition( Point( rFirstPos.x, rFirstPos.y) );
- }
- i += 1;
- count += 1;
- if (i == (*iter)->m_EndPos)
- {
- // note: we assume that we do not have empty runs in the middle of things
- ++iter;
- if (iter == m_vRunData.end())
- {
- break;
- }
- if( pFallbackFonts )
- {
- pFont = static_cast<CTFontRef>(CFDictionaryGetValue( mpTextStyle->GetStyleDict(), kCTFontAttributeName ));
- pFontDesc = CTFontCopyFontDescriptor( (*iter)->m_pFont );
- rDevFontAttr = DevFontFromCTFontDescriptor( pFontDesc, nullptr );
- }
- }
- }
- nStart = i;
-
- return count;
-
-}
-
-DeviceCoordinate CTLayout::GetTextWidth() const
-{
- if( (mnCharCount <= 0) || !mpCTLine )
- return 0;
-
- if( mfCachedWidth < 0.0 )
- {
- mfCachedWidth = CTLineGetTypographicBounds( mpCTLine, nullptr, nullptr, nullptr);
- }
-
- return mfCachedWidth;
-}
-
-DeviceCoordinate CTLayout::FillDXArray( DeviceCoordinate* pDXArray ) const
-{
- DeviceCoordinate nPixelWidth = GetTextWidth();
-
- // short circuit requests which don't need full details
- if( !pDXArray )
- {
- return nPixelWidth;
- }
-
- for(int i = 0; i < mnCharCount; i++)
- {
- pDXArray[i] = 0.0;
- }
-
- // prepare the sub-pixel accurate logical-width array
- ::std::vector<float> aWidthVector( mnCharCount );
- if( mnTrailingSpaceCount && (mfTrailingSpaceWidth > 0.0) )
- {
- const double fOneWidth = mfTrailingSpaceWidth / mnTrailingSpaceCount;
- for(int i = mnCharCount - mnTrailingSpaceCount; i < mnCharCount; i++)
- {
- aWidthVector[i] = fOneWidth;
- }
- }
-
- // handle each glyph run
- CFArrayRef aGlyphRuns = CTLineGetGlyphRuns( mpCTLine );
- const int nRunCount = CFArrayGetCount( aGlyphRuns );
- typedef std::vector<CGSize> CGSizeVector;
- CGSizeVector aSizeVector;
- typedef std::vector<CFIndex> CFIndexVector;
- CFIndexVector aIndexVector;
-
- for( int nRunIndex = 0; nRunIndex < nRunCount; ++nRunIndex )
- {
- CTRunRef pGlyphRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex( aGlyphRuns, nRunIndex ));
- const CFIndex nGlyphCount = CTRunGetGlyphCount( pGlyphRun );
- const CFRange aFullRange = CFRangeMake( 0, nGlyphCount );
-
- aSizeVector.resize( nGlyphCount );
- aIndexVector.resize( nGlyphCount );
- CTRunGetAdvances( pGlyphRun, aFullRange, &aSizeVector[0] );
- CTRunGetStringIndices( pGlyphRun, aFullRange, &aIndexVector[0] );
-
- for( int i = 0; i != nGlyphCount; ++i )
- {
- const int nRelIndex = aIndexVector[i];
- SAL_INFO( "vcl.ct", "aWidthVector[ g:" << i << "-> c:" << nRelIndex << " ] = " <<
- aWidthVector[nRelIndex] << " + " << aSizeVector[i].width << " = " <<
- aWidthVector[nRelIndex] + aSizeVector[i].width);
- aWidthVector[nRelIndex] += aSizeVector[i].width;
- }
- }
-
- // convert the sub-pixel accurate array into classic pDXArray integers
- float fWidthSum = 0.0;
- sal_Int32 nOldDX = 0;
- for( int i = 0; i < mnCharCount; ++i)
- {
- const sal_Int32 nNewDX = rint( fWidthSum += aWidthVector[i]);
- pDXArray[i] = nNewDX - nOldDX;
- nOldDX = nNewDX;
- }
- return nPixelWidth;
-}
-
-sal_Int32 CTLayout::GetTextBreak( DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor ) const
-{
- if( !mpCTLine )
- {
- SAL_INFO("vcl.ct", "GetTextBreak mpCTLine == NULL");
- return -1;
- }
- CTTypesetterRef aCTTypeSetter = CTTypesetterCreateWithAttributedString( mpAttrString );
- CFIndex nBestGuess = (nCharExtra >= 0) ? 0 : mnCharCount;
- for( int i = 1; i <= mnCharCount; i *= 2 )
- {
- // guess the target width considering char-extra expansion/condensation
- const double nTargetWidth = nMaxWidth - nBestGuess * nCharExtra;
- const double fCTMaxWidth = nTargetWidth / nFactor;
- // calculate the breaking index for the guessed target width
- const CFIndex nNewIndex = CTTypesetterSuggestClusterBreak( aCTTypeSetter, 0, fCTMaxWidth );
- if( nNewIndex >= mnCharCount )
- {
- CFRelease( aCTTypeSetter );
- return -1;
- }
- // check if the original extra-width guess was good
- if( !nCharExtra )
- nBestGuess = nNewIndex;
-
- if( nBestGuess == nNewIndex )
- break;
-
- // prepare another round for a different number of characters
- CFIndex nNewGuess = (nNewIndex + nBestGuess + 1) / 2;
- if( nNewGuess == nBestGuess )
- {
- nNewGuess += (nNewIndex > nBestGuess) ? +1 : -1;
- }
- nBestGuess = nNewGuess;
- }
-
- // suggest the best fitting cluster break as breaking position
- CFRelease( aCTTypeSetter );
-
- const int nIndex = nBestGuess + mnMinCharPos;
- SAL_INFO("vcl.ct", "GetTextBreak nIndex:" << nIndex);
-
- return nIndex;
-}
-
-void CTLayout::GetCaretPositions( int nMaxIndex, long* pCaretXArray ) const
-{
- SAL_WARN_IF( (nMaxIndex<=0) || (nMaxIndex&1), "vcl",
- "CTLayout::GetCaretPositions() : invalid number of caret pairs requested");
-
- // initialize the caret positions
- for( int i = 0; i < nMaxIndex; ++i )
- {
- pCaretXArray[ i ] = -1;
- }
- for( int n = 0; n <= mnCharCount; ++n )
- {
- // measure the characters cursor position
- CGFloat fPos2 = -1;
- const CGFloat fPos1 = CTLineGetOffsetForStringIndex( mpCTLine, n, &fPos2 );
- (void)fPos2; // TODO: split cursor at line direction change
-
- // update previous trailing position
- if( n > 0 )
- pCaretXArray[ 2*n-1 ] = lrint( fPos1 );
-
- // update current leading position
- if( 2*n >= nMaxIndex )
- break;
- pCaretXArray[ 2*n+0 ] = lrint( fPos1 );
- }
-}
-
-bool CTLayout::GetBoundRect( SalGraphics& rGraphics, Rectangle& rVCLRect ) const
-{
- // Closely mimic DrawText(), except that instead of calling
- // CTLineDraw() to draw the line, we call CTLineGetImageBounds()
- // to get its bounds. But all the coordinate system manipulation
- // before that is the same => should be factored out?
-
- AquaSalGraphics& rAquaGraphics = static_cast<AquaSalGraphics&>(rGraphics);
-
- if( !rAquaGraphics.CheckContext() )
- return false;
-
- CGContextSaveGState( rAquaGraphics.mrContext );
- CGContextScaleCTM( rAquaGraphics.mrContext, 1.0, -1.0 );
- CGContextSetShouldAntialias( rAquaGraphics.mrContext, !rAquaGraphics.mbNonAntialiasedText );
-
- const CGPoint aVclPos = GetTextDrawPosition();
- CGPoint aTextPos = GetTextDrawPosition();
-
- if( mpTextStyle->mfFontRotation != 0.0 )
- {
- const CGFloat fRadians = mpTextStyle->mfFontRotation;
- CGContextRotateCTM( rAquaGraphics.mrContext, +fRadians );
-
- const CGAffineTransform aInvMatrix = CGAffineTransformMakeRotation( -fRadians );
- aTextPos = CGPointApplyAffineTransform( aTextPos, aInvMatrix );
- }
-
- CGContextSetTextPosition( rAquaGraphics.mrContext, aTextPos.x, aTextPos.y );
- CGRect aMacRect = CTLineGetImageBounds( mpCTLine, rAquaGraphics.mrContext );
-
- if( mpTextStyle->mfFontRotation != 0.0 )
- {
- const CGFloat fRadians = mpTextStyle->mfFontRotation;
- const CGAffineTransform aMatrix = CGAffineTransformMakeRotation( +fRadians );
- aMacRect = CGRectApplyAffineTransform( aMacRect, aMatrix );
- }
-
- CGContextRestoreGState( rAquaGraphics.mrContext );
-
- rVCLRect.Left() = aVclPos.x + lrint(aMacRect.origin.x);
- rVCLRect.Right() = aVclPos.x + lrint(aMacRect.origin.x + aMacRect.size.width);
- rVCLRect.Bottom() = aVclPos.x - lrint(aMacRect.origin.y);
- rVCLRect.Top() = aVclPos.x - lrint(aMacRect.origin.y + aMacRect.size.height);
-
- return true;
-}
-
-// glyph fallback is supported directly by Aqua
-// so methods used only by MultiSalLayout can be dummy implementated
-void CTLayout::InitFont() const {}
-void CTLayout::MoveGlyph( int /*nStart*/, long /*nNewXPos*/ ) {}
-void CTLayout::DropGlyph( int /*nStart*/ ) {}
-void CTLayout::Simplify( bool /*bIsBase*/ ) {}
-
-SalLayout* CoreTextStyle::GetTextLayout() const
-{
- return new CTLayout( this);
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx
index a58870f825af..0333bbf0f6c2 100644
--- a/vcl/quartz/salgdi.cxx
+++ b/vcl/quartz/salgdi.cxx
@@ -380,11 +380,8 @@ 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);
- }
+ static CoreTextGlyphFallbackSubstititution aSubstFallback;
+ pFontCollection->SetFallbackHook(&aSubstFallback);
}
void AquaSalGraphics::ClearDevFontCache()
@@ -534,15 +531,10 @@ void AquaSalGraphics::SetFont(FontSelectPattern* pReqFont, int nFallbackLevel)
SalLayout* AquaSalGraphics::GetTextLayout(ImplLayoutArgs& /*rArgs*/, int nFallbackLevel)
{
- SalLayout* pSalLayout = nullptr;
if (mpTextStyle[nFallbackLevel])
- {
- if (SalLayout::UseCommonLayout())
- pSalLayout = new CommonSalLayout(*mpTextStyle[nFallbackLevel]);
- else
- pSalLayout = mpTextStyle[nFallbackLevel]->GetTextLayout();
- }
- return pSalLayout;
+ return new CommonSalLayout(*mpTextStyle[nFallbackLevel]);
+
+ return nullptr;
}
const FontCharMapRef AquaSalGraphics::GetFontCharMap() const