Update ooo320-m1
[ooovba.git] / vcl / aqua / source / gdi / salatsuifontutils.cxx
blob61ebf4207e809d39c21cc843734e96cfef781aa5
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
31 #include <boost/assert.hpp>
32 #include <vector>
33 #include <set>
35 #include "salgdi.h"
36 #include "saldata.hxx"
37 #include "vcl/svapp.hxx"
38 #include "salatsuifontutils.hxx"
40 // we have to get the font attributes from the name table
41 // since neither head's macStyle nor OS/2's panose are easily available
42 // during font enumeration. macStyle bits would be not sufficient anyway
43 // and SFNT fonts on Mac usually do not contain an OS/2 table.
44 static void UpdateAttributesFromPSName( const String& rPSName, ImplDevFontAttributes& rDFA )
46 ByteString aPSName( rPSName, RTL_TEXTENCODING_UTF8 );
47 aPSName.ToLowerAscii();
49 // TODO: use a multi-string ignore-case matcher once it becomes available
50 if( (aPSName.Search("regular") != STRING_NOTFOUND)
51 || (aPSName.Search("normal") != STRING_NOTFOUND)
52 || (aPSName.Search("roman") != STRING_NOTFOUND)
53 || (aPSName.Search("medium") != STRING_NOTFOUND)
54 || (aPSName.Search("plain") != STRING_NOTFOUND)
55 || (aPSName.Search("standard") != STRING_NOTFOUND)
56 || (aPSName.Search("std") != STRING_NOTFOUND) )
58 rDFA.meWidthType = WIDTH_NORMAL;
59 rDFA.meWeight = WEIGHT_NORMAL;
60 rDFA.meItalic = ITALIC_NONE;
63 // heuristics for font weight
64 if (aPSName.Search("extrablack") != STRING_NOTFOUND)
65 rDFA.meWeight = WEIGHT_BLACK;
66 else if (aPSName.Search("black") != STRING_NOTFOUND)
67 rDFA.meWeight = WEIGHT_BLACK;
68 //else if (aPSName.Search("book") != STRING_NOTFOUND)
69 // rDFA.meWeight = WEIGHT_SEMIBOLD;
70 else if( (aPSName.Search("semibold") != STRING_NOTFOUND)
71 || (aPSName.Search("smbd") != STRING_NOTFOUND))
72 rDFA.meWeight = WEIGHT_SEMIBOLD;
73 else if (aPSName.Search("ultrabold") != STRING_NOTFOUND)
74 rDFA.meWeight = WEIGHT_ULTRABOLD;
75 else if (aPSName.Search("extrabold") != STRING_NOTFOUND)
76 rDFA.meWeight = WEIGHT_BLACK;
77 else if( (aPSName.Search("bold") != STRING_NOTFOUND)
78 || (aPSName.Search("-bd") != STRING_NOTFOUND))
79 rDFA.meWeight = WEIGHT_BOLD;
80 else if (aPSName.Search("extralight") != STRING_NOTFOUND)
81 rDFA.meWeight = WEIGHT_ULTRALIGHT;
82 else if (aPSName.Search("ultralight") != STRING_NOTFOUND)
83 rDFA.meWeight = WEIGHT_ULTRALIGHT;
84 else if (aPSName.Search("light") != STRING_NOTFOUND)
85 rDFA.meWeight = WEIGHT_LIGHT;
86 else if (aPSName.Search("thin") != STRING_NOTFOUND)
87 rDFA.meWeight = WEIGHT_THIN;
88 else if (aPSName.Search("-w3") != STRING_NOTFOUND)
89 rDFA.meWeight = WEIGHT_LIGHT;
90 else if (aPSName.Search("-w4") != STRING_NOTFOUND)
91 rDFA.meWeight = WEIGHT_SEMILIGHT;
92 else if (aPSName.Search("-w5") != STRING_NOTFOUND)
93 rDFA.meWeight = WEIGHT_NORMAL;
94 else if (aPSName.Search("-w6") != STRING_NOTFOUND)
95 rDFA.meWeight = WEIGHT_SEMIBOLD;
96 else if (aPSName.Search("-w7") != STRING_NOTFOUND)
97 rDFA.meWeight = WEIGHT_BOLD;
98 else if (aPSName.Search("-w8") != STRING_NOTFOUND)
99 rDFA.meWeight = WEIGHT_ULTRABOLD;
100 else if (aPSName.Search("-w9") != STRING_NOTFOUND)
101 rDFA.meWeight = WEIGHT_BLACK;
103 // heuristics for font slant
104 if( (aPSName.Search("italic") != STRING_NOTFOUND)
105 || (aPSName.Search(" ital") != STRING_NOTFOUND)
106 || (aPSName.Search("cursive") != STRING_NOTFOUND)
107 || (aPSName.Search("-it") != STRING_NOTFOUND)
108 || (aPSName.Search("lightit") != STRING_NOTFOUND)
109 || (aPSName.Search("mediumit") != STRING_NOTFOUND)
110 || (aPSName.Search("boldit") != STRING_NOTFOUND)
111 || (aPSName.Search("cnit") != STRING_NOTFOUND)
112 || (aPSName.Search("bdcn") != STRING_NOTFOUND)
113 || (aPSName.Search("bdit") != STRING_NOTFOUND)
114 || (aPSName.Search("condit") != STRING_NOTFOUND)
115 || (aPSName.Search("bookit") != STRING_NOTFOUND)
116 || (aPSName.Search("blackit") != STRING_NOTFOUND) )
117 rDFA.meItalic = ITALIC_NORMAL;
118 if( (aPSName.Search("oblique") != STRING_NOTFOUND)
119 || (aPSName.Search("inclined") != STRING_NOTFOUND)
120 || (aPSName.Search("slanted") != STRING_NOTFOUND) )
121 rDFA.meItalic = ITALIC_OBLIQUE;
123 // heuristics for font width
124 if( (aPSName.Search("condensed") != STRING_NOTFOUND)
125 || (aPSName.Search("-cond") != STRING_NOTFOUND)
126 || (aPSName.Search("boldcond") != STRING_NOTFOUND)
127 || (aPSName.Search("boldcn") != STRING_NOTFOUND)
128 || (aPSName.Search("cnit") != STRING_NOTFOUND) )
129 rDFA.meWidthType = WIDTH_CONDENSED;
130 else if (aPSName.Search("narrow") != STRING_NOTFOUND)
131 rDFA.meWidthType = WIDTH_SEMI_CONDENSED;
132 else if (aPSName.Search("expanded") != STRING_NOTFOUND)
133 rDFA.meWidthType = WIDTH_EXPANDED;
134 else if (aPSName.Search("wide") != STRING_NOTFOUND)
135 rDFA.meWidthType = WIDTH_EXPANDED;
137 // heuristics for font pitch
138 if( (aPSName.Search("mono") != STRING_NOTFOUND)
139 || (aPSName.Search("courier") != STRING_NOTFOUND)
140 || (aPSName.Search("monaco") != STRING_NOTFOUND)
141 || (aPSName.Search("typewriter") != STRING_NOTFOUND) )
142 rDFA.mePitch = PITCH_FIXED;
144 // heuristics for font family type
145 if( (aPSName.Search("script") != STRING_NOTFOUND)
146 || (aPSName.Search("chancery") != STRING_NOTFOUND)
147 || (aPSName.Search("zapfino") != STRING_NOTFOUND))
148 rDFA.meFamily = FAMILY_SCRIPT;
149 else if( (aPSName.Search("comic") != STRING_NOTFOUND)
150 || (aPSName.Search("outline") != STRING_NOTFOUND)
151 || (aPSName.Search("pinpoint") != STRING_NOTFOUND) )
152 rDFA.meFamily = FAMILY_DECORATIVE;
153 else if( (aPSName.Search("sans") != STRING_NOTFOUND)
154 || (aPSName.Search("arial") != STRING_NOTFOUND) )
155 rDFA.meFamily = FAMILY_SWISS;
156 else if( (aPSName.Search("roman") != STRING_NOTFOUND)
157 || (aPSName.Search("times") != STRING_NOTFOUND) )
158 rDFA.meFamily = FAMILY_ROMAN;
160 // heuristics for codepoint semantic
161 if( (aPSName.Search("symbol") != STRING_NOTFOUND)
162 || (aPSName.Search("dings") != STRING_NOTFOUND)
163 || (aPSName.Search("dingbats") != STRING_NOTFOUND)
164 || (aPSName.Search("ornaments") != STRING_NOTFOUND)
165 || (aPSName.Search("embellishments") != STRING_NOTFOUND) )
166 rDFA.mbSymbolFlag = true;
168 // #i100020# special heuristic for names with single-char styles
169 // NOTE: we are checking name that hasn't been lower-cased
170 if( rPSName.Len() > 3 )
172 int i = rPSName.Len();
173 sal_Unicode c = rPSName.GetChar( --i );
174 if( c == 'C' ) { // "capitals"
175 rDFA.meFamily = FAMILY_DECORATIVE;
176 c = rPSName.GetChar( --i );
178 if( c == 'O' ) { // CFF-based OpenType
179 c = rPSName.GetChar( --i );
181 if( c == 'I' ) { // "italic"
182 rDFA.meItalic = ITALIC_NORMAL;
183 c = rPSName.GetChar( --i );
185 if( c == 'B' ) // "bold"
186 rDFA.meWeight = WEIGHT_BOLD;
187 if( c == 'C' ) // "capitals"
188 rDFA.meFamily = FAMILY_DECORATIVE;
189 // TODO: check that all single-char styles have been resolved?
193 // -----------------------------------------------------------------------
195 static bool GetDevFontAttributes( ATSUFontID nFontID, ImplDevFontAttributes& rDFA )
197 // all ATSU fonts are device fonts that can be directly rotated
198 rDFA.mbOrientation = true;
199 rDFA.mbDevice = true;
200 rDFA.mnQuality = 0;
202 // reset the attributes
203 rDFA.meFamily = FAMILY_DONTKNOW;
204 rDFA.mePitch = PITCH_VARIABLE;
205 rDFA.meWidthType = WIDTH_NORMAL;
206 rDFA.meWeight = WEIGHT_NORMAL;
207 rDFA.meItalic = ITALIC_NONE;
208 rDFA.mbSymbolFlag = false;
210 // all scalable fonts on this platform are subsettable
211 rDFA.mbSubsettable = true;
212 rDFA.mbEmbeddable = false;
213 // TODO: these members are needed only for our X11 platform targets
214 rDFA.meAntiAlias = ANTIALIAS_DONTKNOW;
215 rDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_DONTKNOW;
217 // prepare iterating over all name strings of the font
218 ItemCount nFontNameCount = 0;
219 OSStatus rc = ATSUCountFontNames( nFontID, &nFontNameCount );
220 if( rc != noErr )
221 return false;
222 int nBestNameValue = 0;
223 int nBestStyleValue = 0;
224 FontLanguageCode eBestLangCode = 0;
225 const FontLanguageCode eUILangCode = Application::GetSettings().GetUILanguage();
226 typedef std::vector<char> NameBuffer;
227 NameBuffer aNameBuffer( 256 );
229 // iterate over all available name strings of the font
230 for( ItemCount nNameIndex = 0; nNameIndex < nFontNameCount; ++nNameIndex )
232 ByteCount nNameLength = 0;
234 FontNameCode eFontNameCode;
235 FontPlatformCode eFontNamePlatform;
236 FontScriptCode eFontNameScript;
237 FontLanguageCode eFontNameLanguage;
238 rc = ATSUGetIndFontName( nFontID, nNameIndex, 0, NULL,
239 &nNameLength, &eFontNameCode, &eFontNamePlatform, &eFontNameScript, &eFontNameLanguage );
240 if( rc != noErr )
241 continue;
243 // ignore non-interesting name entries
244 if( (eFontNameCode != kFontFamilyName)
245 && (eFontNameCode != kFontStyleName)
246 && (eFontNameCode != kFontPostscriptName) )
247 continue;
249 // heuristic to find the most common font name
250 // prefering default language names or even better the names matching to the UI language
251 int nNameValue = (eFontNameLanguage==eUILangCode) ? 0 : ((eFontNameLanguage==0) ? -10 : -20);
252 rtl_TextEncoding eEncoding = RTL_TEXTENCODING_UNICODE;
253 const int nPlatformEncoding = ((int)eFontNamePlatform << 8) + (int)eFontNameScript;
254 switch( nPlatformEncoding )
256 case 0x000: nNameValue += 23; break; // Unicode 1.0
257 case 0x001: nNameValue += 24; break; // Unicode 1.1
258 case 0x002: nNameValue += 25; break; // iso10646_1993
259 case 0x003: nNameValue += 26; break; // UCS-2
260 case 0x301: nNameValue += 27; break; // Win UCS-2
261 case 0x004: // UCS-4
262 case 0x30A: nNameValue += 0; // Win-UCS-4
263 eEncoding = RTL_TEXTENCODING_UCS4;
264 break;
265 case 0x100: nNameValue += 21; // Mac Roman
266 eEncoding = RTL_TEXTENCODING_APPLE_ROMAN;
267 break;
268 case 0x300: nNameValue = 0; // Win Symbol encoded name!
269 rDFA.mbSymbolFlag = true; // (often seen for symbol fonts)
270 break;
271 default: nNameValue = 0; // ignore other encodings
272 break;
275 // ignore name entries with no useful encoding
276 if( nNameValue <= 0 )
277 continue;
278 if( nNameLength >= aNameBuffer.size() )
279 continue;
281 // get the encoded name
282 aNameBuffer.reserve( nNameLength+1 ); // extra byte helps for debugging
283 rc = ATSUGetIndFontName( nFontID, nNameIndex, nNameLength, &aNameBuffer[0],
284 &nNameLength, &eFontNameCode, &eFontNamePlatform, &eFontNameScript, &eFontNameLanguage );
285 if( rc != noErr )
286 continue;
288 // convert to unicode name
289 UniString aUtf16Name;
290 if( eEncoding == RTL_TEXTENCODING_UNICODE ) // we are just interested in UTF16 encoded names
291 aUtf16Name = UniString( (const sal_Unicode*)&aNameBuffer[0], nNameLength/2 );
292 else if( eEncoding == RTL_TEXTENCODING_UCS4 )
293 aUtf16Name = UniString(); // TODO
294 else // assume the non-unicode encoded names are byte encoded
295 aUtf16Name = UniString( &aNameBuffer[0], nNameLength, eEncoding );
297 // ignore empty strings
298 if( aUtf16Name.Len() <= 0 )
299 continue;
301 // handle the name depending on its namecode
302 switch( eFontNameCode )
304 case kFontFamilyName:
305 // ignore font names starting with '.'
306 if( aUtf16Name.GetChar(0) == '.' )
307 nNameValue = 0;
308 else if( rDFA.maName.Len() )
310 // even if a family name is not the one we are looking for
311 // it is still useful as a font name alternative
312 if( rDFA.maMapNames.Len() )
313 rDFA.maMapNames += ';';
314 rDFA.maMapNames += (nBestNameValue < nNameValue) ? rDFA.maName : aUtf16Name;
316 if( nBestNameValue < nNameValue )
318 // get the best family name
319 nBestNameValue = nNameValue;
320 eBestLangCode = eFontNameLanguage;
321 rDFA.maName = aUtf16Name;
323 break;
324 case kFontStyleName:
325 // get a style name matching to the family name
326 if( nBestStyleValue < nNameValue )
328 nBestStyleValue = nNameValue;
329 rDFA.maStyleName = aUtf16Name;
331 break;
332 case kFontPostscriptName:
333 // use the postscript name to get some useful info
334 UpdateAttributesFromPSName( aUtf16Name, rDFA );
335 break;
336 default:
337 // TODO: use other name entries too?
338 break;
342 #if 0 // multiple-master fonts are mostly obsolete nowadays
343 // if we still want to support them this should probably be done one frame higher
344 ItemCount nMaxInstances = 0;
345 rc = ATSUCountFontInstances ( nFontID, &nMaxInstances );
346 for( ItemCount nInstanceIndex = 0; nInstanceIndex < nMaxInstances; ++nInstanceIndex )
348 ItemCount nMaxVariations = 0;
349 rc = ATSUGetFontInstance( nFontID, nInstanceIndex, 0, NULL, NULL, &nMaxVariations );
350 if( (rc == noErr) && (nMaxVariations > 0) )
352 fprintf(stderr,"\tnMaxVariations=%d\n",(int)nMaxVariations);
353 typedef ::std::vector<ATSUFontVariationAxis> VariationAxisVector;
354 typedef ::std::vector<ATSUFontVariationValue> VariationValueVector;
355 VariationAxisVector aVariationAxes( nMaxVariations );
356 VariationValueVector aVariationValues( nMaxVariations );
357 ItemCount nVariationCount = 0;
358 rc = ATSUGetFontInstance ( nFontID, nInstanceIndex, nMaxVariations,
359 &aVariationAxes[0], &aVariationValues[0], &nVariationCount );
360 fprintf(stderr,"\tnVariationCount=%d\n",(int)nVariationCount);
361 for( ItemCount nVariationIndex = 0; nVariationIndex < nMaxVariations; ++nVariationIndex )
363 const char* pTag = (const char*)&aVariationAxes[nVariationIndex];
364 fprintf(stderr,"\tvariation[%d] \'%c%c%c%c\' is %d\n", (int)nVariationIndex,
365 pTag[3],pTag[2],pTag[1],pTag[0], (int)aVariationValues[nVariationIndex]);
369 #endif
371 #if 0 // selecting non-defaulted font features is not enabled yet
372 ByteString aFName( rDFA.maName, RTL_TEXTENCODING_UTF8 );
373 ByteString aSName( rDFA.maStyleName, RTL_TEXTENCODING_UTF8 );
374 ItemCount nMaxFeatures = 0;
375 rc = ATSUCountFontFeatureTypes( nFontID, &nMaxFeatures );
376 fprintf(stderr,"Font \"%s\" \"%s\" has %d features\n",aFName.GetBuffer(),aSName.GetBuffer(),rc);
377 if( (rc == noErr) && (nMaxFeatures > 0) )
379 typedef std::vector<ATSUFontFeatureType> FeatureVector;
380 FeatureVector aFeatureVector( nMaxFeatures );
381 ItemCount nFeatureCount = 0;
382 rc = ATSUGetFontFeatureTypes( nFontID, nMaxFeatures, &aFeatureVector[0], &nFeatureCount );
383 fprintf(stderr,"nFeatureCount=%d\n",(int)nFeatureCount);
384 for( ItemCount nFeatureIndex = 0; nFeatureIndex < nFeatureCount; ++nFeatureIndex )
386 ItemCount nMaxSelectors = 0;
387 rc = ATSUCountFontFeatureSelectors( nFontID, aFeatureVector[nFeatureIndex], &nMaxSelectors );
388 fprintf(stderr,"\tFeature[%d] = %d has %d selectors\n",
389 (int)nFeatureIndex, (int)aFeatureVector[nFeatureIndex], (int)nMaxSelectors );
390 typedef std::vector<ATSUFontFeatureSelector> SelectorVector;
391 SelectorVector aSelectorVector( nMaxSelectors );
392 typedef std::vector<MacOSBoolean> BooleanVector;
393 BooleanVector aEnabledVector( nMaxSelectors );
394 BooleanVector aExclusiveVector( nMaxSelectors );
395 ItemCount nSelectorCount = 0;
396 rc = ATSUGetFontFeatureSelectors ( nFontID, aFeatureVector[nFeatureIndex], nMaxSelectors,
397 &aSelectorVector[0], &aEnabledVector[0], &nSelectorCount, &aExclusiveVector[0]);
398 for( ItemCount nSelectorIndex = 0; nSelectorIndex < nSelectorCount; ++nSelectorIndex )
400 FontNameCode eFontNameCode;
401 rc = ATSUGetFontFeatureNameCode( nFontID, aFeatureVector[nFeatureIndex],
402 aSelectorVector[nSelectorIndex], &eFontNameCode );
403 fprintf(stderr,"\t\tselector[%d] n=%d e=%d, x=%d\n",
404 (int)nSelectorIndex, (int)eFontNameCode,
405 aEnabledVector[nSelectorIndex], aExclusiveVector[nSelectorIndex] );
409 #endif
411 bool bRet = (rDFA.maName.Len() > 0);
412 return bRet;
415 // =======================================================================
417 SystemFontList::SystemFontList()
419 // count available system fonts
420 ItemCount nATSUICompatibleFontsAvailable = 0;
421 if( ATSUFontCount(&nATSUICompatibleFontsAvailable) != noErr )
422 return;
423 if( nATSUICompatibleFontsAvailable <= 0 )
424 return;
426 // enumerate available system fonts
427 typedef std::vector<ATSUFontID> AtsFontIDVector;
428 AtsFontIDVector aFontIDVector( nATSUICompatibleFontsAvailable );
429 ItemCount nFontItemsCount = 0;
430 if( ATSUGetFontIDs( &aFontIDVector[0], aFontIDVector.capacity(), &nFontItemsCount ) != noErr )
431 return;
433 BOOST_ASSERT(nATSUICompatibleFontsAvailable == nFontItemsCount && "Strange I would expect them to be equal");
435 // prepare use of the available fonts
436 AtsFontIDVector::const_iterator it = aFontIDVector.begin();
437 for(; it != aFontIDVector.end(); ++it )
439 const ATSUFontID nFontID = *it;
440 ImplDevFontAttributes aDevFontAttr;
441 if( !GetDevFontAttributes( nFontID, aDevFontAttr ) )
442 continue;
443 ImplMacFontData* pFontData = new ImplMacFontData( aDevFontAttr, nFontID );
444 maFontContainer[ nFontID ] = pFontData;
447 InitGlyphFallbacks();
450 // -----------------------------------------------------------------------
452 SystemFontList::~SystemFontList()
454 MacFontContainer::const_iterator it = maFontContainer.begin();
455 for(; it != maFontContainer.end(); ++it )
456 delete (*it).second;
457 maFontContainer.clear();
459 ATSUDisposeFontFallbacks( maFontFallbacks );
462 // -----------------------------------------------------------------------
464 void SystemFontList::AnnounceFonts( ImplDevFontList& rFontList ) const
466 MacFontContainer::const_iterator it = maFontContainer.begin();
467 for(; it != maFontContainer.end(); ++it )
468 rFontList.Add( (*it).second->Clone() );
471 // -----------------------------------------------------------------------
473 // not all fonts are suitable for glyph fallback => sort them
474 struct GfbCompare{ bool operator()(const ImplMacFontData*, const ImplMacFontData*); };
476 inline bool GfbCompare::operator()( const ImplMacFontData* pA, const ImplMacFontData* pB )
478 // use symbol fonts only as last resort
479 bool bPreferA = !pA->IsSymbolFont();
480 bool bPreferB = !pB->IsSymbolFont();
481 if( bPreferA != bPreferB )
482 return bPreferA;
483 // prefer scalable fonts
484 bPreferA = pA->IsScalable();
485 bPreferB = pB->IsScalable();
486 if( bPreferA != bPreferB )
487 return bPreferA;
488 // prefer non-slanted fonts
489 bPreferA = (pA->GetSlant() == ITALIC_NONE);
490 bPreferB = (pB->GetSlant() == ITALIC_NONE);
491 if( bPreferA != bPreferB )
492 return bPreferA;
493 // prefer normal weight fonts
494 bPreferA = (pA->GetWeight() == WEIGHT_NORMAL);
495 bPreferB = (pB->GetWeight() == WEIGHT_NORMAL);
496 if( bPreferA != bPreferB )
497 return bPreferA;
498 // prefer normal width fonts
499 bPreferA = (pA->GetWidthType() == WIDTH_NORMAL);
500 bPreferB = (pB->GetWidthType() == WIDTH_NORMAL);
501 if( bPreferA != bPreferB )
502 return bPreferA;
503 return false;
506 void SystemFontList::InitGlyphFallbacks()
508 // sort fonts for "glyph fallback"
509 typedef std::multiset<const ImplMacFontData*,GfbCompare> FallbackSet;
510 FallbackSet aFallbackSet;
511 MacFontContainer::const_iterator it = maFontContainer.begin();
512 for(; it != maFontContainer.end(); ++it )
514 const ImplMacFontData* pIFD = (*it).second;
515 // TODO: subsettable/embeddable glyph fallback only for PDF export?
516 if( pIFD->IsSubsettable() || pIFD->IsEmbeddable() )
517 aFallbackSet.insert( pIFD );
520 // tell ATSU about font preferences for "glyph fallback"
521 typedef std::vector<ATSUFontID> AtsFontIDVector;
522 AtsFontIDVector aFallbackVector;
523 aFallbackVector.reserve( maFontContainer.size() );
524 FallbackSet::const_iterator itFData = aFallbackSet.begin();
525 for(; itFData != aFallbackSet.end(); ++itFData )
527 const ImplMacFontData* pFontData = (*itFData);
528 ATSUFontID nFontID = (ATSUFontID)pFontData->GetFontId();
529 aFallbackVector.push_back( nFontID );
532 ATSUCreateFontFallbacks( &maFontFallbacks );
533 ATSUSetObjFontFallbacks( maFontFallbacks,
534 aFallbackVector.size(), &aFallbackVector[0], kATSUSequentialFallbacksPreferred );
537 // -----------------------------------------------------------------------
539 ImplMacFontData* SystemFontList::GetFontDataFromId( ATSUFontID nFontId ) const
541 MacFontContainer::const_iterator it = maFontContainer.find( nFontId );
542 if( it == maFontContainer.end() )
543 return NULL;
544 return (*it).second;
547 // -----------------------------------------------------------------------