summaryrefslogtreecommitdiff
path: root/vcl/coretext
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2013-12-05 22:01:05 +0200
committerTor Lillqvist <tml@collabora.com>2013-12-06 15:05:00 +0200
commitc49721950cb3d897b35f08bf871239308680b18e (patch)
tree6a76e91557328b9195960d065065b1a6914bf9be /vcl/coretext
parent693eced961a3d3014d15e0a406f4e001ee817522 (diff)
Re-organize OS X and iOS code in vcl a bit
Now with the ATSUI code gone is a good time for some re-organisation. Get rid of "aqua" in file names and the separate "coretext" folders. CoreText is all we use now for OS X (and has always been so for iOS), so no need for a "coretext" folder, we can keep the CoreText-using code under "quartz". Keep OS X -specific code in "osx". Ditto for headers. Keep "Aqua" as part of class names for now, though. This is also preparation for planned further unification between OS X and iOS code. Change-Id: Ic60bd73fea4ab98183e7c8a09c7d3f66b9a34223
Diffstat (limited to 'vcl/coretext')
-rw-r--r--vcl/coretext/ctfonts.cxx478
-rw-r--r--vcl/coretext/ctfonts.hxx28
-rw-r--r--vcl/coretext/ctlayout.cxx501
-rw-r--r--vcl/coretext/salgdi.cxx889
4 files changed, 0 insertions, 1896 deletions
diff --git a/vcl/coretext/ctfonts.cxx b/vcl/coretext/ctfonts.cxx
deleted file mode 100644
index fd113b892099..000000000000
--- a/vcl/coretext/ctfonts.cxx
+++ /dev/null
@@ -1,478 +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 <boost/unordered_map.hpp>
-
-#include "impfont.hxx"
-#include "outfont.hxx"
-#include "sallayout.hxx"
-
-#ifdef MACOSX
-#include "aqua/salinst.h"
-#include "aqua/saldata.hxx"
-#endif
-#include "coretext/salgdi.h"
-#include "quartz/utils.h"
-#include "ctfonts.hxx"
-
-#include "basegfx/polygon/b2dpolygon.hxx"
-#include "basegfx/matrix/b2dhommatrix.hxx"
-
-// =======================================================================
-
-inline double toRadian(int nDegree)
-{
- return nDegree * (M_PI / 1800.0);
-}
-
-CoreTextStyle::CoreTextStyle( const FontSelectPattern& rFSD )
-: mpFontData( (CoreTextFontData*)rFSD.mpFontData )
-, mfFontStretch( 1.0 )
-, mfFontRotation( 0.0 )
-, mpStyleDict( NULL )
-{
- mpFontData = (CoreTextFontData*)rFSD.mpFontData;
- const FontSelectPattern* const pReqFont = &rFSD;
-
- double fScaledFontHeight = pReqFont->mfExactHeight;
-
- // convert font rotation to radian
- mfFontRotation = toRadian(pReqFont->mnOrientation);
-
- // dummy matrix so we can use CGAffineTransformConcat() below
- CGAffineTransform aMatrix = CGAffineTransformMakeTranslation(0, 0);
-
- // handle font stretching if any
- if( (pReqFont->mnWidth != 0) && (pReqFont->mnWidth != pReqFont->mnHeight) )
- {
- mfFontStretch = (float)pReqFont->mnWidth / pReqFont->mnHeight;
- aMatrix = CGAffineTransformConcat(aMatrix, CGAffineTransformMakeScale(mfFontStretch, 1.0F));
- }
-
- // create the style object for CoreText font attributes
- static const CFIndex nMaxDictSize = 16; // TODO: does this really suffice?
- mpStyleDict = CFDictionaryCreateMutable( NULL, nMaxDictSize,
- &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
-
- CFBooleanRef pCFVertBool = pReqFont->mbVertical ? kCFBooleanTrue : kCFBooleanFalse;
- CFDictionarySetValue( mpStyleDict, kCTVerticalFormsAttributeName, pCFVertBool );
-
- // fake bold
- if ((pReqFont->GetWeight() >= WEIGHT_BOLD) && (mpFontData->GetWeight() < WEIGHT_SEMIBOLD))
- {
- int nStroke = -10.0;
- CFNumberRef rStroke = CFNumberCreate(NULL, kCFNumberSInt32Type, &nStroke);
- CFDictionarySetValue(mpStyleDict, kCTStrokeWidthAttributeName, rStroke);
- }
-
- // fake italic
- if (((pReqFont->GetSlant() == ITALIC_NORMAL) || (pReqFont->GetSlant() == ITALIC_OBLIQUE))
- && !((mpFontData->GetSlant() == ITALIC_NORMAL) || (mpFontData->GetSlant() == ITALIC_OBLIQUE)))
- {
- aMatrix = CGAffineTransformConcat(aMatrix, CGAffineTransformMake(1, 0, toRadian(120), 1, 0, 0));
- }
-
- CTFontDescriptorRef pFontDesc = (CTFontDescriptorRef)mpFontData->GetFontId();
- CTFontRef pNewCTFont = CTFontCreateWithFontDescriptor( pFontDesc, fScaledFontHeight, &aMatrix );
- CFDictionarySetValue( mpStyleDict, kCTFontAttributeName, pNewCTFont );
- CFRelease( pNewCTFont);
-
-#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( void )
-{
- if( mpStyleDict )
- CFRelease( mpStyleDict );
-}
-
-// -----------------------------------------------------------------------
-
-void CoreTextStyle::GetFontMetric( float fPixelSize, ImplFontMetricData& rMetric ) const
-{
- // get the matching CoreText font handle
- // TODO: is it worth it to cache the CTFontRef in SetFont() and reuse it here?
- CTFontRef aCTFontRef = (CTFontRef)CFDictionaryGetValue( mpStyleDict, kCTFontAttributeName );
-
- rMetric.mnAscent = lrint( CTFontGetAscent( aCTFontRef ) * fPixelSize);
- rMetric.mnDescent = lrint( CTFontGetDescent( aCTFontRef ) * fPixelSize);
- rMetric.mnExtLeading = lrint( CTFontGetLeading( aCTFontRef ) * fPixelSize);
- rMetric.mnIntLeading = 0;
- // since ImplFontMetricData::mnWidth is only used for stretching/squeezing fonts
- // setting this width to the pixel height of the fontsize is good enough
- // it also makes the calculation of the stretch factor simple
- rMetric.mnWidth = lrint( CTFontGetSize( aCTFontRef ) * fPixelSize * mfFontStretch);
-
- // all CoreText fonts are scalable
- rMetric.mbScalableFont = true;
- rMetric.mbKernableFont = true;
-}
-
-// -----------------------------------------------------------------------
-
-bool CoreTextStyle::GetGlyphBoundRect( sal_GlyphId nGlyphId, Rectangle& rRect ) const
-{
- CGGlyph nCGGlyph = nGlyphId & GF_IDXMASK;
- // XXX: this is broken if the glyph came from fallback font
- CTFontRef aCTFontRef = (CTFontRef)CFDictionaryGetValue( mpStyleDict, kCTFontAttributeName );
-
- const CTFontOrientation aFontOrientation = kCTFontDefaultOrientation; // TODO: horz/vert
- const CGRect aCGRect = CTFontGetBoundingRectsForGlyphs( aCTFontRef, aFontOrientation, &nCGGlyph, NULL, 1 );
-
- rRect.Left() = lrint( aCGRect.origin.x );
- rRect.Top() = lrint( aCGRect.origin.y );
- rRect.Right() = lrint( aCGRect.origin.x + aCGRect.size.width );
- rRect.Bottom() = lrint( aCGRect.origin.y + aCGRect.size.height );
- return true;
-}
-
-// -----------------------------------------------------------------------
-
-// callbacks from CTFontCreatePathForGlyph+CGPathApply for GetGlyphOutline()
-struct GgoData { basegfx::B2DPolygon maPolygon; basegfx::B2DPolyPolygon* mpPolyPoly; };
-
-static void MyCGPathApplierFunc( void* pData, const CGPathElement* pElement )
-{
- basegfx::B2DPolygon& rPolygon = static_cast<GgoData*>(pData)->maPolygon;
- const int nPointCount = rPolygon.count();
-
- switch( pElement->type )
- {
- case kCGPathElementCloseSubpath:
- case kCGPathElementMoveToPoint:
- if( nPointCount > 0 ) {
- static_cast<GgoData*>(pData)->mpPolyPoly->append( rPolygon );
- rPolygon.clear();
- }
- // fall through for kCGPathElementMoveToPoint:
- if( pElement->type != kCGPathElementMoveToPoint )
- break;
- case kCGPathElementAddLineToPoint:
- rPolygon.append( basegfx::B2DPoint( +pElement->points[0].x, -pElement->points[0].y ) );
- break;
- case kCGPathElementAddCurveToPoint:
- rPolygon.append( basegfx::B2DPoint( +pElement->points[2].x, -pElement->points[2].y ) );
- rPolygon.setNextControlPoint( nPointCount-1, basegfx::B2DPoint( pElement->points[0].x, -pElement->points[0].y ) );
- rPolygon.setPrevControlPoint( nPointCount+0, basegfx::B2DPoint( pElement->points[1].x, -pElement->points[1].y ) );
- break;
- case kCGPathElementAddQuadCurveToPoint: {
- const basegfx::B2DPoint aStartPt = rPolygon.getB2DPoint( nPointCount-1 );
- const basegfx::B2DPoint aCtrPt1( (aStartPt.getX() + 2* pElement->points[0].x) / 3.0,
- (aStartPt.getY() - 2 * pElement->points[0].y) / 3.0 );
- const basegfx::B2DPoint aCtrPt2( (+2 * +pElement->points[0].x + pElement->points[1].x) / 3.0,
- (-2 * pElement->points[0].y - pElement->points[1].y) / 3.0 );
- rPolygon.append( basegfx::B2DPoint( +pElement->points[1].x, -pElement->points[1].y ) );
- rPolygon.setNextControlPoint( nPointCount-1, aCtrPt1 );
- rPolygon.setPrevControlPoint( nPointCount+0, aCtrPt2 );
- } break;
- }
-}
-
-bool CoreTextStyle::GetGlyphOutline( sal_GlyphId nGlyphId, basegfx::B2DPolyPolygon& rResult ) const
-{
- rResult.clear();
-
- CGGlyph nCGGlyph = nGlyphId & GF_IDXMASK;
- // XXX: this is broken if the glyph came from fallback font
- CTFontRef pCTFont = (CTFontRef)CFDictionaryGetValue( mpStyleDict, kCTFontAttributeName );
- CGPathRef xPath = CTFontCreatePathForGlyph( pCTFont, nCGGlyph, NULL );
-
- GgoData aGgoData;
- aGgoData.mpPolyPoly = &rResult;
- CGPathApply( xPath, (void*)&aGgoData, MyCGPathApplierFunc );
-#if 0 // TODO: does OSX ensure that the last polygon is always closed?
- const CGPathElement aClosingElement = { kCGPathElementCloseSubpath, NULL };
- MyCGPathApplierFunc( (void*)&aGgoData, &aClosingElement );
-#endif
-
- return true;
-}
-
-// -----------------------------------------------------------------------
-
-void CoreTextStyle::SetTextColor( const RGBAColor& rColor )
-{
- CGFloat aColor[] = { rColor.GetRed(), rColor.GetGreen(), rColor.GetBlue(), rColor.GetAlpha() };
- CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
- CGColorRef pCGColor = CGColorCreate( cs, aColor );
- CGColorSpaceRelease( cs );
- CFDictionarySetValue( mpStyleDict, kCTForegroundColorAttributeName, pCGColor );
- CFRelease( pCGColor);
-}
-
-// =======================================================================
-
-PhysicalFontFace* CoreTextFontData::Clone( void ) const
-{
- return new CoreTextFontData( *this);
-}
-
-// -----------------------------------------------------------------------
-
-CoreTextStyle* CoreTextFontData::CreateTextStyle( const FontSelectPattern& rFSD ) const
-{
- return new CoreTextStyle( rFSD);
-}
-
-// -----------------------------------------------------------------------
-
-ImplFontEntry* CoreTextFontData::CreateFontInstance( /*const*/ FontSelectPattern& rFSD ) const
-{
- return new ImplFontEntry( rFSD);
-}
-
-// -----------------------------------------------------------------------
-
-int CoreTextFontData::GetFontTable( const char pTagName[5], unsigned char* pResultBuf ) const
-{
- DBG_ASSERT( pTagName[4]=='\0', "CoreTextFontData::GetFontTable with invalid tagname!\n" );
-
- const CTFontTableTag nTagCode = (pTagName[0]<<24) + (pTagName[1]<<16) + (pTagName[2]<<8) + (pTagName[3]<<0);
-
- // get the raw table length
- CTFontDescriptorRef pFontDesc = reinterpret_cast<CTFontDescriptorRef>( GetFontId());
- CTFontRef rCTFont = CTFontCreateWithFontDescriptor( pFontDesc, 0.0, NULL);
-#if defined(MACOSX) && MACOSX_SDK_VERSION < 1080
- const uint32_t opts( kCTFontTableOptionExcludeSynthetic );
-#else
- const uint32_t opts( kCTFontTableOptionNoOptions );
-#endif
- CFDataRef pDataRef = CTFontCopyTable( rCTFont, nTagCode, opts);
- CFRelease( rCTFont);
- if( !pDataRef)
- return 0;
-
- const CFIndex nByteLength = CFDataGetLength( pDataRef);
-
- // get the raw table data if requested
- if( pResultBuf && (nByteLength > 0))
- {
- const CFRange aFullRange = CFRangeMake( 0, nByteLength);
- CFDataGetBytes( pDataRef, aFullRange, (UInt8*)pResultBuf);
- }
-
- CFRelease( pDataRef);
-
- return (int)nByteLength;
-}
-
-// =======================================================================
-
-ImplDevFontAttributes DevFontFromCTFontDescriptor( CTFontDescriptorRef pFD, bool* bFontEnabled )
-{
- // all CoreText fonts are device fonts that can rotate just fine
- ImplDevFontAttributes rDFA;
- rDFA.mbOrientation = true;
- rDFA.mbDevice = true;
- rDFA.mnQuality = 0;
-
- // reset the font attributes
- rDFA.SetFamilyType( FAMILY_DONTKNOW );
- rDFA.SetPitch( PITCH_VARIABLE );
- rDFA.SetWidthType( WIDTH_NORMAL );
- rDFA.SetWeight( WEIGHT_NORMAL );
- rDFA.SetItalic( ITALIC_NONE );
- rDFA.SetSymbolFlag( false );
-
- // all scalable fonts on this platform are subsettable
- rDFA.mbEmbeddable = false;
- rDFA.mbSubsettable = true;
-
- // get font name
- CFStringRef pFamilyName = (CFStringRef)CTFontDescriptorCopyAttribute( pFD, kCTFontFamilyNameAttribute );
- rDFA.SetFamilyName( GetOUString( pFamilyName ) );
- // get font style
- CFStringRef pStyleName = (CFStringRef)CTFontDescriptorCopyAttribute( pFD, kCTFontStyleNameAttribute );
- rDFA.SetStyleName( GetOUString( pStyleName ) );
-
- // get font-enabled status
- if( bFontEnabled ) {
- int bEnabled = FALSE;
- CFNumberRef pEnabled = (CFNumberRef)CTFontDescriptorCopyAttribute( pFD, kCTFontEnabledAttribute );
- CFNumberGetValue( pEnabled, kCFNumberIntType, &bEnabled );
- *bFontEnabled = bEnabled;
- }
-
- // get font attributes
- CFDictionaryRef pAttrDict = (CFDictionaryRef)CTFontDescriptorCopyAttribute( pFD, kCTFontTraitsAttribute );
-
- // get symbolic trait
- // TODO: use other traits such as MonoSpace/Condensed/Expanded or Vertical too
- SInt64 nSymbolTrait = 0;
- CFNumberRef pSymbolNum = NULL;
- if( CFDictionaryGetValueIfPresent( pAttrDict, kCTFontSymbolicTrait, (const void**)&pSymbolNum ) ) {
- CFNumberGetValue( pSymbolNum, kCFNumberSInt64Type, &nSymbolTrait );
- rDFA.SetSymbolFlag( ((nSymbolTrait & kCTFontClassMaskTrait) == kCTFontSymbolicClass) );
- }
-
- // get the font weight
- double fWeight = 0;
- CFNumberRef pWeightNum = (CFNumberRef)CFDictionaryGetValue( pAttrDict, kCTFontWeightTrait );
- CFNumberGetValue( pWeightNum, kCFNumberDoubleType, &fWeight );
- int nInt = WEIGHT_NORMAL;
- if( fWeight > 0 ) {
- nInt = rint(WEIGHT_NORMAL + fWeight * ((WEIGHT_BLACK - WEIGHT_NORMAL)/0.68));
- if( nInt > WEIGHT_BLACK )
- nInt = WEIGHT_BLACK;
- } else if( fWeight < 0 ) {
- nInt = rint(WEIGHT_NORMAL + fWeight * ((WEIGHT_NORMAL - WEIGHT_THIN)/0.9));
- if( nInt < WEIGHT_THIN )
- nInt = WEIGHT_THIN;
- }
- rDFA.SetWeight( (FontWeight)nInt );
-
- // get the font slant
- double fSlant = 0;
- CFNumberRef pSlantNum = (CFNumberRef)CFDictionaryGetValue( pAttrDict, kCTFontSlantTrait );
- CFNumberGetValue( pSlantNum, kCFNumberDoubleType, &fSlant );
- if( fSlant >= 0.035 )
- rDFA.SetItalic( ITALIC_NORMAL );
-
- // get width trait
- double fWidth = 0;
- CFNumberRef pWidthNum = (CFNumberRef)CFDictionaryGetValue( pAttrDict, kCTFontWidthTrait );
- CFNumberGetValue( pWidthNum, kCFNumberDoubleType, &fWidth );
- nInt = WIDTH_NORMAL;
- if( fWidth > 0 ) {
- nInt = rint( WIDTH_NORMAL + fWidth * ((WIDTH_ULTRA_EXPANDED - WIDTH_NORMAL)/0.4));
- if( nInt > WIDTH_ULTRA_EXPANDED )
- nInt = WIDTH_ULTRA_EXPANDED;
- } else if( fWidth < 0 ) {
- nInt = rint( WIDTH_NORMAL + fWidth * ((WIDTH_NORMAL - WIDTH_ULTRA_CONDENSED)/0.5));
- if( nInt < WIDTH_ULTRA_CONDENSED )
- nInt = WIDTH_ULTRA_CONDENSED;
- }
- rDFA.SetWidthType( (FontWidth)nInt );
-
- // release the attribute dict that we had copied
- CFRelease( pAttrDict );
-
- // TODO? also use the HEAD table if available to get more attributes
-// CFDataRef CTFontCopyTable( CTFontRef, kCTFontTableHead, /*kCTFontTableOptionNoOptions*/kCTFontTableOptionExcludeSynthetic );
-
- return rDFA;
-}
-
-static void CTFontEnumCallBack( const void* pValue, void* pContext )
-{
- CTFontDescriptorRef pFD = static_cast<CTFontDescriptorRef>(pValue);
-
- bool bFontEnabled;
- ImplDevFontAttributes rDFA = DevFontFromCTFontDescriptor( pFD, &bFontEnabled );
-
- if( bFontEnabled)
- {
- const sal_IntPtr nFontId = (sal_IntPtr)pValue;
- CoreTextFontData* pFontData = new CoreTextFontData( rDFA, nFontId );
- SystemFontList* pFontList = (SystemFontList*)pContext;
- pFontList->AddFont( pFontData );
- }
-}
-
-// =======================================================================
-
-SystemFontList::SystemFontList()
-: mpCTFontCollection( NULL )
-, mpCTFontArray( NULL )
-{}
-
-// -----------------------------------------------------------------------
-
-SystemFontList::~SystemFontList()
-{
- CTFontContainer::const_iterator it = maFontContainer.begin();
- for(; it != maFontContainer.end(); ++it )
- delete (*it).second;
- maFontContainer.clear();
-
- if( mpCTFontArray )
- CFRelease( mpCTFontArray );
- if( mpCTFontCollection )
- CFRelease( mpCTFontCollection );
-}
-
-// -----------------------------------------------------------------------
-
-void SystemFontList::AddFont( CoreTextFontData* pFontData )
-{
- sal_IntPtr nFontId = pFontData->GetFontId();
- maFontContainer[ nFontId ] = pFontData;
-}
-
-// -----------------------------------------------------------------------
-
-void SystemFontList::AnnounceFonts( ImplDevFontList& rFontList ) const
-{
- CTFontContainer::const_iterator it = maFontContainer.begin();
- for(; it != maFontContainer.end(); ++it )
- rFontList.Add( (*it).second->Clone() );
-}
-
-// -----------------------------------------------------------------------
-
-CoreTextFontData* SystemFontList::GetFontDataFromId( sal_IntPtr nFontId ) const
-{
- CTFontContainer::const_iterator it = maFontContainer.find( nFontId );
- if( it == maFontContainer.end() )
- return NULL;
- return (*it).second;
-}
-
-// -----------------------------------------------------------------------
-
-bool SystemFontList::Init( void )
-{
- // enumerate available system fonts
- static const int nMaxDictEntries = 8;
- CFMutableDictionaryRef pCFDict = CFDictionaryCreateMutable( NULL,
- nMaxDictEntries, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
- CFDictionaryAddValue( pCFDict, kCTFontCollectionRemoveDuplicatesOption, kCFBooleanTrue );
- mpCTFontCollection = CTFontCollectionCreateFromAvailableFonts( pCFDict );
- CFRelease( pCFDict );
-
- mpCTFontArray = CTFontCollectionCreateMatchingFontDescriptors( mpCTFontCollection );
- const int nFontCount = CFArrayGetCount( mpCTFontArray );
- const CFRange aFullRange = CFRangeMake( 0, nFontCount );
- CFArrayApplyFunction( mpCTFontArray, aFullRange, CTFontEnumCallBack, this );
-
- return true;
-}
-
-// =======================================================================
-
-SystemFontList* GetCoretextFontList( void )
-{
- SystemFontList* pList = new SystemFontList();
- if( !pList->Init() ) {
- delete pList;
- return NULL;
- }
-
- return pList;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/coretext/ctfonts.hxx b/vcl/coretext/ctfonts.hxx
deleted file mode 100644
index 44153115bb94..000000000000
--- a/vcl/coretext/ctfonts.hxx
+++ /dev/null
@@ -1,28 +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 "coretext/salgdi.h"
-#ifdef IOS
-#include "headless/svpgdi.hxx"
-#endif
-#include "sallayout.hxx"
-
-SystemFontList* GetCoretextFontList(void);
-ImplDevFontAttributes DevFontFromCTFontDescriptor( CTFontDescriptorRef, bool* );
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/coretext/ctlayout.cxx b/vcl/coretext/ctlayout.cxx
deleted file mode 100644
index 56d86967aa53..000000000000
--- a/vcl/coretext/ctlayout.cxx
+++ /dev/null
@@ -1,501 +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 "tools/debug.hxx"
-
-#include "ctfonts.hxx"
-
-class CTLayout
-: public SalLayout
-{
-public:
- explicit CTLayout( const CoreTextStyle* );
- virtual ~CTLayout( void );
-
- virtual bool LayoutText( ImplLayoutArgs& );
- virtual void AdjustLayout( ImplLayoutArgs& );
- virtual void DrawText( SalGraphics& ) const;
-
- virtual int GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos, int&,
- sal_Int32* pGlyphAdvances, int* pCharIndexes,
- const PhysicalFontFace** pFallbackFonts ) const;
-
- virtual long GetTextWidth() const;
- virtual long FillDXArray( sal_Int32* pDXArray ) const;
- virtual sal_Int32 GetTextBreak(long nMaxWidth, long nCharExtra, int nFactor) const SAL_OVERRIDE;
- virtual void GetCaretPositions( int nArraySize, sal_Int32* pCaretXArray ) const;
- virtual bool GetGlyphOutlines( SalGraphics&, PolyPolyVector& ) const;
- virtual bool GetBoundRect( SalGraphics&, Rectangle& ) const;
-
- virtual void InitFont( void) const;
- virtual void MoveGlyph( int nStart, long nNewXPos );
- virtual void DropGlyph( int nStart );
- virtual void Simplify( bool bIsBase );
-
-private:
- CGPoint GetTextDrawPosition(void) const;
- double GetWidth(void) const;
-
- const CoreTextStyle* const mpTextStyle;
-
- // CoreText specific objects
- CFAttributedStringRef mpAttrString;
- CTLineRef mpCTLine;
-
- int mnCharCount; // ==mnEndCharPos-mnMinCharPos
-
- // 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;
-};
-
-CTLayout::CTLayout( const CoreTextStyle* pTextStyle )
-: mpTextStyle( pTextStyle )
-, mpAttrString( NULL )
-, mpCTLine( NULL )
-, mnCharCount( 0 )
-, mfCachedWidth( -1 )
-, mfBaseAdv( 0 )
-{
-}
-
-CTLayout::~CTLayout()
-{
- if( mpCTLine )
- CFRelease( mpCTLine );
- if( mpAttrString )
- CFRelease( mpAttrString );
-}
-
-bool CTLayout::LayoutText( ImplLayoutArgs& rArgs )
-{
- if( mpAttrString )
- CFRelease( mpAttrString );
- mpAttrString = NULL;
- if( mpCTLine )
- CFRelease( mpCTLine );
- mpCTLine = NULL;
-
- SalLayout::AdjustLayout( rArgs );
- mnCharCount = mnEndCharPos - mnMinCharPos;
-
- // short circuit if there is nothing to do
- if( mnCharCount <= 0 )
- return false;
-
- // create the CoreText line layout
- CFStringRef aCFText = CFStringCreateWithCharactersNoCopy( NULL, rArgs.mpStr + mnMinCharPos, mnCharCount, kCFAllocatorNull );
- // CFAttributedStringCreate copies the attribues parameter
- mpAttrString = CFAttributedStringCreate( NULL, aCFText, mpTextStyle->GetStyleDict() );
- mpCTLine = CTLineCreateWithAttributedString( mpAttrString );
- CFRelease( aCFText);
-
- return true;
-}
-
-void CTLayout::AdjustLayout( ImplLayoutArgs& rArgs )
-{
- if( !mpCTLine)
- return;
-
- int nOrigWidth = GetTextWidth();
- int nPixelWidth = rArgs.mnLayoutWidth;
- if( nPixelWidth )
- {
- if( nPixelWidth <= 0)
- return;
- }
- else if( rArgs.mpDXArray )
- {
- // for now we are only interested in the layout width
- // TODO: use all mpDXArray elements for layouting
- nPixelWidth = rArgs.mpDXArray[ mnCharCount - 1 ];
- }
-
- float fTrailingSpace = CTLineGetTrailingWhitespaceWidth( mpCTLine );
- // in RTL-layouts trailing spaces are leftmost
- // TODO: use BiDi-algorithm to thoroughly check this assumption
- if( rArgs.mnFlags & SAL_LAYOUT_BIDI_RTL)
- mfBaseAdv = fTrailingSpace;
-
- // return early if there is nothing to do
- 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
- if( (nOrigWidth >= nPixelWidth-1) && (nOrigWidth <= nPixelWidth+1) )
- return;
-
- CTLineRef pNewCTLine = CTLineCreateJustifiedLine( mpCTLine, 1.0, nPixelWidth - fTrailingSpace );
- 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;
- }
- CFRelease( mpCTLine );
- mpCTLine = pNewCTLine;
- mfCachedWidth = nPixelWidth;
-}
-
-// 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(void) const
-{
- float fPosX, fPosY;
-
- if (mnLayoutFlags & SAL_LAYOUT_RIGHT_ALIGN)
- {
- // text is always drawn at its leftmost point
- const Point aPos = DrawBase();
- fPosX = aPos.X() + mfBaseAdv - GetWidth();
- fPosY = aPos.Y();
- }
- else
- {
- const Point aPos = GetDrawPosition(Point(mfBaseAdv, 0));
- fPosX = aPos.X();
- fPosY = aPos.Y();
- }
-
- CGPoint aTextPos = { +fPosX, -fPosY };
- return aTextPos;
-}
-
-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;
-
- // the view is vertically flipped => flipped glyphs
- // so apply a temporary transformation that it flips back
- // also compensate if the font was size limited
- CGContextSaveGState( rAquaGraphics.mrContext );
- CGContextScaleCTM( rAquaGraphics.mrContext, 1.0, -1.0 );
- CGContextSetShouldAntialias( rAquaGraphics.mrContext, !rAquaGraphics.mbNonAntialiasedText );
-
- // Draw the text
- 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 );
- CTLineDraw( mpCTLine, rAquaGraphics.mrContext );
-#ifndef IOS
- // request an update of the changed window area
- if( rAquaGraphics.IsWindowGraphics() )
- {
- const CGRect aInkRect = CTLineGetImageBounds( mpCTLine, rAquaGraphics.mrContext );
- const CGRect aRefreshRect = CGContextConvertRectToDeviceSpace( rAquaGraphics.mrContext, aInkRect );
- rAquaGraphics.RefreshRect( aRefreshRect );
- }
-#endif
- // restore the original graphic context transformations
- CGContextRestoreGState( rAquaGraphics.mrContext );
-}
-
-int CTLayout::GetNextGlyphs( int nLen, sal_GlyphId* pGlyphIDs, Point& rPos, int& nStart,
- sal_Int32* pGlyphAdvances, int* pCharIndexes,
- const PhysicalFontFace** pFallbackFonts ) const
-{
- if( !mpCTLine )
- return 0;
-
- if( nStart < 0 ) // first glyph requested?
- nStart = 0;
- nLen = 1; // TODO: handle nLen>1 below
-
- // prepare to iterate over the glyph runs
- int nCount = 0;
- int nSubIndex = nStart;
-
- typedef std::vector<CGGlyph> CGGlyphVector;
- typedef std::vector<CGPoint> CGPointVector;
- typedef std::vector<CGSize> CGSizeVector;
- typedef std::vector<CFIndex> CFIndexVector;
- CGGlyphVector aCGGlyphVec;
- CGPointVector aCGPointVec;
- CGSizeVector aCGSizeVec;
- CFIndexVector aCFIndexVec;
-
- // TODO: iterate over cached layout
- CFArrayRef aGlyphRuns = CTLineGetGlyphRuns( mpCTLine );
- const int nRunCount = CFArrayGetCount( aGlyphRuns );
- for( int nRunIndex = 0; nRunIndex < nRunCount; ++nRunIndex ) {
- CTRunRef pGlyphRun = (CTRunRef)CFArrayGetValueAtIndex( aGlyphRuns, nRunIndex );
- const CFIndex nGlyphsInRun = CTRunGetGlyphCount( pGlyphRun );
- // skip to the first glyph run of interest
- if( nSubIndex >= nGlyphsInRun ) {
- nSubIndex -= nGlyphsInRun;
- continue;
- }
- const CFRange aFullRange = CFRangeMake( 0, nGlyphsInRun );
-
- // get glyph run details
- const CGGlyph* pCGGlyphIdx = CTRunGetGlyphsPtr( pGlyphRun );
- if( !pCGGlyphIdx ) {
- aCGGlyphVec.reserve( nGlyphsInRun );
- CTRunGetGlyphs( pGlyphRun, aFullRange, &aCGGlyphVec[0] );
- pCGGlyphIdx = &aCGGlyphVec[0];
- }
- const CGPoint* pCGGlyphPos = CTRunGetPositionsPtr( pGlyphRun );
- if( !pCGGlyphPos ) {
- aCGPointVec.reserve( nGlyphsInRun );
- CTRunGetPositions( pGlyphRun, aFullRange, &aCGPointVec[0] );
- pCGGlyphPos = &aCGPointVec[0];
- }
-
- const CGSize* pCGGlyphAdvs = NULL;
- if( pGlyphAdvances) {
- pCGGlyphAdvs = CTRunGetAdvancesPtr( pGlyphRun );
- if( !pCGGlyphAdvs) {
- aCGSizeVec.reserve( nGlyphsInRun );
- CTRunGetAdvances( pGlyphRun, aFullRange, &aCGSizeVec[0] );
- pCGGlyphAdvs = &aCGSizeVec[0];
- }
- }
-
- const CFIndex* pCGGlyphStrIdx = NULL;
- if( pCharIndexes) {
- pCGGlyphStrIdx = CTRunGetStringIndicesPtr( pGlyphRun );
- if( !pCGGlyphStrIdx) {
- aCFIndexVec.reserve( nGlyphsInRun );
- CTRunGetStringIndices( pGlyphRun, aFullRange, &aCFIndexVec[0] );
- pCGGlyphStrIdx = &aCFIndexVec[0];
- }
- }
-
- const PhysicalFontFace* pFallbackFont = NULL;
- if( pFallbackFonts ) {
- CFDictionaryRef pRunAttributes = CTRunGetAttributes( pGlyphRun );
- CTFontRef pRunFont = (CTFontRef)CFDictionaryGetValue( pRunAttributes, kCTFontAttributeName );
-
- CFDictionaryRef pAttributes = mpTextStyle->GetStyleDict();
- CTFontRef pFont = (CTFontRef)CFDictionaryGetValue( pAttributes, kCTFontAttributeName );
- if ( !CFEqual( pRunFont, pFont ) ) {
- CTFontDescriptorRef pFontDesc = CTFontCopyFontDescriptor( pRunFont );
- ImplDevFontAttributes rDevFontAttr = DevFontFromCTFontDescriptor( pFontDesc, NULL );
- pFallbackFont = new CoreTextFontData( rDevFontAttr, (sal_IntPtr)pFontDesc );
- }
- }
-
- // get the details for each interesting glyph
- // TODO: handle nLen>1
- for(; (--nLen >= 0) && (nSubIndex < nGlyphsInRun); ++nSubIndex, ++nStart )
- {
- // convert glyph details for VCL
- *(pGlyphIDs++) = pCGGlyphIdx[ nSubIndex ];
- if( pGlyphAdvances )
- *(pGlyphAdvances++) = lrint(pCGGlyphAdvs[ nSubIndex ].width);
- if( pCharIndexes )
- *(pCharIndexes++) = pCGGlyphStrIdx[ nSubIndex] + mnMinCharPos;
- if( pFallbackFonts )
- *(pFallbackFonts++) = pFallbackFont;
- if( !nCount++ ) {
- const CGPoint& rCurPos = pCGGlyphPos[ nSubIndex ];
- rPos = GetDrawPosition( Point( rCurPos.x, rCurPos.y) );
- }
- }
- nSubIndex = 0; // prepare for the next glyph run
- break; // TODO: handle nLen>1
- }
-
- return nCount;
-}
-
-double CTLayout::GetWidth() const
-{
- if( (mnCharCount <= 0) || !mpCTLine )
- return 0;
-
- if( mfCachedWidth < 0.0 ) {
- mfCachedWidth = CTLineGetTypographicBounds( mpCTLine, NULL, NULL, NULL);
- }
-
- return mfCachedWidth;
-}
-
-long CTLayout::GetTextWidth() const
-{
- return lrint(GetWidth());
-}
-
-long CTLayout::FillDXArray( sal_Int32* pDXArray ) const
-{
- // short circuit requests which don't need full details
- if( !pDXArray )
- return GetTextWidth();
-
- long nPixWidth = GetTextWidth();
- if( pDXArray ) {
- // initialize the result array
- for( int i = 0; i < mnCharCount; ++i)
- pDXArray[i] = 0;
- // handle each glyph run
- CFArrayRef aGlyphRuns = CTLineGetGlyphRuns( mpCTLine );
- const int nRunCount = CFArrayGetCount( aGlyphRuns );
- typedef std::vector<CGSize> CGSizeVector;
- CGSizeVector aSizeVec;
- typedef std::vector<CFIndex> CFIndexVector;
- CFIndexVector aIndexVec;
- for( int nRunIndex = 0; nRunIndex < nRunCount; ++nRunIndex ) {
- CTRunRef pGlyphRun = (CTRunRef)CFArrayGetValueAtIndex( aGlyphRuns, nRunIndex );
- const CFIndex nGlyphCount = CTRunGetGlyphCount( pGlyphRun );
- const CFRange aFullRange = CFRangeMake( 0, nGlyphCount );
- aSizeVec.reserve( nGlyphCount );
- aIndexVec.reserve( nGlyphCount );
- CTRunGetAdvances( pGlyphRun, aFullRange, &aSizeVec[0] );
- CTRunGetStringIndices( pGlyphRun, aFullRange, &aIndexVec[0] );
- for( int i = 0; i != nGlyphCount; ++i ) {
- const int nRelIdx = aIndexVec[i];
- pDXArray[ nRelIdx ] += lrint(aSizeVec[i].width);
- }
- }
- }
-
- return nPixWidth;
-}
-
-sal_Int32 CTLayout::GetTextBreak( long nMaxWidth, long /*nCharExtra*/, int nFactor ) const
-{
- if( !mpCTLine )
- return -1;
-
- CTTypesetterRef aCTTypeSetter = CTTypesetterCreateWithAttributedString( mpAttrString );
- const double fCTMaxWidth = (double)nMaxWidth / nFactor;
- CFIndex nIndex = CTTypesetterSuggestClusterBreak( aCTTypeSetter, 0, fCTMaxWidth );
- if( nIndex >= mnCharCount )
- return -1;
-
- nIndex += mnMinCharPos;
- return nIndex;
-}
-
-void CTLayout::GetCaretPositions( int nMaxIndex, sal_Int32* pCaretXArray ) const
-{
- DBG_ASSERT( ((nMaxIndex>0)&&!(nMaxIndex&1)),
- "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
-bool CTLayout::GetGlyphOutlines( SalGraphics&, PolyPolyVector& ) const { return false; }
-void CTLayout::InitFont() const {}
-void CTLayout::MoveGlyph( int /*nStart*/, long /*nNewXPos*/ ) {}
-void CTLayout::DropGlyph( int /*nStart*/ ) {}
-void CTLayout::Simplify( bool /*bIsBase*/ ) {}
-
-SalLayout* CoreTextStyle::GetTextLayout( void ) const
-{
- return new CTLayout( this);
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/coretext/salgdi.cxx b/vcl/coretext/salgdi.cxx
deleted file mode 100644
index ee6c834aead9..000000000000
--- a/vcl/coretext/salgdi.cxx
+++ /dev/null
@@ -1,889 +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 <config_folders.h>
-
-#include "sal/config.h"
-
-#include "osl/file.hxx"
-#include "osl/process.h"
-
-#include "osl/mutex.hxx"
-
-#include "rtl/bootstrap.h"
-#include "rtl/strbuf.hxx"
-
-#include "basegfx/range/b2drectangle.hxx"
-#include "basegfx/polygon/b2dpolygon.hxx"
-#include "basegfx/polygon/b2dpolygontools.hxx"
-#include "basegfx/matrix/b2dhommatrix.hxx"
-#include "basegfx/matrix/b2dhommatrixtools.hxx"
-
-#include "vcl/sysdata.hxx"
-#include "vcl/svapp.hxx"
-
-#include "coretext/salgdi.h"
-
-#ifdef MACOSX
-#include "aqua/salframe.h"
-#endif
-
-#ifdef IOS
-#include "saldatabasic.hxx"
-#include <basebmp/scanlineformats.hxx>
-#endif
-
-#include "ctfonts.hxx"
-
-#include "fontsubset.hxx"
-#include "impfont.hxx"
-#include "sallayout.hxx"
-#include "sft.hxx"
-
-
-using namespace vcl;
-
-// =======================================================================
-
-CoreTextFontData::CoreTextFontData( const CoreTextFontData& rSrc )
-: PhysicalFontFace( rSrc )
-, mnFontId( rSrc.mnFontId )
-, mpCharMap( rSrc.mpCharMap )
-, mbOs2Read( rSrc.mbOs2Read )
-, mbHasOs2Table( rSrc.mbHasOs2Table )
-, mbCmapEncodingRead( rSrc.mbCmapEncodingRead )
-{
- if( mpCharMap )
- mpCharMap->AddReference();
-}
-
-// -----------------------------------------------------------------------
-
-CoreTextFontData::CoreTextFontData( const ImplDevFontAttributes& rDFA, sal_IntPtr nFontId )
-: PhysicalFontFace( rDFA, 0 )
-, mnFontId( nFontId )
-, mpCharMap( NULL )
-, mbOs2Read( false )
-, mbHasOs2Table( false )
-, mbCmapEncodingRead( false )
-, mbFontCapabilitiesRead( false )
-{
-}
-
-// -----------------------------------------------------------------------
-
-CoreTextFontData::~CoreTextFontData()
-{
- if( mpCharMap )
- mpCharMap->DeReference();
-}
-
-// -----------------------------------------------------------------------
-
-sal_IntPtr CoreTextFontData::GetFontId() const
-{
- return (sal_IntPtr)mnFontId;
-}
-
-// -----------------------------------------------------------------------
-
-static unsigned GetUShort( const unsigned char* p ){return((p[0]<<8)+p[1]);}
-
-const ImplFontCharMap* CoreTextFontData::GetImplFontCharMap() const
-{
- // return the cached charmap
- if( mpCharMap )
- return mpCharMap;
-
- // set the default charmap
- mpCharMap = ImplFontCharMap::GetDefaultMap();
- mpCharMap->AddReference();
-
- // get the CMAP byte size
- // allocate a buffer for the CMAP raw data
- const int nBufSize = GetFontTable( "cmap", NULL );
- DBG_ASSERT( (nBufSize > 0), "CoreTextFontData::GetImplFontCharMap : GetFontTable1 failed!\n");
- if( nBufSize <= 0 )
- return mpCharMap;
-
- // get the CMAP raw data
- ByteVector aBuffer( nBufSize );
- const int nRawLength = GetFontTable( "cmap", &aBuffer[0] );
- DBG_ASSERT( (nRawLength > 0), "CoreTextFontData::GetImplFontCharMap : GetFontTable2 failed!\n");
- if( nRawLength <= 0 )
- return mpCharMap;
- DBG_ASSERT( (nBufSize==nRawLength), "CoreTextFontData::GetImplFontCharMap : ByteCount mismatch!\n");
-
- // parse the CMAP
- CmapResult aCmapResult;
- if( ParseCMAP( &aBuffer[0], nRawLength, aCmapResult ) )
- {
- // create the matching charmap
- mpCharMap->DeReference();
- mpCharMap = new ImplFontCharMap( aCmapResult );
- mpCharMap->AddReference();
- }
-
- return mpCharMap;
-}
-
-bool CoreTextFontData::GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
-{
- // read this only once per font
- if( mbFontCapabilitiesRead )
- {
- rFontCapabilities = maFontCapabilities;
- return !rFontCapabilities.maUnicodeRange.empty() || !rFontCapabilities.maCodePageRange.empty();
- }
- mbFontCapabilitiesRead = true;
-
- int nBufSize = 0;
- // prepare to get the GSUB table raw data
- nBufSize = GetFontTable( "GSUB", NULL );
- if( nBufSize > 0 )
- {
- // allocate a buffer for the GSUB raw data
- ByteVector aBuffer( nBufSize );
- // get the GSUB raw data
- const int nRawLength = GetFontTable( "GSUB", &aBuffer[0] );
- if( nRawLength > 0 )
- {
- const unsigned char* pGSUBTable = &aBuffer[0];
- vcl::getTTScripts(maFontCapabilities.maGSUBScriptTags, pGSUBTable, nRawLength);
- }
- }
- nBufSize = GetFontTable( "OS/2", NULL );
- if( nBufSize > 0 )
- {
- // allocate a buffer for the OS/2 raw data
- ByteVector aBuffer( nBufSize );
- // get the OS/2 raw data
- const int nRawLength = GetFontTable( "OS/2", &aBuffer[0] );
- if( nRawLength > 0 )
- {
- const unsigned char* pOS2Table = &aBuffer[0];
- vcl::getTTCoverage(
- maFontCapabilities.maUnicodeRange,
- maFontCapabilities.maCodePageRange,
- pOS2Table, nRawLength);
- }
- }
- rFontCapabilities = maFontCapabilities;
- return !rFontCapabilities.maUnicodeRange.empty() || !rFontCapabilities.maCodePageRange.empty();
-}
-
-// -----------------------------------------------------------------------
-
-void CoreTextFontData::ReadOs2Table( void ) const
-{
- // read this only once per font
- if( mbOs2Read )
- return;
- mbOs2Read = true;
- mbHasOs2Table = false;
-
- // prepare to get the OS/2 table raw data
- const int nBufSize = GetFontTable( "OS/2", NULL );
- DBG_ASSERT( (nBufSize > 0), "CoreTextFontData::ReadOs2Table : GetFontTable1 failed!\n");
- if( nBufSize <= 0 )
- return;
-
- // get the OS/2 raw data
- ByteVector aBuffer( nBufSize );
- const int nRawLength = GetFontTable( "cmap", &aBuffer[0] );
- DBG_ASSERT( (nRawLength > 0), "CoreTextFontData::ReadOs2Table : GetFontTable2 failed!\n");
- if( nRawLength <= 0 )
- return;
- DBG_ASSERT( (nBufSize==nRawLength), "CoreTextFontData::ReadOs2Table : ByteCount mismatch!\n");
- mbHasOs2Table = true;
-
- // parse the OS/2 raw data
- // TODO: also analyze panose info, etc.
-}
-
-void CoreTextFontData::ReadMacCmapEncoding( void ) const
-{
- // read this only once per font
- if( mbCmapEncodingRead )
- return;
- mbCmapEncodingRead = true;
-
- const int nBufSize = GetFontTable( "cmap", NULL );
- if( nBufSize <= 0 )
- return;
-
- // get the CMAP raw data
- ByteVector aBuffer( nBufSize );
- const int nRawLength = GetFontTable( "cmap", &aBuffer[0] );
- if( nRawLength < 24 )
- return;
- DBG_ASSERT( (nBufSize==nRawLength), "CoreTextFontData::ReadMacCmapEncoding : ByteCount mismatch!\n");
-
- const unsigned char* pCmap = &aBuffer[0];
- if( GetUShort( pCmap ) != 0x0000 )
- return;
-}
-
-// -----------------------------------------------------------------------
-
-AquaSalGraphics::AquaSalGraphics()
-#ifdef MACOSX
- : mpFrame( NULL )
- , mxLayer( NULL )
- , mrContext( NULL )
- , mpXorEmulation( NULL )
- , mnXorMode( 0 )
- , mnWidth( 0 )
- , mnHeight( 0 )
- , mnBitmapDepth( 0 )
- , mnRealDPIX( 0 )
- , mnRealDPIY( 0 )
- , mfFakeDPIScale( 1.0 )
- , mxClipPath( NULL )
- , maLineColor( COL_WHITE )
- , maFillColor( COL_BLACK )
- , mpFontData( NULL )
- , mpTextStyle( NULL )
- , maTextColor( COL_BLACK )
- , mbNonAntialiasedText( false )
- , mbPrinter( false )
- , mbVirDev( false )
- , mbWindow( false )
-#else
- : mrContext( NULL )
- , mfFakeDPIScale( 1.0 )
- , mpFontData( NULL )
- , mpTextStyle( NULL )
- , maTextColor( COL_BLACK )
- , mbNonAntialiasedText( false )
-#endif
-{}
-
-// -----------------------------------------------------------------------
-
-AquaSalGraphics::~AquaSalGraphics()
-{
-#ifdef MACOSX
- CGPathRelease( mxClipPath );
- delete mpTextStyle;
-
- if( mpXorEmulation )
- delete mpXorEmulation;
-
- if( mxLayer )
- CGLayerRelease( mxLayer );
- else if( mrContext && mbWindow )
- {
- // destroy backbuffer bitmap context that we created ourself
- CGContextRelease( mrContext );
- mrContext = NULL;
- }
-#endif
-}
-
-// =======================================================================
-
-void AquaSalGraphics::SetTextColor( SalColor nSalColor )
-{
- maTextColor = RGBAColor( nSalColor );
- if( mpTextStyle)
- mpTextStyle->SetTextColor( maTextColor );
-}
-
-// -----------------------------------------------------------------------
-
-void AquaSalGraphics::GetFontMetric( ImplFontMetricData* pMetric, int /*nFallbackLevel*/ )
-{
- mpTextStyle->GetFontMetric( mfFakeDPIScale, *pMetric );
-}
-
-// -----------------------------------------------------------------------
-
-static bool AddTempDevFont(const OUString& rFontFileURL)
-{
- OUString aUSytemPath;
- OSL_VERIFY( !osl::FileBase::getSystemPathFromFileURL( rFontFileURL, aUSytemPath ) );
- OString aCFileName = OUStringToOString( aUSytemPath, RTL_TEXTENCODING_UTF8 );
-
- CFStringRef rFontPath = CFStringCreateWithCString(NULL, aCFileName.getStr(), kCFStringEncodingUTF8);
- CFURLRef rFontURL = CFURLCreateWithFileSystemPath(NULL, rFontPath, kCFURLPOSIXPathStyle, true);
-
- CFErrorRef error;
- bool success = CTFontManagerRegisterFontsForURL(rFontURL, kCTFontManagerScopeProcess, &error);
-
- if (!success)
- {
- CFRelease(error);
- return false;
- }
-
- return true;
-}
-
-static void AddTempFontDir( const OUString &rFontDirUrl )
-{
- osl::Directory aFontDir( rFontDirUrl );
- osl::FileBase::RC rcOSL = aFontDir.open();
- if( rcOSL == osl::FileBase::E_None )
- {
- osl::DirectoryItem aDirItem;
-
- while( aFontDir.getNextItem( aDirItem, 10 ) == osl::FileBase::E_None )
- {
- osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileURL );
- rcOSL = aDirItem.getFileStatus( aFileStatus );
- if ( rcOSL == osl::FileBase::E_None )
- AddTempDevFont(aFileStatus.getFileURL());
- }
- }
-}
-
-static void AddLocalTempFontDirs()
-{
- static bool bFirst = true;
- if( !bFirst )
- return;
- bFirst = false;
-
- // add private font files
-
- OUString aBrandStr( "$BRAND_BASE_DIR" );
- rtl_bootstrap_expandMacros( &aBrandStr.pData );
- AddTempFontDir( aBrandStr + "/" LIBO_SHARE_FOLDER "/fonts/truetype/" );
-}
-
-void AquaSalGraphics::GetDevFontList( ImplDevFontList* pFontList )
-{
- DBG_ASSERT( pFontList, "AquaSalGraphics::GetDevFontList(NULL) !");
-
- AddLocalTempFontDirs();
-
- // The idea is to cache the list of system fonts once it has been generated.
- // SalData seems to be a good place for this caching. However we have to
- // carefully make the access to the font list thread-safe. If we register
- // a font-change event handler to update the font list in case fonts have
- // changed on the system we have to lock access to the list. The right
- // way to do that is the solar mutex since GetDevFontList is protected
- // through it as should be all event handlers
-
- SalData* pSalData = GetSalData();
- if( !pSalData->mpFontList )
- pSalData->mpFontList = GetCoretextFontList();
-
- // Copy all PhysicalFontFace objects contained in the SystemFontList
- pSalData->mpFontList->AnnounceFonts( *pFontList );
-}
-
-void AquaSalGraphics::ClearDevFontCache()
-{
- SalData* pSalData = GetSalData();
- delete pSalData->mpFontList;
- pSalData->mpFontList = NULL;
-}
-
-// -----------------------------------------------------------------------
-
-bool AquaSalGraphics::AddTempDevFont( ImplDevFontList*,
- const OUString& rFontFileURL, const OUString& /*rFontName*/ )
-{
- return ::AddTempDevFont(rFontFileURL);
-}
-
-// -----------------------------------------------------------------------
-
-sal_Bool AquaSalGraphics::GetGlyphOutline( sal_GlyphId nGlyphId, basegfx::B2DPolyPolygon& rPolyPoly )
-{
- const bool bRC = mpTextStyle->GetGlyphOutline( nGlyphId, rPolyPoly );
- return bRC;
-}
-
-// -----------------------------------------------------------------------
-
-sal_Bool AquaSalGraphics::GetGlyphBoundRect( sal_GlyphId nGlyphId, Rectangle& rRect )
-{
- const bool bRC = mpTextStyle->GetGlyphBoundRect( nGlyphId, rRect );
- return bRC;
-}
-
-// -----------------------------------------------------------------------
-
-void AquaSalGraphics::DrawServerFontLayout( const ServerFontLayout& )
-{
-}
-
-// -----------------------------------------------------------------------
-
-sal_uInt16 AquaSalGraphics::SetFont( FontSelectPattern* pReqFont, int /*nFallbackLevel*/ )
-{
- // release the text style
- delete mpTextStyle;
- mpTextStyle = NULL;
-
- // handle NULL request meaning: release-font-resources request
- if( !pReqFont )
- {
- mpFontData = NULL;
- return 0;
- }
-
- // update the text style
- mpFontData = static_cast<const CoreTextFontData*>( pReqFont->mpFontData );
- mpTextStyle = mpFontData->CreateTextStyle( *pReqFont );
- mpTextStyle->SetTextColor( maTextColor );
-
- SAL_INFO("vcl.coretext",
- "SetFont"
- << " to " << mpFontData->GetFamilyName()
- << ", " << mpFontData->GetStyleName()
- << " fontid=" << mpFontData->GetFontId()
- << " for " << pReqFont->GetFamilyName()
- << ", " << pReqFont->GetStyleName()
- << " weight=" << pReqFont->GetWeight()
- << " slant=" << pReqFont->GetSlant()
- << " size=" << pReqFont->mnHeight << "x" << pReqFont->mnWidth
- << " orientation=" << pReqFont->mnOrientation
- );
-
- return 0;
-}
-
-// -----------------------------------------------------------------------
-
-SalLayout* AquaSalGraphics::GetTextLayout( ImplLayoutArgs& /*rArgs*/, int /*nFallbackLevel*/ )
-{
- SalLayout* pSalLayout = mpTextStyle->GetTextLayout();
- return pSalLayout;
-}
-
-// -----------------------------------------------------------------------
-
-const ImplFontCharMap* AquaSalGraphics::GetImplFontCharMap() const
-{
- if( !mpFontData )
- return ImplFontCharMap::GetDefaultMap();
-
- return mpFontData->GetImplFontCharMap();
-}
-
-bool AquaSalGraphics::GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
-{
- if( !mpFontData )
- return false;
-
- return mpFontData->GetImplFontCapabilities(rFontCapabilities);
-}
-
-// -----------------------------------------------------------------------
-
-// fake a SFNT font directory entry for a font table
-// see http://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html#Directory
-static void FakeDirEntry( const char aTag[5], ByteCount nOfs, ByteCount nLen,
- const unsigned char* /*pData*/, unsigned char*& rpDest )
-{
- // write entry tag
- rpDest[ 0] = aTag[0];
- rpDest[ 1] = aTag[1];
- rpDest[ 2] = aTag[2];
- rpDest[ 3] = aTag[3];
- // TODO: get entry checksum and write it
- // not too important since the subsetter doesn't care currently
- // for( pData+nOfs ... pData+nOfs+nLen )
- // write entry offset
- rpDest[ 8] = (char)(nOfs >> 24);
- rpDest[ 9] = (char)(nOfs >> 16);
- rpDest[10] = (char)(nOfs >> 8);
- rpDest[11] = (char)(nOfs >> 0);
- // write entry length
- rpDest[12] = (char)(nLen >> 24);
- rpDest[13] = (char)(nLen >> 16);
- rpDest[14] = (char)(nLen >> 8);
- rpDest[15] = (char)(nLen >> 0);
- // advance to next entry
- rpDest += 16;
-}
-
-// fake a TTF or CFF font as directly accessing font file is not possible
-// when only the fontid is known. This approach also handles *.dfont fonts.
-bool AquaSalGraphics::GetRawFontData( const PhysicalFontFace* pFontData,
- ByteVector& rBuffer, bool* pJustCFF )
-{
- const CoreTextFontData* pMacFont = static_cast<const CoreTextFontData*>(pFontData);
-
- // short circuit for CFF-only fonts
- const int nCffSize = pMacFont->GetFontTable( "CFF ", NULL);
- if( pJustCFF != NULL )
- {
- *pJustCFF = (nCffSize > 0);
- if( *pJustCFF)
- {
- rBuffer.resize( nCffSize);
- const int nCffRead = pMacFont->GetFontTable( "CFF ", &rBuffer[0]);
- if( nCffRead != nCffSize)
- return false;
- return true;
- }
- }
-
- // get font table availability and size in bytes
- const int nHeadSize = pMacFont->GetFontTable( "head", NULL);
- if( nHeadSize <= 0)
- return false;
- const int nMaxpSize = pMacFont->GetFontTable( "maxp", NULL);
- if( nMaxpSize <= 0)
- return false;
- const int nCmapSize = pMacFont->GetFontTable( "cmap", NULL);
- if( nCmapSize <= 0)
- return false;
- const int nNameSize = pMacFont->GetFontTable( "name", NULL);
- if( nNameSize <= 0)
- return false;
- const int nHheaSize = pMacFont->GetFontTable( "hhea", NULL);
- if( nHheaSize <= 0)
- return false;
- const int nHmtxSize = pMacFont->GetFontTable( "hmtx", NULL);
- if( nHmtxSize <= 0)
- return false;
-
- // get the ttf-glyf outline tables
- int nLocaSize = 0;
- int nGlyfSize = 0;
- if( nCffSize <= 0)
- {
- nLocaSize = pMacFont->GetFontTable( "loca", NULL);
- if( nLocaSize <= 0)
- return false;
- nGlyfSize = pMacFont->GetFontTable( "glyf", NULL);
- if( nGlyfSize <= 0)
- return false;
- }
-
- int nPrepSize = 0, nCvtSize = 0, nFpgmSize = 0;
- if( nGlyfSize) // TODO: reduce PDF size by making hint subsetting optional
- {
- nPrepSize = pMacFont->GetFontTable( "prep", NULL);
- nCvtSize = pMacFont->GetFontTable( "cvt ", NULL);
- nFpgmSize = pMacFont->GetFontTable( "fpgm", NULL);
- }
-
- // prepare a byte buffer for a fake font
- int nTableCount = 7;
- nTableCount += (nPrepSize>0) + (nCvtSize>0) + (nFpgmSize>0) + (nGlyfSize>0);
- const ByteCount nFdirSize = 12 + 16*nTableCount;
- ByteCount nTotalSize = nFdirSize;
- nTotalSize += nHeadSize + nMaxpSize + nNameSize + nCmapSize;
- if( nGlyfSize )
- nTotalSize += nLocaSize + nGlyfSize;
- else
- nTotalSize += nCffSize;
- nTotalSize += nHheaSize + nHmtxSize;
- nTotalSize += nPrepSize + nCvtSize + nFpgmSize;
- rBuffer.resize( nTotalSize );
-
- // fake a SFNT font directory header
- if( nTableCount < 16 )
- {
- int nLog2 = 0;
- while( (nTableCount >> nLog2) > 1 ) ++nLog2;
- rBuffer[ 1] = 1; // Win-TTF style scaler
- rBuffer[ 5] = nTableCount; // table count
- rBuffer[ 7] = nLog2*16; // searchRange
- rBuffer[ 9] = nLog2; // entrySelector
- rBuffer[11] = (nTableCount-nLog2)*16; // rangeShift
- }
-
- // get font table raw data and update the fake directory entries
- ByteCount nOfs = nFdirSize;
- unsigned char* pFakeEntry = &rBuffer[12];
- if( nCmapSize != pMacFont->GetFontTable( "cmap", &rBuffer[nOfs]))
- return false;
- FakeDirEntry( "cmap", nOfs, nCmapSize, &rBuffer[0], pFakeEntry );
- nOfs += nCmapSize;
- if( nCvtSize ) {
- if( nCvtSize != pMacFont->GetFontTable( "cvt ", &rBuffer[nOfs]))
- return false;
- FakeDirEntry( "cvt ", nOfs, nCvtSize, &rBuffer[0], pFakeEntry );
- nOfs += nCvtSize;
- }
- if( nFpgmSize ) {
- if( nFpgmSize != pMacFont->GetFontTable( "fpgm", &rBuffer[nOfs]))
- return false;
- FakeDirEntry( "fpgm", nOfs, nFpgmSize, &rBuffer[0], pFakeEntry );
- nOfs += nFpgmSize;
- }
- if( nCffSize ) {
- if( nCffSize != pMacFont->GetFontTable( "CFF ", &rBuffer[nOfs]))
- return false;
- FakeDirEntry( "CFF ", nOfs, nCffSize, &rBuffer[0], pFakeEntry );
- nOfs += nGlyfSize;
- } else {
- if( nGlyfSize != pMacFont->GetFontTable( "glyf", &rBuffer[nOfs]))
- return false;
- FakeDirEntry( "glyf", nOfs, nGlyfSize, &rBuffer[0], pFakeEntry );
- nOfs += nGlyfSize;
- if( nLocaSize != pMacFont->GetFontTable( "loca", &rBuffer[nOfs]))
- return false;
- FakeDirEntry( "loca", nOfs, nLocaSize, &rBuffer[0], pFakeEntry );
- nOfs += nLocaSize;
- }
- if( nHeadSize != pMacFont->GetFontTable( "head", &rBuffer[nOfs]))
- return false;
- FakeDirEntry( "head", nOfs, nHeadSize, &rBuffer[0], pFakeEntry );
- nOfs += nHeadSize;
- if( nHheaSize != pMacFont->GetFontTable( "hhea", &rBuffer[nOfs]))
- return false;
- FakeDirEntry( "hhea", nOfs, nHheaSize, &rBuffer[0], pFakeEntry );
- nOfs += nHheaSize;
- if( nHmtxSize != pMacFont->GetFontTable( "hmtx", &rBuffer[nOfs]))
- return false;
- FakeDirEntry( "hmtx", nOfs, nHmtxSize, &rBuffer[0], pFakeEntry );
- nOfs += nHmtxSize;
- if( nMaxpSize != pMacFont->GetFontTable( "maxp", &rBuffer[nOfs]))
- return false;
- FakeDirEntry( "maxp", nOfs, nMaxpSize, &rBuffer[0], pFakeEntry );
- nOfs += nMaxpSize;
- if( nNameSize != pMacFont->GetFontTable( "name", &rBuffer[nOfs]))
- return false;
- FakeDirEntry( "name", nOfs, nNameSize, &rBuffer[0], pFakeEntry );
- nOfs += nNameSize;
- if( nPrepSize ) {
- if( nPrepSize != pMacFont->GetFontTable( "prep", &rBuffer[nOfs]))
- return false;
- FakeDirEntry( "prep", nOfs, nPrepSize, &rBuffer[0], pFakeEntry );
- nOfs += nPrepSize;
- }
-
- DBG_ASSERT( (nOfs==nTotalSize), "AquaSalGraphics::CreateFontSubset (nOfs!=nTotalSize)");
-
- return true;
-}
-
-// -----------------------------------------------------------------------
-
-void AquaSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFontData, bool bVertical,
- Int32Vector& rGlyphWidths, Ucs2UIntMap& rUnicodeEnc )
-{
- rGlyphWidths.clear();
- rUnicodeEnc.clear();
-
- if( pFontData->IsSubsettable() )
- {
- ByteVector aBuffer;
- if( !GetRawFontData( pFontData, aBuffer, NULL ) )
- return;
-
- // TODO: modernize psprint's horrible fontsubset C-API
- // this probably only makes sense after the switch to another SCM
- // that can preserve change history after file renames
-
- // use the font subsetter to get the widths
- TrueTypeFont* pSftFont = NULL;
- int nRC = ::OpenTTFontBuffer( (void*)&aBuffer[0], aBuffer.size(), 0, &pSftFont);
- if( nRC != SF_OK )
- return;
-
- const int nGlyphCount = ::GetTTGlyphCount( pSftFont );
- if( nGlyphCount > 0 )
- {
- // get glyph metrics
- rGlyphWidths.resize(nGlyphCount);
- std::vector<sal_uInt16> aGlyphIds(nGlyphCount);
- for( int i = 0; i < nGlyphCount; i++ )
- aGlyphIds[i] = static_cast<sal_uInt16>(i);
- const TTSimpleGlyphMetrics* pGlyphMetrics = ::GetTTSimpleGlyphMetrics(
- pSftFont, &aGlyphIds[0], nGlyphCount, bVertical );
- if( pGlyphMetrics )
- {
- for( int i = 0; i < nGlyphCount; ++i )
- rGlyphWidths[i] = pGlyphMetrics[i].adv;
- free( (void*)pGlyphMetrics );
- }
-
- const ImplFontCharMap* pMap = mpFontData->GetImplFontCharMap();
- DBG_ASSERT( pMap && pMap->GetCharCount(), "no charmap" );
- pMap->AddReference(); // TODO: add and use RAII object instead
-
- // get unicode<->glyph encoding
- // TODO? avoid sft mapping by using the pMap itself
- int nCharCount = pMap->GetCharCount();
- sal_uInt32 nChar = pMap->GetFirstChar();
- for(; --nCharCount >= 0; nChar = pMap->GetNextChar( nChar ) )
- {
- if( nChar > 0xFFFF ) // TODO: allow UTF-32 chars
- break;
- sal_Ucs nUcsChar = static_cast<sal_Ucs>(nChar);
- sal_uInt32 nGlyph = ::MapChar( pSftFont, nUcsChar, bVertical );
- if( nGlyph > 0 )
- rUnicodeEnc[ nUcsChar ] = nGlyph;
- }
-
- pMap->DeReference(); // TODO: add and use RAII object instead
- }
-
- ::CloseTTFont( pSftFont );
- }
- else if( pFontData->IsEmbeddable() )
- {
- // get individual character widths
- OSL_FAIL("not implemented for non-subsettable fonts!\n");
- }
-}
-
-// -----------------------------------------------------------------------
-
-const Ucs2SIntMap* AquaSalGraphics::GetFontEncodingVector(
- const PhysicalFontFace*, const Ucs2OStrMap** /*ppNonEncoded*/ )
-{
- return NULL;
-}
-
-// -----------------------------------------------------------------------
-
-const void* AquaSalGraphics::GetEmbedFontData( const PhysicalFontFace*,
- const sal_Ucs* /*pUnicodes*/,
- sal_Int32* /*pWidths*/,
- FontSubsetInfo&,
- long* /*pDataLen*/ )
-{
- return NULL;
-}
-
-// -----------------------------------------------------------------------
-
-void AquaSalGraphics::FreeEmbedFontData( const void* pData, long /*nDataLen*/ )
-{
- // TODO: implementing this only makes sense when the implementation of
- // AquaSalGraphics::GetEmbedFontData() returns non-NULL
- (void)pData;
- DBG_ASSERT( (pData!=NULL), "AquaSalGraphics::FreeEmbedFontData() is not implemented\n");
-}
-
-// -----------------------------------------------------------------------
-
-SystemFontData AquaSalGraphics::GetSysFontData( int /* nFallbacklevel */ ) const
-{
- SystemFontData aSysFontData;
- aSysFontData.nSize = sizeof( SystemFontData );
-
- aSysFontData.bAntialias = !mbNonAntialiasedText;
-
- return aSysFontData;
-}
-
-#ifdef IOS
-
-// Note that "SvpSalGraphics" is actually called AquaSalGraphics for iOS
-
-bool SvpSalGraphics::CheckContext()
-{
- const basegfx::B2IVector size = m_aDevice->getSize();
- const basegfx::B2IVector bufferSize = m_aDevice->getBufferSize();
- const sal_Int32 scanlineStride = m_aDevice->getScanlineStride();
- basebmp::RawMemorySharedArray pixelBuffer = m_aDevice->getBuffer();
- bool warned = false;
-
- SAL_INFO( "vcl.ios",
- "CheckContext: device=" << m_aDevice.get() <<
- " size=" << size.getX() << "x" << size.getY() <<
- (m_aDevice->isTopDown() ? " top-down" : " bottom-up") <<
- " stride=" << scanlineStride <<
- " bufferSize=(" << bufferSize.getX() << "," << bufferSize.getY() << ")" );
-
- switch( m_aDevice->getScanlineFormat() ) {
- case basebmp::FORMAT_EIGHT_BIT_PAL:
- mrContext = CGBitmapContextCreate(pixelBuffer.get(),
- bufferSize.getX(), bufferSize.getY(),
- 8, scanlineStride,
- CGColorSpaceCreateDeviceGray(),
- kCGImageAlphaNone);
- break;
- case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_RGBA:
- mrContext = CGBitmapContextCreate(pixelBuffer.get(),
- bufferSize.getX(), bufferSize.getY(),
- 8, scanlineStride,
- CGColorSpaceCreateDeviceRGB(),
- kCGImageAlphaNoneSkipLast);
- break;
- case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_BGRA:
- mrContext = CGBitmapContextCreate(pixelBuffer.get(),
- bufferSize.getX(), bufferSize.getY(),
- 8, scanlineStride,
- CGColorSpaceCreateDeviceRGB(),
- kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little);
- break;
- default:
- SAL_WARN( "vcl.ios", "CheckContext: unsupported color format " << basebmp::formatName( m_aDevice->getScanlineFormat() ) );
- warned = true;
- }
-
- SAL_WARN_IF( mrContext == NULL && !warned, "vcl.ios", "CheckContext: CGBitmapContextCreate() failed" );
-
- // Should we also clip the context? (Then we need to add a
- // getBounds() function to BitmapDevice.)
-
- if( mrContext != NULL && m_aDevice->isTopDown() )
- {
- CGContextTranslateCTM( mrContext, 0, bufferSize.getY() );
- CGContextScaleCTM( mrContext, 1, -1 );
- }
-
-
- if (mrContext)
- {
- RectangleVector aRectangles;
- m_aClipRegion.GetRegionRectangles(aRectangles);
-
- CGContextBeginPath( mrContext );
-
- for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
- {
- const long nW(aRectIter->Right() - aRectIter->Left() + 1); // uses +1 logic in original
-
- if(nW)
- {
- const long nH(aRectIter->Bottom() - aRectIter->Top() + 1); // uses +1 logic in original
-
- if(nH)
- {
- CGRect aRect = {{ (CGFloat) aRectIter->Left(), (CGFloat) aRectIter->Top() }, { (CGFloat) nW, (CGFloat) nH }};
- CGContextAddRect( mrContext, aRect );
- }
- }
- }
-
- if (!CGContextIsPathEmpty(mrContext))
- CGContextClip(mrContext);
- }
-
-
- SAL_INFO( "vcl.ios", "CheckContext: context=" << mrContext );
-
- return ( mrContext != NULL );
-}
-
-CGContextRef SvpSalGraphics::GetContext()
-{
- if ( !mrContext )
- CheckContext();
-
- return mrContext;
-}
-
-#endif
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */