xref: /aoo41x/main/vcl/aqua/source/gdi/ctfonts.cxx (revision 2822fc04)
1*2822fc04SHerbert Dürr /**************************************************************
2*2822fc04SHerbert Dürr  *
3*2822fc04SHerbert Dürr  * Licensed to the Apache Software Foundation (ASF) under one
4*2822fc04SHerbert Dürr  * or more contributor license agreements.  See the NOTICE file
5*2822fc04SHerbert Dürr  * distributed with this work for additional information
6*2822fc04SHerbert Dürr  * regarding copyright ownership.  The ASF licenses this file
7*2822fc04SHerbert Dürr  * to you under the Apache License, Version 2.0 (the
8*2822fc04SHerbert Dürr  * "License"); you may not use this file except in compliance
9*2822fc04SHerbert Dürr  * with the License.  You may obtain a copy of the License at
10*2822fc04SHerbert Dürr  *
11*2822fc04SHerbert Dürr  *   http://www.apache.org/licenses/LICENSE-2.0
12*2822fc04SHerbert Dürr  *
13*2822fc04SHerbert Dürr  * Unless required by applicable law or agreed to in writing,
14*2822fc04SHerbert Dürr  * software distributed under the License is distributed on an
15*2822fc04SHerbert Dürr  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*2822fc04SHerbert Dürr  * KIND, either express or implied.  See the License for the
17*2822fc04SHerbert Dürr  * specific language governing permissions and limitations
18*2822fc04SHerbert Dürr  * under the License.
19*2822fc04SHerbert Dürr  *
20*2822fc04SHerbert Dürr  *************************************************************/
21*2822fc04SHerbert Dürr 
22*2822fc04SHerbert Dürr // MARKER(update_precomp.py): autogen include statement, do not remove
23*2822fc04SHerbert Dürr #include "precompiled_vcl.hxx"
24*2822fc04SHerbert Dürr 
25*2822fc04SHerbert Dürr #include "impfont.hxx"
26*2822fc04SHerbert Dürr #include "outfont.hxx"
27*2822fc04SHerbert Dürr #include "sallayout.hxx"
28*2822fc04SHerbert Dürr 
29*2822fc04SHerbert Dürr #include "aqua/salinst.h"
30*2822fc04SHerbert Dürr #include "aqua/saldata.hxx"
31*2822fc04SHerbert Dürr #include "aqua/salgdi.h"
32*2822fc04SHerbert Dürr #include "ctfonts.hxx"
33*2822fc04SHerbert Dürr 
34*2822fc04SHerbert Dürr #include "basegfx/polygon/b2dpolygon.hxx"
35*2822fc04SHerbert Dürr #include "basegfx/matrix/b2dhommatrix.hxx"
36*2822fc04SHerbert Dürr 
37*2822fc04SHerbert Dürr #ifndef DISABLE_CORETEXT_DYNLOAD
38*2822fc04SHerbert Dürr #include <dlfcn.h>
39*2822fc04SHerbert Dürr #endif
40*2822fc04SHerbert Dürr 
41*2822fc04SHerbert Dürr // =======================================================================
42*2822fc04SHerbert Dürr 
43*2822fc04SHerbert Dürr // CoreText specific physically available font face
44*2822fc04SHerbert Dürr class CTFontData
45*2822fc04SHerbert Dürr :	public ImplMacFontData
46*2822fc04SHerbert Dürr {
47*2822fc04SHerbert Dürr public:
48*2822fc04SHerbert Dürr 	explicit				CTFontData( const ImplDevFontAttributes&, sal_IntPtr nFontId );
49*2822fc04SHerbert Dürr 	virtual					~CTFontData( void );
50*2822fc04SHerbert Dürr 	virtual ImplFontData*   Clone( void ) const;
51*2822fc04SHerbert Dürr 
52*2822fc04SHerbert Dürr 	virtual ImplMacTextStyle*	CreateMacTextStyle( const ImplFontSelectData& ) const;
53*2822fc04SHerbert Dürr 	virtual ImplFontEntry*		CreateFontInstance( /*const*/ ImplFontSelectData& ) const;
54*2822fc04SHerbert Dürr 	virtual int					GetFontTable( const char pTagName[5], unsigned char* ) const;
55*2822fc04SHerbert Dürr };
56*2822fc04SHerbert Dürr 
57*2822fc04SHerbert Dürr // =======================================================================
58*2822fc04SHerbert Dürr 
59*2822fc04SHerbert Dürr class CTFontList
60*2822fc04SHerbert Dürr :	public SystemFontList
61*2822fc04SHerbert Dürr {
62*2822fc04SHerbert Dürr public:
63*2822fc04SHerbert Dürr 	explicit	CTFontList( void );
64*2822fc04SHerbert Dürr 	virtual		~CTFontList( void );
65*2822fc04SHerbert Dürr 
66*2822fc04SHerbert Dürr 	bool		Init( void );
67*2822fc04SHerbert Dürr 	void		AddFont( CTFontData* );
68*2822fc04SHerbert Dürr 
69*2822fc04SHerbert Dürr 	virtual void    AnnounceFonts( ImplDevFontList& ) const;
70*2822fc04SHerbert Dürr 	virtual ImplMacFontData* GetFontDataFromId( sal_IntPtr ) const;
71*2822fc04SHerbert Dürr 
72*2822fc04SHerbert Dürr private:
73*2822fc04SHerbert Dürr 	CTFontCollectionRef mpCTFontCollection;
74*2822fc04SHerbert Dürr 	CFArrayRef mpCTFontArray;
75*2822fc04SHerbert Dürr 
76*2822fc04SHerbert Dürr 	typedef std::hash_map<sal_IntPtr,CTFontData*> CTFontContainer;
77*2822fc04SHerbert Dürr 	CTFontContainer	maFontContainer;
78*2822fc04SHerbert Dürr };
79*2822fc04SHerbert Dürr 
80*2822fc04SHerbert Dürr // =======================================================================
81*2822fc04SHerbert Dürr 
82*2822fc04SHerbert Dürr CTTextStyle::CTTextStyle( const ImplFontSelectData& rFSD )
83*2822fc04SHerbert Dürr :	ImplMacTextStyle( rFSD )
84*2822fc04SHerbert Dürr ,	mpStyleDict( NULL )
85*2822fc04SHerbert Dürr {
86*2822fc04SHerbert Dürr 	mpFontData = (CTFontData*)rFSD.mpFontData;
87*2822fc04SHerbert Dürr 	const ImplFontSelectData* const pReqFont = &rFSD;
88*2822fc04SHerbert Dürr 
89*2822fc04SHerbert Dürr 	double fScaledFontHeight = pReqFont->mfExactHeight;
90*2822fc04SHerbert Dürr #if 0 // TODO: does CoreText need font size limiting???
91*2822fc04SHerbert Dürr 	static const float fMaxFontHeight = 144.0; // TODO: is there a limit for CoreText?
92*2822fc04SHerbert Dürr 	if( fScaledFontHeight > fMaxFontHeight )
93*2822fc04SHerbert Dürr 	{
94*2822fc04SHerbert Dürr 		mfFontScale = fScaledFontHeight / fMaxFontHeight;
95*2822fc04SHerbert Dürr 		fScaledFontHeight = fMaxFontHeight;
96*2822fc04SHerbert Dürr 	}
97*2822fc04SHerbert Dürr #endif
98*2822fc04SHerbert Dürr 
99*2822fc04SHerbert Dürr 	// convert font rotation to radian
100*2822fc04SHerbert Dürr 	mfFontRotation = pReqFont->mnOrientation * (M_PI / 1800.0);
101*2822fc04SHerbert Dürr 
102*2822fc04SHerbert Dürr 	// handle font stretching if any
103*2822fc04SHerbert Dürr 	const CGAffineTransform* pMatrix = NULL;
104*2822fc04SHerbert Dürr 	CGAffineTransform aMatrix;
105*2822fc04SHerbert Dürr 	if( (pReqFont->mnWidth != 0) && (pReqFont->mnWidth != pReqFont->mnHeight) )
106*2822fc04SHerbert Dürr 	{
107*2822fc04SHerbert Dürr 		mfFontStretch = (float)pReqFont->mnWidth / pReqFont->mnHeight;
108*2822fc04SHerbert Dürr 		aMatrix = CGAffineTransformMakeScale( mfFontStretch, 1.0F );
109*2822fc04SHerbert Dürr 		pMatrix = &aMatrix;
110*2822fc04SHerbert Dürr 	}
111*2822fc04SHerbert Dürr 
112*2822fc04SHerbert Dürr 	// create the style object for CoreText font attributes
113*2822fc04SHerbert Dürr 	static const CFIndex nMaxDictSize = 16; // TODO: does this really suffice?
114*2822fc04SHerbert Dürr 	mpStyleDict = CFDictionaryCreateMutable( NULL, nMaxDictSize,
115*2822fc04SHerbert Dürr 		&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
116*2822fc04SHerbert Dürr 
117*2822fc04SHerbert Dürr 	// set some default styles: no kerning, regular ligatures
118*2822fc04SHerbert Dürr 	static const CGFloat fValZero = 0.0;
119*2822fc04SHerbert Dürr 	CFNumberRef pCFFloatNumZero = CFNumberCreate( NULL, kCFNumberFloatType, &fValZero );
120*2822fc04SHerbert Dürr 	CFDictionarySetValue( mpStyleDict, kCTKernAttributeName, pCFFloatNumZero );
121*2822fc04SHerbert Dürr 	CFRelease( pCFFloatNumZero);
122*2822fc04SHerbert Dürr 	static const int nValOne = 1;
123*2822fc04SHerbert Dürr 	CFNumberRef pCFIntNumOne = CFNumberCreate( NULL, kCFNumberIntType, &nValOne );
124*2822fc04SHerbert Dürr 	CFDictionarySetValue( mpStyleDict, kCTLigatureAttributeName, pCFIntNumOne );
125*2822fc04SHerbert Dürr 	CFRelease( pCFIntNumOne);
126*2822fc04SHerbert Dürr 	CFBooleanRef pCFVertBool = pReqFont->mbVertical ? kCFBooleanTrue : kCFBooleanFalse;
127*2822fc04SHerbert Dürr 	CFDictionarySetValue( mpStyleDict, kCTVerticalFormsAttributeName, pCFVertBool );
128*2822fc04SHerbert Dürr 
129*2822fc04SHerbert Dürr 	CTFontDescriptorRef pFontDesc = (CTFontDescriptorRef)mpFontData->GetFontId();
130*2822fc04SHerbert Dürr 	CTFontRef pNewCTFont = CTFontCreateWithFontDescriptor( pFontDesc, fScaledFontHeight, pMatrix );
131*2822fc04SHerbert Dürr 	CFDictionarySetValue( mpStyleDict, kCTFontAttributeName, pNewCTFont );
132*2822fc04SHerbert Dürr 	CFRelease( pNewCTFont);
133*2822fc04SHerbert Dürr 
134*2822fc04SHerbert Dürr #if 0 // LastResort is implicit in CoreText's font cascading
135*2822fc04SHerbert Dürr 	const void* aGFBDescriptors[] = { CTFontDescriptorCreateWithNameAndSize( CFSTR("LastResort"), 0) }; // TODO: use the full GFB list
136*2822fc04SHerbert Dürr 	const int nGfbCount = sizeof(aGFBDescriptors) / sizeof(*aGFBDescriptors);
137*2822fc04SHerbert Dürr 	CFArrayRef pGfbList = CFArrayCreate( NULL, aGFBDescriptors, nGfbCount, &kCFTypeArrayCallBacks);
138*2822fc04SHerbert Dürr 	CFDictionaryAddValue( mpStyleDict, kCTFontCascadeListAttribute, pGfbList);
139*2822fc04SHerbert Dürr 	CFRelease( pGfbList);
140*2822fc04SHerbert Dürr #endif
141*2822fc04SHerbert Dürr }
142*2822fc04SHerbert Dürr 
143*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
144*2822fc04SHerbert Dürr 
145*2822fc04SHerbert Dürr CTTextStyle::~CTTextStyle( void )
146*2822fc04SHerbert Dürr {
147*2822fc04SHerbert Dürr 	if( mpStyleDict )
148*2822fc04SHerbert Dürr 		CFRelease( mpStyleDict );
149*2822fc04SHerbert Dürr }
150*2822fc04SHerbert Dürr 
151*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
152*2822fc04SHerbert Dürr 
153*2822fc04SHerbert Dürr void CTTextStyle::GetFontMetric( float fDPIY, ImplFontMetricData& rMetric ) const
154*2822fc04SHerbert Dürr {
155*2822fc04SHerbert Dürr 	// get the matching CoreText font handle
156*2822fc04SHerbert Dürr 	// TODO: is it worth it to cache the CTFontRef in SetFont() and reuse it here?
157*2822fc04SHerbert Dürr 	CTFontRef aCTFontRef = (CTFontRef)CFDictionaryGetValue( mpStyleDict, kCTFontAttributeName );
158*2822fc04SHerbert Dürr 
159*2822fc04SHerbert Dürr 	const double fPixelSize = (mfFontScale * fDPIY);
160*2822fc04SHerbert Dürr 	rMetric.mnAscent       = lrint( CTFontGetAscent( aCTFontRef ) * fPixelSize);
161*2822fc04SHerbert Dürr 	rMetric.mnDescent      = lrint( CTFontGetDescent( aCTFontRef ) * fPixelSize);
162*2822fc04SHerbert Dürr 	rMetric.mnIntLeading   = lrint( CTFontGetLeading( aCTFontRef ) * fPixelSize);
163*2822fc04SHerbert Dürr 	rMetric.mnExtLeading   = 0;
164*2822fc04SHerbert Dürr 	// since ImplFontMetricData::mnWidth is only used for stretching/squeezing fonts
165*2822fc04SHerbert Dürr 	// setting this width to the pixel height of the fontsize is good enough
166*2822fc04SHerbert Dürr 	// it also makes the calculation of the stretch factor simple
167*2822fc04SHerbert Dürr 	rMetric.mnWidth        = lrint( CTFontGetSize( aCTFontRef ) * fPixelSize * mfFontStretch);
168*2822fc04SHerbert Dürr 
169*2822fc04SHerbert Dürr 	// all CoreText fonts are scalable
170*2822fc04SHerbert Dürr 	rMetric.mbScalableFont = true;
171*2822fc04SHerbert Dürr 	// TODO: check if any kerning is supported
172*2822fc04SHerbert Dürr 	rMetric.mbKernableFont = true;
173*2822fc04SHerbert Dürr }
174*2822fc04SHerbert Dürr 
175*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
176*2822fc04SHerbert Dürr 
177*2822fc04SHerbert Dürr bool CTTextStyle::GetGlyphBoundRect( sal_GlyphId aGlyphId, Rectangle& rRect ) const
178*2822fc04SHerbert Dürr {
179*2822fc04SHerbert Dürr 	const DynCoreTextSyms& rCT = DynCoreTextSyms::get();
180*2822fc04SHerbert Dürr 	CGGlyph nCGGlyph = aGlyphId & GF_IDXMASK; // NOTE: CoreText handles glyph fallback itself
181*2822fc04SHerbert Dürr 	CTFontRef aCTFontRef = (CTFontRef)CFDictionaryGetValue( mpStyleDict, kCTFontAttributeName );
182*2822fc04SHerbert Dürr 
183*2822fc04SHerbert Dürr 	const CTFontOrientation aFontOrientation = kCTFontDefaultOrientation; // TODO: horz/vert
184*2822fc04SHerbert Dürr 	const CGRect aCGRect = rCT.FontGetBoundingRectsForGlyphs( aCTFontRef, aFontOrientation, &nCGGlyph, NULL, 1 );
185*2822fc04SHerbert Dürr 
186*2822fc04SHerbert Dürr 	rRect.Left()   = lrint( mfFontScale * aCGRect.origin.x );
187*2822fc04SHerbert Dürr 	rRect.Top()    = lrint( mfFontScale * aCGRect.origin.y );
188*2822fc04SHerbert Dürr 	rRect.Right()  = lrint( mfFontScale * (aCGRect.origin.x + aCGRect.size.width) );
189*2822fc04SHerbert Dürr 	rRect.Bottom() = lrint( mfFontScale * (aCGRect.origin.y + aCGRect.size.height) );
190*2822fc04SHerbert Dürr 	return true;
191*2822fc04SHerbert Dürr }
192*2822fc04SHerbert Dürr 
193*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
194*2822fc04SHerbert Dürr 
195*2822fc04SHerbert Dürr // callbacks from CTFontCreatePathForGlyph+CGPathApply for GetGlyphOutline()
196*2822fc04SHerbert Dürr struct GgoData { basegfx::B2DPolygon maPolygon; basegfx::B2DPolyPolygon* mpPolyPoly; };
197*2822fc04SHerbert Dürr 
198*2822fc04SHerbert Dürr static void MyCGPathApplierFunc( void* pData, const CGPathElement* pElement )
199*2822fc04SHerbert Dürr {
200*2822fc04SHerbert Dürr 	basegfx::B2DPolygon& rPolygon = static_cast<GgoData*>(pData)->maPolygon;
201*2822fc04SHerbert Dürr 	const int nPointCount = rPolygon.count();
202*2822fc04SHerbert Dürr 
203*2822fc04SHerbert Dürr 	switch( pElement->type )
204*2822fc04SHerbert Dürr 	{
205*2822fc04SHerbert Dürr 	case kCGPathElementCloseSubpath:
206*2822fc04SHerbert Dürr 	case kCGPathElementMoveToPoint:
207*2822fc04SHerbert Dürr 		if( nPointCount > 0 ) {
208*2822fc04SHerbert Dürr 			static_cast<GgoData*>(pData)->mpPolyPoly->append( rPolygon );
209*2822fc04SHerbert Dürr 			rPolygon.clear();
210*2822fc04SHerbert Dürr 		}
211*2822fc04SHerbert Dürr 		// fall through for kCGPathElementMoveToPoint:
212*2822fc04SHerbert Dürr 		if( pElement->type != kCGPathElementMoveToPoint )
213*2822fc04SHerbert Dürr 			break;
214*2822fc04SHerbert Dürr 	case kCGPathElementAddLineToPoint:
215*2822fc04SHerbert Dürr 		rPolygon.append( basegfx::B2DPoint( +pElement->points[0].x, -pElement->points[0].y ) );
216*2822fc04SHerbert Dürr 		break;
217*2822fc04SHerbert Dürr 	case kCGPathElementAddCurveToPoint:
218*2822fc04SHerbert Dürr 		rPolygon.append( basegfx::B2DPoint( +pElement->points[2].x, -pElement->points[2].y ) );
219*2822fc04SHerbert Dürr 		rPolygon.setNextControlPoint( nPointCount-1, basegfx::B2DPoint( pElement->points[0].x, -pElement->points[0].y ) );
220*2822fc04SHerbert Dürr 		rPolygon.setPrevControlPoint( nPointCount+0, basegfx::B2DPoint( pElement->points[1].x, -pElement->points[1].y ) );
221*2822fc04SHerbert Dürr 		break;
222*2822fc04SHerbert Dürr 	case kCGPathElementAddQuadCurveToPoint: {
223*2822fc04SHerbert Dürr 		const basegfx::B2DPoint aStartPt = rPolygon.getB2DPoint( nPointCount-1 );
224*2822fc04SHerbert Dürr 		const basegfx::B2DPoint aCtrPt1( (aStartPt.getX() + 2* pElement->points[0].x) / 3.0,
225*2822fc04SHerbert Dürr 					(aStartPt.getY() - 2 * pElement->points[0].y) / 3.0 );
226*2822fc04SHerbert Dürr 		const basegfx::B2DPoint aCtrPt2( (+2 * +pElement->points[0].x + pElement->points[1].x) / 3.0,
227*2822fc04SHerbert Dürr 				(-2 * pElement->points[0].y - pElement->points[1].y) / 3.0 );
228*2822fc04SHerbert Dürr 		rPolygon.append( basegfx::B2DPoint( +pElement->points[1].x, -pElement->points[1].y ) );
229*2822fc04SHerbert Dürr 		rPolygon.setNextControlPoint( nPointCount-1, aCtrPt1 );
230*2822fc04SHerbert Dürr 		rPolygon.setPrevControlPoint( nPointCount+0, aCtrPt2 );
231*2822fc04SHerbert Dürr 		} break;
232*2822fc04SHerbert Dürr 	}
233*2822fc04SHerbert Dürr }
234*2822fc04SHerbert Dürr 
235*2822fc04SHerbert Dürr bool CTTextStyle::GetGlyphOutline( sal_GlyphId aGlyphId, basegfx::B2DPolyPolygon& rResult ) const
236*2822fc04SHerbert Dürr {
237*2822fc04SHerbert Dürr 	rResult.clear();
238*2822fc04SHerbert Dürr 
239*2822fc04SHerbert Dürr 	const DynCoreTextSyms& rCT = DynCoreTextSyms::get();
240*2822fc04SHerbert Dürr 	// TODO: GF_FONTMASK if using non-native glyph fallback
241*2822fc04SHerbert Dürr 	CGGlyph nCGGlyph = aGlyphId & GF_IDXMASK;
242*2822fc04SHerbert Dürr 	CTFontRef pCTFont = (CTFontRef)CFDictionaryGetValue( mpStyleDict, kCTFontAttributeName );
243*2822fc04SHerbert Dürr 	CGPathRef xPath = rCT.FontCreatePathForGlyph( pCTFont, nCGGlyph, NULL );
244*2822fc04SHerbert Dürr 
245*2822fc04SHerbert Dürr 	GgoData aGgoData;
246*2822fc04SHerbert Dürr 	aGgoData.mpPolyPoly = &rResult;
247*2822fc04SHerbert Dürr 	CGPathApply( xPath, (void*)&aGgoData, MyCGPathApplierFunc );
248*2822fc04SHerbert Dürr #if 0 // TODO: does OSX ensure that the last polygon is always closed?
249*2822fc04SHerbert Dürr 	const CGPathElement aClosingElement = { kCGPathElementCloseSubpath, NULL };
250*2822fc04SHerbert Dürr 	MyCGPathApplierFunc( (void*)&aGgoData, &aClosingElement );
251*2822fc04SHerbert Dürr #endif
252*2822fc04SHerbert Dürr 
253*2822fc04SHerbert Dürr 	// apply the font scale
254*2822fc04SHerbert Dürr 	if( mfFontScale != 1.0 ) {
255*2822fc04SHerbert Dürr 		basegfx::B2DHomMatrix aScale;
256*2822fc04SHerbert Dürr 		aScale.scale( +mfFontScale, +mfFontScale );
257*2822fc04SHerbert Dürr 		rResult.transform( aScale );
258*2822fc04SHerbert Dürr 	}
259*2822fc04SHerbert Dürr 
260*2822fc04SHerbert Dürr 	return true;
261*2822fc04SHerbert Dürr }
262*2822fc04SHerbert Dürr 
263*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
264*2822fc04SHerbert Dürr 
265*2822fc04SHerbert Dürr void CTTextStyle::SetTextColor( const RGBAColor& rColor )
266*2822fc04SHerbert Dürr {
267*2822fc04SHerbert Dürr #if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
268*2822fc04SHerbert Dürr 	CGColorRef pCGColor = CGColorCreateGenericRGB( rColor.GetRed(),
269*2822fc04SHerbert Dürr 		rColor.GetGreen(), rColor.GetBlue(), rColor.GetAlpha() );
270*2822fc04SHerbert Dürr #else // for builds on OSX 10.4 SDK
271*2822fc04SHerbert Dürr 	const CGColorSpaceRef pCGColorSpace = GetSalData()->mxRGBSpace;
272*2822fc04SHerbert Dürr 	CGColorRef pCGColor = CGColorCreate( pCGColorSpace, rColor.AsArray() );
273*2822fc04SHerbert Dürr #endif
274*2822fc04SHerbert Dürr 	CFDictionarySetValue( mpStyleDict, kCTForegroundColorAttributeName, pCGColor );
275*2822fc04SHerbert Dürr 	CFRelease( pCGColor);
276*2822fc04SHerbert Dürr }
277*2822fc04SHerbert Dürr 
278*2822fc04SHerbert Dürr // =======================================================================
279*2822fc04SHerbert Dürr 
280*2822fc04SHerbert Dürr CTFontData::CTFontData( const ImplDevFontAttributes& rDFA, sal_IntPtr nFontId )
281*2822fc04SHerbert Dürr :	ImplMacFontData( rDFA, nFontId )
282*2822fc04SHerbert Dürr {}
283*2822fc04SHerbert Dürr 
284*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
285*2822fc04SHerbert Dürr 
286*2822fc04SHerbert Dürr CTFontData::~CTFontData( void )
287*2822fc04SHerbert Dürr {
288*2822fc04SHerbert Dürr 	// TODO: any resources to release?
289*2822fc04SHerbert Dürr }
290*2822fc04SHerbert Dürr 
291*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
292*2822fc04SHerbert Dürr 
293*2822fc04SHerbert Dürr ImplFontData* CTFontData::Clone( void ) const
294*2822fc04SHerbert Dürr {
295*2822fc04SHerbert Dürr 	return new CTFontData( *this);
296*2822fc04SHerbert Dürr }
297*2822fc04SHerbert Dürr 
298*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
299*2822fc04SHerbert Dürr 
300*2822fc04SHerbert Dürr ImplMacTextStyle* CTFontData::CreateMacTextStyle( const ImplFontSelectData& rFSD ) const
301*2822fc04SHerbert Dürr {
302*2822fc04SHerbert Dürr 	return new CTTextStyle( rFSD);
303*2822fc04SHerbert Dürr }
304*2822fc04SHerbert Dürr 
305*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
306*2822fc04SHerbert Dürr 
307*2822fc04SHerbert Dürr ImplFontEntry* CTFontData::CreateFontInstance( /*const*/ ImplFontSelectData& rFSD ) const
308*2822fc04SHerbert Dürr {
309*2822fc04SHerbert Dürr 	return new ImplFontEntry( rFSD);
310*2822fc04SHerbert Dürr }
311*2822fc04SHerbert Dürr 
312*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
313*2822fc04SHerbert Dürr 
314*2822fc04SHerbert Dürr int CTFontData::GetFontTable( const char pTagName[5], unsigned char* pResultBuf ) const
315*2822fc04SHerbert Dürr {
316*2822fc04SHerbert Dürr 	DBG_ASSERT( pTagName[4]=='\0', "CTFontData::GetFontTable with invalid tagname!\n" );
317*2822fc04SHerbert Dürr 
318*2822fc04SHerbert Dürr 	const CTFontTableTag nTagCode = (pTagName[0]<<24) + (pTagName[1]<<16) + (pTagName[2]<<8) + (pTagName[3]<<0);
319*2822fc04SHerbert Dürr 
320*2822fc04SHerbert Dürr 	// get the raw table length
321*2822fc04SHerbert Dürr 	CTFontDescriptorRef pFontDesc = reinterpret_cast<CTFontDescriptorRef>( GetFontId());
322*2822fc04SHerbert Dürr 	CTFontRef rCTFont = CTFontCreateWithFontDescriptor( pFontDesc, 0.0, NULL);
323*2822fc04SHerbert Dürr 	CFDataRef pDataRef = CTFontCopyTable( rCTFont, nTagCode, kCTFontTableOptionExcludeSynthetic);
324*2822fc04SHerbert Dürr 	CFRelease( rCTFont);
325*2822fc04SHerbert Dürr 	if( !pDataRef)
326*2822fc04SHerbert Dürr 		return 0;
327*2822fc04SHerbert Dürr 
328*2822fc04SHerbert Dürr 	const CFIndex nByteLength = CFDataGetLength( pDataRef);
329*2822fc04SHerbert Dürr 
330*2822fc04SHerbert Dürr 	// get the raw table data if requested
331*2822fc04SHerbert Dürr 	if( pResultBuf && (nByteLength > 0))
332*2822fc04SHerbert Dürr 	{
333*2822fc04SHerbert Dürr 		const CFRange aFullRange = CFRangeMake( 0, nByteLength);
334*2822fc04SHerbert Dürr 		CFDataGetBytes( pDataRef, aFullRange, (UInt8*)pResultBuf);
335*2822fc04SHerbert Dürr 	}
336*2822fc04SHerbert Dürr 
337*2822fc04SHerbert Dürr 	CFRelease( pDataRef);
338*2822fc04SHerbert Dürr 
339*2822fc04SHerbert Dürr 	return (int)nByteLength;
340*2822fc04SHerbert Dürr }
341*2822fc04SHerbert Dürr 
342*2822fc04SHerbert Dürr // =======================================================================
343*2822fc04SHerbert Dürr 
344*2822fc04SHerbert Dürr static void CTFontEnumCallBack( const void* pValue, void* pContext )
345*2822fc04SHerbert Dürr {
346*2822fc04SHerbert Dürr 	CTFontDescriptorRef pFD = static_cast<CTFontDescriptorRef>(pValue);
347*2822fc04SHerbert Dürr 
348*2822fc04SHerbert Dürr 	// all CoreText fonts are device fonts that can rotate just fine
349*2822fc04SHerbert Dürr 	ImplDevFontAttributes rDFA;
350*2822fc04SHerbert Dürr 	rDFA.mbOrientation = true;
351*2822fc04SHerbert Dürr 	rDFA.mbDevice      = true;
352*2822fc04SHerbert Dürr 	rDFA.mnQuality     = 0;
353*2822fc04SHerbert Dürr 
354*2822fc04SHerbert Dürr 	// reset the font attributes
355*2822fc04SHerbert Dürr 	rDFA.meFamily     = FAMILY_DONTKNOW;
356*2822fc04SHerbert Dürr 	rDFA.mePitch      = PITCH_VARIABLE;
357*2822fc04SHerbert Dürr 	rDFA.meWidthType  = WIDTH_NORMAL;
358*2822fc04SHerbert Dürr 	rDFA.meWeight     = WEIGHT_NORMAL;
359*2822fc04SHerbert Dürr 	rDFA.meItalic     = ITALIC_NONE;
360*2822fc04SHerbert Dürr 	rDFA.mbSymbolFlag = false;
361*2822fc04SHerbert Dürr 
362*2822fc04SHerbert Dürr 	// all scalable fonts on this platform are subsettable
363*2822fc04SHerbert Dürr 	rDFA.mbEmbeddable = false;
364*2822fc04SHerbert Dürr 	rDFA.mbSubsettable = true;
365*2822fc04SHerbert Dürr 
366*2822fc04SHerbert Dürr 	// get font name
367*2822fc04SHerbert Dürr 	// TODO: use kCTFontDisplayNameAttribute instead???
368*2822fc04SHerbert Dürr 	CFStringRef pFamilyName = (CFStringRef)CTFontDescriptorCopyAttribute( pFD, kCTFontFamilyNameAttribute );
369*2822fc04SHerbert Dürr 	rDFA.maName = GetOUString( pFamilyName );
370*2822fc04SHerbert Dürr 	// get font style
371*2822fc04SHerbert Dürr 	CFStringRef pStyleName = (CFStringRef)CTFontDescriptorCopyAttribute( pFD, kCTFontStyleNameAttribute );
372*2822fc04SHerbert Dürr 	rDFA.maStyleName = GetOUString( pStyleName );
373*2822fc04SHerbert Dürr 
374*2822fc04SHerbert Dürr 	// get font-enabled status
375*2822fc04SHerbert Dürr 	int bFontEnabled = FALSE;
376*2822fc04SHerbert Dürr 	CFNumberRef pFontEnabled = (CFNumberRef)CTFontDescriptorCopyAttribute( pFD, kCTFontEnabledAttribute );
377*2822fc04SHerbert Dürr 	CFNumberGetValue( pFontEnabled, kCFNumberIntType, &bFontEnabled );
378*2822fc04SHerbert Dürr 
379*2822fc04SHerbert Dürr 	// get font attributes
380*2822fc04SHerbert Dürr 	CFDictionaryRef pAttrDict = (CFDictionaryRef)CTFontDescriptorCopyAttribute( pFD, kCTFontTraitsAttribute );
381*2822fc04SHerbert Dürr 
382*2822fc04SHerbert Dürr 	// get symbolic trait
383*2822fc04SHerbert Dürr 	// TODO: use other traits such as MonoSpace/Condensed/Expanded or Vertical too
384*2822fc04SHerbert Dürr 	SInt64 nSymbolTrait = 0;
385*2822fc04SHerbert Dürr 	CFNumberRef pSymbolNum = NULL;
386*2822fc04SHerbert Dürr 	if( CFDictionaryGetValueIfPresent( pAttrDict, kCTFontSymbolicTrait, (const void**)&pSymbolNum ) ) {
387*2822fc04SHerbert Dürr 		CFNumberGetValue( pSymbolNum, kCFNumberSInt64Type, &nSymbolTrait );
388*2822fc04SHerbert Dürr 		rDFA.mbSymbolFlag = ((nSymbolTrait & kCTFontClassMaskTrait) == kCTFontSymbolicClass);
389*2822fc04SHerbert Dürr 	}
390*2822fc04SHerbert Dürr 
391*2822fc04SHerbert Dürr 	// get the font weight
392*2822fc04SHerbert Dürr 	double fWeight = 0;
393*2822fc04SHerbert Dürr 	CFNumberRef pWeightNum = (CFNumberRef)CFDictionaryGetValue( pAttrDict, kCTFontWeightTrait );
394*2822fc04SHerbert Dürr 	CFNumberGetValue( pWeightNum, kCFNumberDoubleType, &fWeight );
395*2822fc04SHerbert Dürr 	int nInt = WEIGHT_NORMAL;
396*2822fc04SHerbert Dürr 	if( fWeight > 0 ) {
397*2822fc04SHerbert Dürr 		nInt = rint(WEIGHT_NORMAL + fWeight * ((WEIGHT_BLACK - WEIGHT_NORMAL)/0.68));
398*2822fc04SHerbert Dürr 		if( nInt > WEIGHT_BLACK )
399*2822fc04SHerbert Dürr 			nInt = WEIGHT_BLACK;
400*2822fc04SHerbert Dürr 	} else if( fWeight < 0 ) {
401*2822fc04SHerbert Dürr 		nInt = rint(WEIGHT_NORMAL + fWeight * ((WEIGHT_NORMAL - WEIGHT_THIN)/0.9));
402*2822fc04SHerbert Dürr 		if( nInt < WEIGHT_THIN )
403*2822fc04SHerbert Dürr 			nInt = WEIGHT_THIN;
404*2822fc04SHerbert Dürr 	}
405*2822fc04SHerbert Dürr 	rDFA.meWeight = (FontWeight)nInt;
406*2822fc04SHerbert Dürr 
407*2822fc04SHerbert Dürr 	// get the font slant
408*2822fc04SHerbert Dürr 	double fSlant = 0;
409*2822fc04SHerbert Dürr 	CFNumberRef pSlantNum = (CFNumberRef)CFDictionaryGetValue( pAttrDict, kCTFontSlantTrait );
410*2822fc04SHerbert Dürr 	CFNumberGetValue( pSlantNum, kCFNumberDoubleType, &fSlant );
411*2822fc04SHerbert Dürr 	if( fSlant >= 0.035 )
412*2822fc04SHerbert Dürr 		rDFA.meItalic = ITALIC_NORMAL;
413*2822fc04SHerbert Dürr 
414*2822fc04SHerbert Dürr 	// get width trait
415*2822fc04SHerbert Dürr 	double fWidth = 0;
416*2822fc04SHerbert Dürr 	CFNumberRef pWidthNum = (CFNumberRef)CFDictionaryGetValue( pAttrDict, kCTFontWidthTrait );
417*2822fc04SHerbert Dürr 	CFNumberGetValue( pWidthNum, kCFNumberDoubleType, &fWidth );
418*2822fc04SHerbert Dürr 	nInt = WIDTH_NORMAL;
419*2822fc04SHerbert Dürr 	if( fWidth > 0 ) {
420*2822fc04SHerbert Dürr 		nInt = rint( WIDTH_NORMAL + fWidth * ((WIDTH_ULTRA_EXPANDED - WIDTH_NORMAL)/0.4));
421*2822fc04SHerbert Dürr 		if( nInt > WIDTH_ULTRA_EXPANDED )
422*2822fc04SHerbert Dürr 			nInt = WIDTH_ULTRA_EXPANDED;
423*2822fc04SHerbert Dürr 	} else if( fWidth < 0 ) {
424*2822fc04SHerbert Dürr 		nInt = rint( WIDTH_NORMAL + fWidth * ((WIDTH_NORMAL - WIDTH_ULTRA_CONDENSED)/0.5));
425*2822fc04SHerbert Dürr 		if( nInt < WIDTH_ULTRA_CONDENSED )
426*2822fc04SHerbert Dürr 			nInt = WIDTH_ULTRA_CONDENSED;
427*2822fc04SHerbert Dürr 	}
428*2822fc04SHerbert Dürr 	rDFA.meWidthType = (FontWidth)nInt;
429*2822fc04SHerbert Dürr 
430*2822fc04SHerbert Dürr 	// release the attribute dict that we had copied
431*2822fc04SHerbert Dürr 	CFRelease( pAttrDict );
432*2822fc04SHerbert Dürr 
433*2822fc04SHerbert Dürr 	// TODO? also use the HEAD table if available to get more attributes
434*2822fc04SHerbert Dürr //	CFDataRef CTFontCopyTable( CTFontRef, kCTFontTableHead, /*kCTFontTableOptionNoOptions*/kCTFontTableOptionExcludeSynthetic );
435*2822fc04SHerbert Dürr 
436*2822fc04SHerbert Dürr #if (OSL_DEBUG_LEVEL >= 1)
437*2822fc04SHerbert Dürr 	// update font attributes using the font's postscript name
438*2822fc04SHerbert Dürr 	ImplDevFontAttributes rDFA2;
439*2822fc04SHerbert Dürr 	CTFontRef pFont = CTFontCreateWithFontDescriptor( pFD, 0.0, NULL );
440*2822fc04SHerbert Dürr 	CFStringRef pPSName = CTFontCopyPostScriptName( pFont );
441*2822fc04SHerbert Dürr 	const String aPSName = GetOUString( pPSName );
442*2822fc04SHerbert Dürr 
443*2822fc04SHerbert Dürr 	rDFA2.mbSymbolFlag = false;
444*2822fc04SHerbert Dürr 	rDFA2.mePitch      = PITCH_VARIABLE;
445*2822fc04SHerbert Dürr 	rDFA2.meWidthType  = WIDTH_NORMAL;
446*2822fc04SHerbert Dürr 	rDFA2.meWeight     = WEIGHT_NORMAL;
447*2822fc04SHerbert Dürr 	rDFA2.meItalic     = ITALIC_NONE;
448*2822fc04SHerbert Dürr 
449*2822fc04SHerbert Dürr 	UpdateAttributesFromPSName( aPSName, rDFA2 );
450*2822fc04SHerbert Dürr 	CFRelease( pPSName );
451*2822fc04SHerbert Dürr 	CFRelease( pFont );
452*2822fc04SHerbert Dürr 
453*2822fc04SHerbert Dürr 	// show the font details and compare the CTFontDescriptor vs. PSName traits
454*2822fc04SHerbert Dürr 	char cMatch = (rDFA.mbSymbolFlag==rDFA2.mbSymbolFlag);
455*2822fc04SHerbert Dürr 	cMatch &= (rDFA.meWeight==rDFA2.meWeight);
456*2822fc04SHerbert Dürr 	cMatch &= ((rDFA.meItalic==ITALIC_NONE) == (rDFA2.meItalic==ITALIC_NONE));
457*2822fc04SHerbert Dürr 	cMatch &= (rDFA.meWidthType==rDFA2.meWidthType);
458*2822fc04SHerbert Dürr 	cMatch = cMatch ? '.' : '#';
459*2822fc04SHerbert Dürr 
460*2822fc04SHerbert Dürr 	char aFN[256], aSN[256];
461*2822fc04SHerbert Dürr 	CFStringGetCString( pFamilyName, aFN, sizeof(aFN), kCFStringEncodingUTF8 );
462*2822fc04SHerbert Dürr 	CFStringGetCString( pStyleName, aSN, sizeof(aSN), kCFStringEncodingUTF8 );
463*2822fc04SHerbert Dürr 
464*2822fc04SHerbert Dürr 	const ByteString aPSCName( aPSName, RTL_TEXTENCODING_UTF8 );
465*2822fc04SHerbert Dürr 	const char* aPN = aPSCName.GetBuffer();
466*2822fc04SHerbert Dürr 	printf("\tCTFont_%d%x%d%d_%c_%d%x%d%d ena=%d s=%02d b=%+.2f i=%+.2f w=%+.2f (\"%s\", \"%s\", \"%s\")\n",
467*2822fc04SHerbert Dürr 		(int)rDFA.mbSymbolFlag,(int)rDFA.meWeight,(int)rDFA.meItalic,(int)rDFA.meWidthType,
468*2822fc04SHerbert Dürr 		cMatch,
469*2822fc04SHerbert Dürr 		(int)rDFA2.mbSymbolFlag,(int)rDFA2.meWeight,(int)rDFA2.meItalic,(int)rDFA2.meWidthType,
470*2822fc04SHerbert Dürr 		bFontEnabled,
471*2822fc04SHerbert Dürr 		(int)(nSymbolTrait>>kCTFontClassMaskShift),fWeight,fSlant,fWidth,aFN,aSN,aPN);
472*2822fc04SHerbert Dürr #endif // (OSL_DEBUG_LEVEL >= 1)
473*2822fc04SHerbert Dürr 
474*2822fc04SHerbert Dürr 	if( bFontEnabled)
475*2822fc04SHerbert Dürr 	{
476*2822fc04SHerbert Dürr 		const sal_IntPtr nFontId = (sal_IntPtr)pValue;
477*2822fc04SHerbert Dürr 		CTFontData* pFontData = new CTFontData( rDFA, nFontId );
478*2822fc04SHerbert Dürr 		CTFontList* pFontList = (CTFontList*)pContext;
479*2822fc04SHerbert Dürr 		pFontList->AddFont( pFontData );
480*2822fc04SHerbert Dürr 	}
481*2822fc04SHerbert Dürr }
482*2822fc04SHerbert Dürr 
483*2822fc04SHerbert Dürr // =======================================================================
484*2822fc04SHerbert Dürr 
485*2822fc04SHerbert Dürr CTFontList::CTFontList()
486*2822fc04SHerbert Dürr :	mpCTFontCollection( NULL )
487*2822fc04SHerbert Dürr ,	mpCTFontArray( NULL )
488*2822fc04SHerbert Dürr {}
489*2822fc04SHerbert Dürr 
490*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
491*2822fc04SHerbert Dürr 
492*2822fc04SHerbert Dürr CTFontList::~CTFontList()
493*2822fc04SHerbert Dürr {
494*2822fc04SHerbert Dürr 	CTFontContainer::const_iterator it = maFontContainer.begin();
495*2822fc04SHerbert Dürr 	for(; it != maFontContainer.end(); ++it )
496*2822fc04SHerbert Dürr 		delete (*it).second;
497*2822fc04SHerbert Dürr 	maFontContainer.clear();
498*2822fc04SHerbert Dürr 
499*2822fc04SHerbert Dürr 	if( mpCTFontArray )
500*2822fc04SHerbert Dürr 		CFRelease( mpCTFontArray );
501*2822fc04SHerbert Dürr 	if( mpCTFontCollection )
502*2822fc04SHerbert Dürr 		CFRelease( mpCTFontCollection );
503*2822fc04SHerbert Dürr }
504*2822fc04SHerbert Dürr 
505*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
506*2822fc04SHerbert Dürr 
507*2822fc04SHerbert Dürr void CTFontList::AddFont( CTFontData* pFontData )
508*2822fc04SHerbert Dürr {
509*2822fc04SHerbert Dürr 	sal_IntPtr nFontId = pFontData->GetFontId();
510*2822fc04SHerbert Dürr 	maFontContainer[ nFontId ] = pFontData;
511*2822fc04SHerbert Dürr }
512*2822fc04SHerbert Dürr 
513*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
514*2822fc04SHerbert Dürr 
515*2822fc04SHerbert Dürr void CTFontList::AnnounceFonts( ImplDevFontList& rFontList ) const
516*2822fc04SHerbert Dürr {
517*2822fc04SHerbert Dürr 	CTFontContainer::const_iterator it = maFontContainer.begin();
518*2822fc04SHerbert Dürr 	for(; it != maFontContainer.end(); ++it )
519*2822fc04SHerbert Dürr 		rFontList.Add( (*it).second->Clone() );
520*2822fc04SHerbert Dürr }
521*2822fc04SHerbert Dürr 
522*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
523*2822fc04SHerbert Dürr 
524*2822fc04SHerbert Dürr ImplMacFontData* CTFontList::GetFontDataFromId( sal_IntPtr nFontId ) const
525*2822fc04SHerbert Dürr {
526*2822fc04SHerbert Dürr 	CTFontContainer::const_iterator it = maFontContainer.find( nFontId );
527*2822fc04SHerbert Dürr 	if( it == maFontContainer.end() )
528*2822fc04SHerbert Dürr 		return NULL;
529*2822fc04SHerbert Dürr 	return (*it).second;
530*2822fc04SHerbert Dürr }
531*2822fc04SHerbert Dürr 
532*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
533*2822fc04SHerbert Dürr 
534*2822fc04SHerbert Dürr bool CTFontList::Init( void )
535*2822fc04SHerbert Dürr {
536*2822fc04SHerbert Dürr #ifndef DISABLE_CORETEXT_DYNLOAD
537*2822fc04SHerbert Dürr 	// check availability of the CoreText API
538*2822fc04SHerbert Dürr 	const DynCoreTextSyms& rCT = DynCoreTextSyms::get();
539*2822fc04SHerbert Dürr 	if( !rCT.IsActive() )
540*2822fc04SHerbert Dürr 		return false;
541*2822fc04SHerbert Dürr #endif // DISABLE_CORETEXT_DYNLOAD
542*2822fc04SHerbert Dürr 
543*2822fc04SHerbert Dürr 	// enumerate available system fonts
544*2822fc04SHerbert Dürr 	static const int nMaxDictEntries = 8;
545*2822fc04SHerbert Dürr 	CFMutableDictionaryRef pCFDict = CFDictionaryCreateMutable( NULL,
546*2822fc04SHerbert Dürr 		nMaxDictEntries, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
547*2822fc04SHerbert Dürr 	CFDictionaryAddValue( pCFDict, kCTFontCollectionRemoveDuplicatesOption, kCFBooleanTrue );
548*2822fc04SHerbert Dürr 	mpCTFontCollection = rCT.FontCollectionCreateFromAvailableFonts( pCFDict );
549*2822fc04SHerbert Dürr 	CFRelease( pCFDict );
550*2822fc04SHerbert Dürr 
551*2822fc04SHerbert Dürr 	mpCTFontArray = rCT.FontCollectionCreateMatchingFontDescriptors( mpCTFontCollection );
552*2822fc04SHerbert Dürr 	const int nFontCount = CFArrayGetCount( mpCTFontArray );
553*2822fc04SHerbert Dürr 	const CFRange aFullRange = CFRangeMake( 0, nFontCount );
554*2822fc04SHerbert Dürr 	CFArrayApplyFunction( mpCTFontArray, aFullRange, CTFontEnumCallBack, this );
555*2822fc04SHerbert Dürr 
556*2822fc04SHerbert Dürr 	return true;
557*2822fc04SHerbert Dürr }
558*2822fc04SHerbert Dürr 
559*2822fc04SHerbert Dürr // =======================================================================
560*2822fc04SHerbert Dürr 
561*2822fc04SHerbert Dürr #ifndef DISABLE_CORETEXT_DYNLOAD
562*2822fc04SHerbert Dürr 
563*2822fc04SHerbert Dürr DynCoreTextSyms::DynCoreTextSyms( void )
564*2822fc04SHerbert Dürr {
565*2822fc04SHerbert Dürr 	mbIsActive = false;
566*2822fc04SHerbert Dürr 
567*2822fc04SHerbert Dürr 	// check if CoreText has been explicitely disabled
568*2822fc04SHerbert Dürr 	const char* pEnvStr = getenv( "SAL_DISABLE_CORETEXT");
569*2822fc04SHerbert Dürr 	if( pEnvStr && (pEnvStr[0] != '0') )
570*2822fc04SHerbert Dürr 		return;
571*2822fc04SHerbert Dürr 
572*2822fc04SHerbert Dürr 	// check CoreText version
573*2822fc04SHerbert Dürr 	GetCoreTextVersion = (uint32_t(*)(void))dlsym( RTLD_DEFAULT, "CTGetCoreTextVersion");
574*2822fc04SHerbert Dürr 	if( !GetCoreTextVersion) return;
575*2822fc04SHerbert Dürr 
576*2822fc04SHerbert Dürr 	const uint32_t nCTVersion = GetCoreTextVersion();
577*2822fc04SHerbert Dürr 	static const uint32_t mykCTVersionNumber10_5 = 0x00020000;
578*2822fc04SHerbert Dürr 	if( nCTVersion < mykCTVersionNumber10_5)
579*2822fc04SHerbert Dürr 		return;
580*2822fc04SHerbert Dürr 
581*2822fc04SHerbert Dürr 	// load CoreText symbols dynamically
582*2822fc04SHerbert Dürr 	LineGetTrailingWhitespaceWidth = (double(*)(CTLineRef))dlsym( RTLD_DEFAULT, "CTLineGetTrailingWhitespaceWidth");
583*2822fc04SHerbert Dürr 	if( !LineGetTrailingWhitespaceWidth) return;
584*2822fc04SHerbert Dürr 
585*2822fc04SHerbert Dürr 	LineCreateJustifiedLine = (CTLineRef(*)(CTLineRef,CGFloat,double))dlsym( RTLD_DEFAULT, "CTLineCreateJustifiedLine");
586*2822fc04SHerbert Dürr 	if( !LineCreateJustifiedLine) return;
587*2822fc04SHerbert Dürr 
588*2822fc04SHerbert Dürr 	LineGetOffsetForStringIndex = (CGFloat(*)(CTLineRef,CFIndex,CGFloat*))dlsym( RTLD_DEFAULT, "CTLineGetOffsetForStringIndex");
589*2822fc04SHerbert Dürr 	if( !LineGetOffsetForStringIndex) return;
590*2822fc04SHerbert Dürr 
591*2822fc04SHerbert Dürr 	LineGetGlyphRuns = (CFArrayRef(*)(CTLineRef))dlsym( RTLD_DEFAULT, "CTLineGetGlyphRuns");
592*2822fc04SHerbert Dürr 	if( !LineGetGlyphRuns) return;
593*2822fc04SHerbert Dürr 
594*2822fc04SHerbert Dürr 	RunGetGlyphCount = (CFIndex(*)(CTRunRef))dlsym( RTLD_DEFAULT, "CTRunGetGlyphCount");
595*2822fc04SHerbert Dürr 	if( !RunGetGlyphCount) return;
596*2822fc04SHerbert Dürr 
597*2822fc04SHerbert Dürr 	RunGetGlyphsPtr = (const CGGlyph*(*)(CTRunRef))dlsym( RTLD_DEFAULT, "CTRunGetGlyphsPtr");
598*2822fc04SHerbert Dürr 	if( !RunGetGlyphsPtr) return;
599*2822fc04SHerbert Dürr 
600*2822fc04SHerbert Dürr 	RunGetPositionsPtr = (const CGPoint*(*)(CTRunRef))dlsym( RTLD_DEFAULT, "CTRunGetPositionsPtr");
601*2822fc04SHerbert Dürr 	if( !RunGetPositionsPtr) return;
602*2822fc04SHerbert Dürr 
603*2822fc04SHerbert Dürr 	RunGetAdvancesPtr = (const CGSize*(*)(CTRunRef))dlsym( RTLD_DEFAULT, "CTRunGetAdvancesPtr");
604*2822fc04SHerbert Dürr 	if( !RunGetAdvancesPtr) return;
605*2822fc04SHerbert Dürr 
606*2822fc04SHerbert Dürr 	RunGetStringIndicesPtr = (const CFIndex*(*)(CTRunRef))dlsym( RTLD_DEFAULT, "CTRunGetStringIndicesPtr");
607*2822fc04SHerbert Dürr 	if( !RunGetStringIndicesPtr) return;
608*2822fc04SHerbert Dürr 
609*2822fc04SHerbert Dürr 	FontCollectionCreateFromAvailableFonts = (CTFontCollectionRef(*)(CFDictionaryRef))dlsym( RTLD_DEFAULT, "CTFontCollectionCreateFromAvailableFonts");
610*2822fc04SHerbert Dürr 	if( !FontCollectionCreateFromAvailableFonts) return;
611*2822fc04SHerbert Dürr 
612*2822fc04SHerbert Dürr 	FontCollectionCreateMatchingFontDescriptors = (CFArrayRef(*)(CTFontCollectionRef))dlsym( RTLD_DEFAULT, "CTFontCollectionCreateMatchingFontDescriptors");
613*2822fc04SHerbert Dürr 	if( !FontCollectionCreateMatchingFontDescriptors) return;
614*2822fc04SHerbert Dürr 
615*2822fc04SHerbert Dürr 	FontCreatePathForGlyph = (CGPathRef(*)(CTFontRef,CGGlyph,const CGAffineTransform*))dlsym( RTLD_DEFAULT, "CTFontCreatePathForGlyph");
616*2822fc04SHerbert Dürr 	if( !FontCreatePathForGlyph) return;
617*2822fc04SHerbert Dürr 
618*2822fc04SHerbert Dürr 	FontGetBoundingRectsForGlyphs = (CGRect(*)(CTFontRef,CTFontOrientation,CGGlyph*,CGRect*,CFIndex))dlsym( RTLD_DEFAULT, "CTFontGetBoundingRectsForGlyphs");
619*2822fc04SHerbert Dürr 	if( !FontGetBoundingRectsForGlyphs) return;
620*2822fc04SHerbert Dürr 
621*2822fc04SHerbert Dürr 	mbIsActive = true;
622*2822fc04SHerbert Dürr }
623*2822fc04SHerbert Dürr 
624*2822fc04SHerbert Dürr // -----------------------------------------------------------------------
625*2822fc04SHerbert Dürr 
626*2822fc04SHerbert Dürr const DynCoreTextSyms& DynCoreTextSyms::get( void )
627*2822fc04SHerbert Dürr {
628*2822fc04SHerbert Dürr 	static DynCoreTextSyms aCT;
629*2822fc04SHerbert Dürr 	return aCT;
630*2822fc04SHerbert Dürr }
631*2822fc04SHerbert Dürr 
632*2822fc04SHerbert Dürr #endif // DISABLE_CORETEXT_DYNLOAD
633*2822fc04SHerbert Dürr 
634*2822fc04SHerbert Dürr // =======================================================================
635*2822fc04SHerbert Dürr 
636*2822fc04SHerbert Dürr SystemFontList* GetCoretextFontList( void )
637*2822fc04SHerbert Dürr {
638*2822fc04SHerbert Dürr 	CTFontList* pList = new CTFontList();
639*2822fc04SHerbert Dürr 	if( !pList->Init() ) {
640*2822fc04SHerbert Dürr 		delete pList;
641*2822fc04SHerbert Dürr 		return NULL;
642*2822fc04SHerbert Dürr 	}
643*2822fc04SHerbert Dürr 
644*2822fc04SHerbert Dürr 	return pList;
645*2822fc04SHerbert Dürr }
646*2822fc04SHerbert Dürr 
647*2822fc04SHerbert Dürr // =======================================================================
648*2822fc04SHerbert Dürr 
649