]> git.saurik.com Git - wxWidgets.git/blame - src/osx/carbon/font.cpp
Fix history in wxWebViewIE when using a custom file scheme.
[wxWidgets.git] / src / osx / carbon / font.cpp
CommitLineData
489468fe 1/////////////////////////////////////////////////////////////////////////////
524c47aa 2// Name: src/osx/carbon/font.cpp
489468fe
SC
3// Purpose: wxFont class
4// Author: Stefan Csomor
5// Modified by:
6// Created: 1998-01-01
7// RCS-ID: $Id$
8// Copyright: (c) Stefan Csomor
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#include "wx/wxprec.h"
13
14#include "wx/font.h"
15
16#ifndef WX_PRECOMP
17 #include "wx/string.h"
18 #include "wx/utils.h"
19 #include "wx/intl.h"
20 #include "wx/gdicmn.h"
21 #include "wx/log.h"
22#endif
23
24#include "wx/fontutil.h"
25#include "wx/graphics.h"
26#include "wx/settings.h"
f1c40652 27#include "wx/tokenzr.h"
489468fe 28
b2680ced 29#include "wx/osx/private.h"
29e32b7f 30
489468fe
SC
31#include <map>
32#include <string>
33
489468fe
SC
34class WXDLLEXPORT wxFontRefData: public wxGDIRefData
35{
36public:
489468fe 37
f1c40652 38 wxFontRefData()
489468fe 39 {
f1c40652
SC
40 Init();
41 m_info.Init(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL,
42 false, wxEmptyString, wxFONTENCODING_DEFAULT);
489468fe
SC
43 }
44
f1c40652 45 wxFontRefData(const wxFontRefData& data);
03647350 46
f1c40652 47 wxFontRefData( const wxNativeFontInfo& info ) : m_info(info)
489468fe 48 {
f1c40652 49 Init();
489468fe
SC
50 }
51
f1c40652 52 wxFontRefData(wxOSXSystemFont font, int size);
03647350 53
292e5e1f 54#if wxOSX_USE_CORE_TEXT
489468fe
SC
55 wxFontRefData( wxUint32 coreTextFontType );
56 wxFontRefData( CTFontRef font );
57 wxFontRefData( CTFontDescriptorRef fontdescriptor, int size );
58#endif
59
60 virtual ~wxFontRefData();
61
489468fe
SC
62 void SetPointSize( int size )
63 {
f1c40652
SC
64 if( GetPointSize() != size )
65 {
66 m_info.SetPointSize(size);
67 Free();
68 }
489468fe
SC
69 }
70
f1c40652 71 int GetPointSize() const { return m_info.GetPointSize(); }
489468fe 72
0c14b6c3 73 void SetFamily( wxFontFamily family )
489468fe 74 {
f1c40652
SC
75 if ( m_info.m_family != family )
76 {
77 m_info.SetFamily( family );
78 Free();
79 }
489468fe
SC
80 }
81
f1c40652 82 wxFontFamily GetFamily() const { return m_info.GetFamily(); }
489468fe 83
0c14b6c3 84 void SetStyle( wxFontStyle style )
489468fe 85 {
f1c40652
SC
86 if ( m_info.m_style != style )
87 {
88 m_info.SetStyle( style );
89 Free();
90 }
489468fe
SC
91 }
92
93
f1c40652 94 wxFontStyle GetStyle() const { return m_info.GetStyle(); }
489468fe 95
0c14b6c3 96 void SetWeight( wxFontWeight weight )
489468fe 97 {
f1c40652
SC
98 if ( m_info.m_weight != weight )
99 {
100 m_info.SetWeight( weight );
101 Free();
102 }
489468fe
SC
103 }
104
105
f1c40652 106 wxFontWeight GetWeight() const { return m_info.GetWeight(); }
489468fe
SC
107
108 void SetUnderlined( bool u )
109 {
f1c40652
SC
110 if ( m_info.m_underlined != u )
111 {
112 m_info.SetUnderlined( u );
113 Free();
114 }
489468fe
SC
115 }
116
f1c40652 117 bool GetUnderlined() const { return m_info.GetUnderlined(); }
489468fe
SC
118
119 void SetFaceName( const wxString& facename )
120 {
f1c40652
SC
121 if ( m_info.m_faceName != facename )
122 {
123 m_info.SetFaceName( facename );
124 Free();
125 }
489468fe
SC
126 }
127
f1c40652 128 wxString GetFaceName() const { return m_info.GetFaceName(); }
489468fe
SC
129
130 void SetEncoding( wxFontEncoding encoding )
131 {
f1c40652
SC
132 if ( m_info.m_encoding != encoding )
133 {
134 m_info.SetEncoding( encoding );
135 Free();
136 }
489468fe
SC
137 }
138
f1c40652 139 wxFontEncoding GetEncoding() const { return m_info.GetEncoding(); }
489468fe 140
f1c40652 141 void Free();
489468fe
SC
142
143 void MacFindFont();
144
145protected:
146 // common part of all ctors
f1c40652 147 void Init();
292e5e1f 148#if wxOSX_USE_CORE_TEXT
f1c40652 149 // void Init( CTFontRef font );
489468fe 150#endif
489468fe 151public:
f1c40652
SC
152 bool m_fontValid;
153#if wxOSX_USE_CARBON && wxOSX_USE_ATSU_TEXT
b3b17ee7 154 // for true theming support we must store the correct font
489468fe
SC
155 // information here, as this speeds up and optimizes rendering
156 ThemeFontID m_macThemeFontID ;
157#endif
292e5e1f 158#if wxOSX_USE_CORE_TEXT
489468fe 159 wxCFRef<CTFontRef> m_ctFont;
489468fe 160#endif
beb2638a 161#if wxOSX_USE_ATSU_TEXT
03c28161
SC
162 void CreateATSUFont();
163
489468fe 164 ATSUStyle m_macATSUStyle ;
f1c40652 165#endif
9445de1e 166 wxCFRef<CGFontRef> m_cgFont;
f1c40652
SC
167#if wxOSX_USE_COCOA
168 WX_NSFont m_nsFont;
169#endif
170#if wxOSX_USE_IPHONE
171 WX_UIFont m_uiFont;
489468fe
SC
172#endif
173 wxNativeFontInfo m_info;
174};
175
176#define M_FONTDATA ((wxFontRefData*)m_refData)
177
ea2807a4 178wxFontRefData::wxFontRefData(const wxFontRefData& data) : wxGDIRefData()
f1c40652
SC
179{
180 Init();
181 m_info = data.m_info;
f1c40652
SC
182 m_fontValid = data.m_fontValid;
183#if wxOSX_USE_CARBON && wxOSX_USE_ATSU_TEXT
184 m_macThemeFontID = data.m_macThemeFontID;
185#endif
186#if wxOSX_USE_CORE_TEXT
187 m_ctFont = data.m_ctFont;
03647350 188#endif
9445de1e 189 m_cgFont = data.m_cgFont;
beb2638a 190#if wxOSX_USE_ATSU_TEXT
f1c40652
SC
191 if ( data.m_macATSUStyle != NULL )
192 {
193 ATSUCreateStyle(&m_macATSUStyle) ;
194 ATSUCopyAttributes(data.m_macATSUStyle, m_macATSUStyle);
195 }
196#endif
197#if wxOSX_USE_COCOA
198 m_nsFont = (NSFont*) wxMacCocoaRetain(data.m_nsFont);
199#endif
200#if wxOSX_USE_IPHONE
b4ff8b3e 201 m_uiFont = (UIFont*) wxMacCocoaRetain(data.m_uiFont);
f1c40652 202#endif
03647350 203
f1c40652 204}
489468fe
SC
205
206// ============================================================================
207// implementation
208// ============================================================================
209
210// ----------------------------------------------------------------------------
211// wxFontRefData
212// ----------------------------------------------------------------------------
213
f1c40652 214void wxFontRefData::Init()
489468fe 215{
f1c40652 216#if wxOSX_USE_CARBON && wxOSX_USE_ATSU_TEXT
489468fe
SC
217 m_macThemeFontID = kThemeCurrentPortFont ;
218#endif
beb2638a 219#if wxOSX_USE_ATSU_TEXT
489468fe
SC
220 m_macATSUStyle = NULL ;
221#endif
f1c40652
SC
222#if wxOSX_USE_COCOA
223 m_nsFont = NULL;
224#endif
225#if wxOSX_USE_IPHONE
226 m_uiFont = NULL;
227#endif
228 m_fontValid = false;
489468fe
SC
229}
230
231wxFontRefData::~wxFontRefData()
232{
f1c40652 233 Free();
489468fe
SC
234}
235
f1c40652 236void wxFontRefData::Free()
489468fe 237{
292e5e1f 238#if wxOSX_USE_CORE_TEXT
489468fe 239 m_ctFont.reset();
489468fe 240#endif
9445de1e 241 m_cgFont.reset();
beb2638a 242#if wxOSX_USE_ATSU_TEXT
9581362b
SC
243#if wxOSX_USE_CARBON
244 m_macThemeFontID = kThemeCurrentPortFont ;
245#endif
489468fe
SC
246 if ( m_macATSUStyle )
247 {
248 ::ATSUDisposeStyle((ATSUStyle)m_macATSUStyle);
249 m_macATSUStyle = NULL ;
250 }
251#endif
f1c40652
SC
252#if wxOSX_USE_COCOA
253 if (m_nsFont != NULL)
254 {
255 wxMacCocoaRelease(m_nsFont);
256 m_nsFont = NULL;
489468fe 257 }
f1c40652
SC
258#endif
259#if wxOSX_USE_IPHONE
260 if (m_uiFont != NULL)
489468fe 261 {
f1c40652
SC
262 wxMacCocoaRelease(m_uiFont);
263 m_uiFont = NULL;
489468fe 264 }
f1c40652
SC
265#endif
266 m_fontValid = false;
489468fe
SC
267}
268
f1c40652 269wxFontRefData::wxFontRefData(wxOSXSystemFont font, int size)
489468fe 270{
f1c40652
SC
271 wxASSERT( font != wxOSX_SYSTEM_FONT_NONE );
272 Init();
03647350 273
f1c40652
SC
274#if wxOSX_USE_CORE_TEXT
275 if ( UMAGetSystemVersion() >= 0x1050 )
489468fe 276 {
de0d2095 277 CTFontUIFontType uifont = kCTFontSystemFontType;
f1c40652 278 switch( font )
489468fe 279 {
f1c40652
SC
280 case wxOSX_SYSTEM_FONT_NORMAL:
281 uifont = kCTFontSystemFontType;
282 break;
283 case wxOSX_SYSTEM_FONT_BOLD:
284 uifont = kCTFontEmphasizedSystemFontType;
285 break;
286 case wxOSX_SYSTEM_FONT_SMALL:
287 uifont = kCTFontSmallSystemFontType;
288 break;
289 case wxOSX_SYSTEM_FONT_SMALL_BOLD:
290 uifont = kCTFontSmallEmphasizedSystemFontType;
291 break;
292 case wxOSX_SYSTEM_FONT_MINI:
293 uifont = kCTFontMiniSystemFontType;
294 break;
295 case wxOSX_SYSTEM_FONT_MINI_BOLD:
296 uifont = kCTFontMiniEmphasizedSystemFontType;
297 break;
298 case wxOSX_SYSTEM_FONT_LABELS:
299 uifont = kCTFontLabelFontType;
300 break;
301 case wxOSX_SYSTEM_FONT_VIEWS:
302 uifont = kCTFontViewsFontType;
303 break;
304 default:
305 break;
489468fe 306 }
f1c40652
SC
307 m_ctFont.reset(CTFontCreateUIFontForLanguage( uifont, (CGFloat) size, NULL ));
308 wxCFRef<CTFontDescriptorRef> descr;
309 descr.reset( CTFontCopyFontDescriptor( m_ctFont ) );
310 m_info.Init(descr);
311 }
312#endif
313#if wxOSX_USE_ATSU_TEXT
314 {
9a672c75
SC
315#if !wxOSX_USE_CARBON
316 // not needed outside
de0d2095 317 ThemeFontID m_macThemeFontID = kThemeSystemFont;
9a672c75 318#endif
f1c40652
SC
319 switch( font )
320 {
321 case wxOSX_SYSTEM_FONT_NORMAL:
322 m_macThemeFontID = kThemeSystemFont;
323 break;
324 case wxOSX_SYSTEM_FONT_BOLD:
325 m_macThemeFontID = kThemeEmphasizedSystemFont;
326 break;
327 case wxOSX_SYSTEM_FONT_SMALL:
328 m_macThemeFontID = kThemeSmallSystemFont;
329 break;
330 case wxOSX_SYSTEM_FONT_SMALL_BOLD:
331 m_macThemeFontID = kThemeSmallEmphasizedSystemFont;
332 break;
333 case wxOSX_SYSTEM_FONT_MINI:
334 m_macThemeFontID = kThemeMiniSystemFont;
335 break;
336 case wxOSX_SYSTEM_FONT_MINI_BOLD:
b3b17ee7 337 // bold not available under theming
f1c40652
SC
338 m_macThemeFontID = kThemeMiniSystemFont;
339 break;
340 case wxOSX_SYSTEM_FONT_LABELS:
341 m_macThemeFontID = kThemeLabelFont;
342 break;
343 case wxOSX_SYSTEM_FONT_VIEWS:
344 m_macThemeFontID = kThemeViewsFont;
345 break;
346 default:
03647350 347 break;
f1c40652
SC
348 }
349 if ( m_info.m_faceName.empty() )
350 {
351 Style style ;
352 FMFontSize fontSize;
353 Str255 qdFontName ;
03647350 354
f1c40652
SC
355 GetThemeFont( m_macThemeFontID, GetApplicationScript(), qdFontName, &fontSize, &style );
356 if ( size != 0 )
357 fontSize = size;
358
359 wxFontStyle fontstyle = wxFONTSTYLE_NORMAL;
360 wxFontWeight fontweight = wxFONTWEIGHT_NORMAL;
361 bool underlined = false;
03647350 362
f1c40652
SC
363 if ( style & bold )
364 fontweight = wxFONTWEIGHT_BOLD ;
365 else
366 fontweight = wxFONTWEIGHT_NORMAL ;
367 if ( style & italic )
368 fontstyle = wxFONTSTYLE_ITALIC ;
369 if ( style & underline )
370 underlined = true ;
03647350 371
2ff0354a 372 m_info.Init(fontSize,wxFONTFAMILY_DEFAULT,fontstyle,fontweight,underlined,
f1c40652
SC
373 wxMacMakeStringFromPascal( qdFontName ), wxFONTENCODING_DEFAULT);
374 }
489468fe 375 }
489468fe 376#endif
f1c40652 377#if wxOSX_USE_COCOA
aa6208d9 378 m_nsFont = wxFont::OSXCreateNSFont( font, &m_info );
f1c40652
SC
379#endif
380#if wxOSX_USE_IPHONE
aa6208d9 381 m_uiFont = wxFont::OSXCreateUIFont( font, &m_info );
f1c40652 382#endif
03c28161
SC
383 m_info.EnsureValid();
384#if wxOSX_USE_ATSU_TEXT
385 CreateATSUFont();
386#endif
387
388 m_fontValid = true;
f1c40652 389}
489468fe 390
03c28161
SC
391#if wxOSX_USE_ATSU_TEXT
392void wxFontRefData::CreateATSUFont()
393{
394 // we try to get as much styles as possible into ATSU
395
396 OSStatus status = ::ATSUCreateStyle(&m_macATSUStyle);
397 wxASSERT_MSG( status == noErr , wxT("couldn't create ATSU style") );
398
399 ATSUAttributeTag atsuTags[] =
400 {
401 kATSUFontTag ,
402 kATSUSizeTag ,
403 kATSUVerticalCharacterTag,
404 kATSUQDBoldfaceTag ,
405 kATSUQDItalicTag ,
406 kATSUQDUnderlineTag ,
407 kATSUQDCondensedTag ,
408 kATSUQDExtendedTag ,
409 };
410 ByteCount atsuSizes[WXSIZEOF(atsuTags)] =
411 {
412 sizeof( ATSUFontID ) ,
413 sizeof( Fixed ) ,
414 sizeof( ATSUVerticalCharacterType),
415 sizeof( Boolean ) ,
416 sizeof( Boolean ) ,
417 sizeof( Boolean ) ,
418 sizeof( Boolean ) ,
419 sizeof( Boolean ) ,
420 };
421
422 Boolean kTrue = true ;
423 Boolean kFalse = false ;
424
425 Fixed atsuSize = IntToFixed( m_info.m_pointSize );
426 ATSUVerticalCharacterType kHorizontal = kATSUStronglyHorizontal;
427 FMFontStyle addQDStyle = m_info.m_atsuAdditionalQDStyles;
428 ATSUAttributeValuePtr atsuValues[WXSIZEOF(atsuTags)] =
429 {
430 &m_info.m_atsuFontID ,
431 &atsuSize ,
432 &kHorizontal,
433 (addQDStyle & bold) ? &kTrue : &kFalse ,
434 (addQDStyle & italic) ? &kTrue : &kFalse ,
435 (addQDStyle & underline) ? &kTrue : &kFalse ,
436 (addQDStyle & condense) ? &kTrue : &kFalse ,
437 (addQDStyle & extend) ? &kTrue : &kFalse ,
438 };
439
440 status = ::ATSUSetAttributes(
441 (ATSUStyle)m_macATSUStyle,
442 WXSIZEOF(atsuTags),
443 atsuTags, atsuSizes, atsuValues);
444
445 wxASSERT_MSG( status == noErr , wxString::Format(wxT("couldn't modify ATSU style. Status was %d"), (int) status).c_str() );
446
447 if ( m_cgFont.get() == NULL )
448 {
449 ATSFontRef fontRef = FMGetATSFontRefFromFont(m_info.m_atsuFontID);
450 m_cgFont.reset( CGFontCreateWithPlatformFont( &fontRef ) );
451 }
452}
453#endif
454
d0a7d7b1
SC
455static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
456static const CGAffineTransform kSlantTransform = CGAffineTransformMake( 1, 0, tan(DegToRad(11)), 1, 0, 0 );
457
489468fe
SC
458void wxFontRefData::MacFindFont()
459{
f1c40652
SC
460 if ( m_fontValid )
461 return;
03647350 462
72912228
JS
463 wxCHECK_RET( m_info.m_pointSize > 0, wxT("Point size should not be zero.") );
464
f1c40652 465 m_info.EnsureValid();
03647350 466
292e5e1f 467#if wxOSX_USE_CORE_TEXT
489468fe
SC
468 if ( UMAGetSystemVersion() >= 0x1050 )
469 {
f1c40652 470 CTFontSymbolicTraits traits = 0;
0c14b6c3 471
f1c40652
SC
472 if (m_info.m_weight == wxFONTWEIGHT_BOLD)
473 traits |= kCTFontBoldTrait;
474 if (m_info.m_style == wxFONTSTYLE_ITALIC || m_info.m_style == wxFONTSTYLE_SLANT)
475 traits |= kCTFontItalicTrait;
489468fe 476
f1c40652 477 // use font caching
c2eb8938 478 wxString lookupnameWithSize = wxString::Format( "%s_%u_%d", m_info.m_faceName, traits, m_info.m_pointSize );
489468fe 479
f1c40652
SC
480 static std::map< std::wstring , wxCFRef< CTFontRef > > fontcache ;
481 m_ctFont = fontcache[ std::wstring(lookupnameWithSize.wc_str()) ];
482 if ( !m_ctFont )
489468fe 483 {
03c28161 484 m_ctFont.reset(CTFontCreateWithName( wxCFStringRef(m_info.m_faceName), m_info.m_pointSize , NULL ));
d0a7d7b1 485 if ( m_ctFont.get() == NULL )
03c28161 486 {
d0a7d7b1
SC
487 // TODO try fallbacks according to font type
488 m_ctFont.reset(CTFontCreateUIFontForLanguage( kCTFontSystemFontType, m_info.m_pointSize , NULL ));
489 }
490 else
491 {
492 if ( traits != 0 )
493 {
494 // attempt native font variant, if not available, fallback to italic emulation mode and remove bold
495 CTFontRef fontWithTraits = CTFontCreateCopyWithSymbolicTraits( m_ctFont, 0, NULL, traits, traits );
496 if ( fontWithTraits == NULL )
497 {
498 CTFontSymbolicTraits remainingTraits = traits;
499 const CGAffineTransform* remainingTransform = NULL;
ce00f59b 500
d0a7d7b1
SC
501 if( remainingTraits & kCTFontItalicTrait )
502 {
503 remainingTraits &= ~kCTFontItalicTrait;
504 remainingTransform = &kSlantTransform;
505 if ( remainingTraits & kCTFontBoldTrait )
506 {
507 // first try an emulated oblique with an existing bold font
508 fontWithTraits = CTFontCreateCopyWithSymbolicTraits( m_ctFont, 0, remainingTransform, remainingTraits, remainingTraits );
509 if ( fontWithTraits == NULL )
510 {
511 // give in on the bold, try native oblique
512 fontWithTraits = CTFontCreateCopyWithSymbolicTraits( m_ctFont, 0, NULL, kCTFontItalicTrait, kCTFontItalicTrait );
513 }
514 }
515 }
ce00f59b 516
d0a7d7b1
SC
517 if ( fontWithTraits == NULL )
518 {
519 fontWithTraits = CTFontCreateWithName( wxCFStringRef(m_info.m_faceName), m_info.m_pointSize, remainingTransform );
520 }
ce00f59b 521
d0a7d7b1
SC
522 }
523 if ( fontWithTraits != NULL )
524 m_ctFont.reset(fontWithTraits);
525 }
03c28161 526 }
489468fe 527 }
ce00f59b 528
9445de1e 529 m_cgFont.reset(CTFontCopyGraphicsFont(m_ctFont, NULL));
489468fe 530 }
f1c40652 531
489468fe 532#endif
292e5e1f 533#if wxOSX_USE_ATSU_TEXT
03c28161 534 CreateATSUFont();
489468fe 535#endif
f1c40652 536#if wxOSX_USE_COCOA
aa6208d9 537 m_nsFont = wxFont::OSXCreateNSFont( &m_info );
f1c40652
SC
538#endif
539#if wxOSX_USE_IPHONE
aa6208d9 540 m_uiFont = wxFont::OSXCreateUIFont( &m_info );
f1c40652
SC
541#endif
542 m_fontValid = true;
489468fe
SC
543}
544
545// ----------------------------------------------------------------------------
546// wxFont
547// ----------------------------------------------------------------------------
548
549bool wxFont::Create(const wxNativeFontInfo& info)
550{
f1c40652 551 UnRef();
03647350 552
f1c40652
SC
553 m_refData = new wxFontRefData( info );
554 RealizeResource();
03647350 555
f1c40652 556 return true;
489468fe
SC
557}
558
7eb8aeb8
SC
559wxFont::wxFont(wxOSXSystemFont font)
560{
561 m_refData = new wxFontRefData( font, 0 );
562}
563
489468fe
SC
564wxFont::wxFont(const wxString& fontdesc)
565{
566 wxNativeFontInfo info;
567 if ( info.FromString(fontdesc) )
568 (void)Create(info);
569}
570
571bool wxFont::Create(int pointSize,
0c14b6c3
FM
572 wxFontFamily family,
573 wxFontStyle style,
574 wxFontWeight weight,
575 bool underlined,
f1c40652 576 const wxString& faceNameParam,
0c14b6c3 577 wxFontEncoding encoding)
489468fe
SC
578{
579 UnRef();
03647350 580
f1c40652 581 wxString faceName = faceNameParam;
489468fe 582
f1c40652
SC
583 if ( faceName.empty() )
584 {
585 switch ( family )
586 {
587 case wxFONTFAMILY_DEFAULT :
588 faceName = wxT("Lucida Grande");
589 break;
03647350 590
f1c40652
SC
591 case wxFONTFAMILY_SCRIPT :
592 case wxFONTFAMILY_ROMAN :
593 case wxFONTFAMILY_DECORATIVE :
594 faceName = wxT("Times");
595 break ;
596
597 case wxFONTFAMILY_SWISS :
598 faceName = wxT("Helvetica");
599 break ;
600
601 case wxFONTFAMILY_MODERN :
602 case wxFONTFAMILY_TELETYPE:
603 faceName = wxT("Courier");
604 break ;
605
606 default:
607 faceName = wxT("Times");
608 break ;
609 }
610 }
03647350 611
f1c40652 612 wxNativeFontInfo info;
03647350 613
f1c40652 614 info.Init(pointSize, family, style, weight,
489468fe
SC
615 underlined, faceName, encoding);
616
f1c40652 617 m_refData = new wxFontRefData(info);
489468fe
SC
618
619 return true;
620}
621
f1c40652 622wxFont::~wxFont()
489468fe 623{
f1c40652 624}
489468fe 625
c443ff6f
SC
626void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo& info)
627{
628 UnRef();
03647350 629
c443ff6f
SC
630 m_refData = new wxFontRefData( info);
631}
632
633
f1c40652
SC
634bool wxFont::RealizeResource()
635{
636 M_FONTDATA->MacFindFont();
489468fe
SC
637
638 return true;
639}
640
f1c40652
SC
641void wxFont::SetEncoding(wxFontEncoding encoding)
642{
643 AllocExclusive();
489468fe
SC
644
645 M_FONTDATA->SetEncoding( encoding );
489468fe
SC
646}
647
648wxGDIRefData *wxFont::CreateGDIRefData() const
649{
650 return new wxFontRefData;
651}
652
653wxGDIRefData *wxFont::CloneGDIRefData(const wxGDIRefData *data) const
654{
5c33522f 655 return new wxFontRefData(*static_cast<const wxFontRefData *>(data));
489468fe
SC
656}
657
658void wxFont::SetPointSize(int pointSize)
659{
660 if ( M_FONTDATA->GetPointSize() == pointSize )
661 return;
662
f1c40652 663 AllocExclusive();
489468fe
SC
664
665 M_FONTDATA->SetPointSize( pointSize );
489468fe
SC
666}
667
0c14b6c3 668void wxFont::SetFamily(wxFontFamily family)
489468fe 669{
f1c40652 670 AllocExclusive();
489468fe
SC
671
672 M_FONTDATA->SetFamily( family );
489468fe
SC
673}
674
0c14b6c3 675void wxFont::SetStyle(wxFontStyle style)
489468fe 676{
f1c40652 677 AllocExclusive();
489468fe
SC
678
679 M_FONTDATA->SetStyle( style );
489468fe
SC
680}
681
0c14b6c3 682void wxFont::SetWeight(wxFontWeight weight)
489468fe 683{
f1c40652 684 AllocExclusive();
489468fe
SC
685
686 M_FONTDATA->SetWeight( weight );
489468fe
SC
687}
688
689bool wxFont::SetFaceName(const wxString& faceName)
690{
f1c40652 691 AllocExclusive();
489468fe
SC
692
693 M_FONTDATA->SetFaceName( faceName );
694
489468fe
SC
695 return wxFontBase::SetFaceName(faceName);
696}
697
698void wxFont::SetUnderlined(bool underlined)
699{
f1c40652 700 AllocExclusive();
489468fe
SC
701
702 M_FONTDATA->SetUnderlined( underlined );
489468fe
SC
703}
704
489468fe
SC
705// ----------------------------------------------------------------------------
706// accessors
707// ----------------------------------------------------------------------------
708
709// TODO: insert checks everywhere for M_FONTDATA == NULL!
710
711int wxFont::GetPointSize() const
712{
713 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
714
715 return M_FONTDATA->GetPointSize();
716}
717
718wxSize wxFont::GetPixelSize() const
719{
720#if wxUSE_GRAPHICS_CONTEXT
721 // TODO: consider caching the value
722 wxGraphicsContext* dc = wxGraphicsContext::CreateFromNative((CGContextRef) NULL);
723 dc->SetFont(*(wxFont *)this,*wxBLACK);
724 wxDouble width, height = 0;
725 dc->GetTextExtent( wxT("g"), &width, &height, NULL, NULL);
726 delete dc;
727 return wxSize((int)width, (int)height);
728#else
729 return wxFontBase::GetPixelSize();
730#endif
731}
732
59b7da02 733wxFontFamily wxFont::DoGetFamily() const
489468fe 734{
489468fe
SC
735 return M_FONTDATA->GetFamily();
736}
737
0c14b6c3 738wxFontStyle wxFont::GetStyle() const
489468fe 739{
0c14b6c3 740 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTSTYLE_MAX, wxT("invalid font") );
489468fe
SC
741
742 return M_FONTDATA->GetStyle() ;
743}
744
0c14b6c3 745wxFontWeight wxFont::GetWeight() const
489468fe 746{
0c14b6c3 747 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTWEIGHT_MAX, wxT("invalid font") );
489468fe
SC
748
749 return M_FONTDATA->GetWeight();
750}
751
752bool wxFont::GetUnderlined() const
753{
754 wxCHECK_MSG( M_FONTDATA != NULL , false, wxT("invalid font") );
755
756 return M_FONTDATA->GetUnderlined();
757}
758
759wxString wxFont::GetFaceName() const
760{
761 wxCHECK_MSG( M_FONTDATA != NULL , wxEmptyString , wxT("invalid font") );
762
763 return M_FONTDATA->GetFaceName() ;
764}
765
766wxFontEncoding wxFont::GetEncoding() const
767{
768 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTENCODING_DEFAULT , wxT("invalid font") );
769
770 return M_FONTDATA->GetEncoding() ;
771}
772
f1c40652 773#if wxOSX_USE_ATSU_TEXT && wxOSX_USE_CARBON
489468fe
SC
774
775short wxFont::MacGetFontNum() const
776{
777 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
778
f1c40652
SC
779 // cast away constness otherwise lazy font resolution is not possible
780 const_cast<wxFont *>(this)->RealizeResource();
03647350 781
f1c40652 782 return M_FONTDATA->m_info.m_qdFontFamily;
489468fe
SC
783}
784
f1c40652 785wxByte wxFont::MacGetFontStyle() const
489468fe
SC
786{
787 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
788
f1c40652
SC
789 // cast away constness otherwise lazy font resolution is not possible
790 const_cast<wxFont *>(this)->RealizeResource();
03647350 791
f1c40652 792 return M_FONTDATA->m_info.m_qdFontStyle;
489468fe
SC
793}
794
f1c40652 795wxUint16 wxFont::MacGetThemeFontID() const
489468fe
SC
796{
797 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
798
f1c40652 799 return M_FONTDATA->m_macThemeFontID;
489468fe
SC
800}
801
f1c40652
SC
802#endif
803
beb2638a 804#if wxOSX_USE_ATSU_TEXT
f1c40652 805void * wxFont::MacGetATSUStyle() const
489468fe 806{
f1c40652 807 wxCHECK_MSG( M_FONTDATA != NULL , NULL, wxT("invalid font") );
489468fe 808
f1c40652
SC
809 // cast away constness otherwise lazy font resolution is not possible
810 const_cast<wxFont *>(this)->RealizeResource();
03647350 811
f1c40652 812 return M_FONTDATA->m_macATSUStyle;
489468fe 813}
6f283573 814
03647350 815wxUint32 wxFont::MacGetATSUFontID() const
6f283573 816{
c22ace4d 817 wxCHECK_MSG( M_FONTDATA != NULL, 0, wxT("invalid font") );
6f283573
SC
818
819 // cast away constness otherwise lazy font resolution is not possible
820 const_cast<wxFont *>(this)->RealizeResource();
03647350 821
6f283573
SC
822 return M_FONTDATA->m_info.m_atsuFontID;
823}
824
825wxUint32 wxFont::MacGetATSUAdditionalQDStyles() const
826{
c22ace4d 827 wxCHECK_MSG( M_FONTDATA != NULL, 0, wxT("invalid font") );
6f283573
SC
828
829 // cast away constness otherwise lazy font resolution is not possible
830 const_cast<wxFont *>(this)->RealizeResource();
03647350 831
6f283573
SC
832 return M_FONTDATA->m_info.m_atsuAdditionalQDStyles;
833}
834#endif
835
f1c40652 836#if wxOSX_USE_CORE_TEXT
489468fe 837
aa6208d9 838CTFontRef wxFont::OSXGetCTFont() const
489468fe
SC
839{
840 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
841
f1c40652
SC
842 // cast away constness otherwise lazy font resolution is not possible
843 const_cast<wxFont *>(this)->RealizeResource();
03647350 844
f1c40652 845 return (CTFontRef)(M_FONTDATA->m_ctFont);
489468fe
SC
846}
847
f1c40652
SC
848#endif
849
9445de1e
SC
850#if wxOSX_USE_COCOA_OR_CARBON
851
aa6208d9 852CGFontRef wxFont::OSXGetCGFont() const
9445de1e
SC
853{
854 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
855
856 // cast away constness otherwise lazy font resolution is not possible
857 const_cast<wxFont *>(this)->RealizeResource();
03647350 858
9445de1e
SC
859 return (M_FONTDATA->m_cgFont);
860}
861
862#endif
863
864
f1c40652
SC
865#if wxOSX_USE_COCOA
866
aa6208d9 867NSFont* wxFont::OSXGetNSFont() const
489468fe
SC
868{
869 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
870
f1c40652
SC
871 // cast away constness otherwise lazy font resolution is not possible
872 const_cast<wxFont *>(this)->RealizeResource();
03647350 873
f1c40652 874 return (M_FONTDATA->m_nsFont);
489468fe 875}
f1c40652 876
489468fe
SC
877#endif
878
e5e5b843
SC
879#if wxOSX_USE_IPHONE
880
881UIFont* wxFont::OSXGetUIFont() const
882{
883 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
ce00f59b 884
e5e5b843
SC
885 // cast away constness otherwise lazy font resolution is not possible
886 const_cast<wxFont *>(this)->RealizeResource();
ce00f59b 887
e5e5b843
SC
888 return (M_FONTDATA->m_uiFont);
889}
890
891#endif
892
f1c40652 893const wxNativeFontInfo * wxFont::GetNativeFontInfo() const
489468fe
SC
894{
895 wxCHECK_MSG( M_FONTDATA != NULL , NULL, wxT("invalid font") );
a1b806b9 896 wxCHECK_MSG( IsOk(), NULL, wxT("invalid font") );
489468fe 897
f1c40652
SC
898 // cast away constness otherwise lazy font resolution is not possible
899 const_cast<wxFont *>(this)->RealizeResource();
03647350 900
f1c40652
SC
901 // M_FONTDATA->m_info.InitFromFont(*this);
902
903 return &(M_FONTDATA->m_info);
904}
905
906// ----------------------------------------------------------------------------
907// wxNativeFontInfo
908// ----------------------------------------------------------------------------
909
d0a7d7b1 910#if 0 // wxOSX_USE_CORE_TEXT
f1c40652
SC
911
912/* from Core Text Manual Common Operations */
913
914static CTFontDescriptorRef wxMacCreateCTFontDescriptor(CFStringRef iFamilyName, CTFontSymbolicTraits iTraits )
915{
916 CTFontDescriptorRef descriptor = NULL;
917 CFMutableDictionaryRef attributes;
918
2e587bb9 919 wxASSERT(iFamilyName != NULL);
f1c40652
SC
920 // Create a mutable dictionary to hold our attributes.
921 attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
922 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2e587bb9 923 wxASSERT(attributes != NULL);
f1c40652
SC
924
925 if (attributes != NULL) {
926 // Add a family name to our attributes.
927 CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, iFamilyName);
928
929
930 if ( iTraits ) {
931 CFMutableDictionaryRef traits;
932 CFNumberRef symTraits;
933
934 // Create the traits dictionary.
935 symTraits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type,
936 &iTraits);
2e587bb9 937 wxASSERT(symTraits != NULL);
f1c40652
SC
938
939 if (symTraits != NULL) {
940 // Create a dictionary to hold our traits values.
941 traits = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
942 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2e587bb9 943 wxASSERT(traits != NULL);
f1c40652
SC
944
945 if (traits != NULL) {
946 // Add the symbolic traits value to the traits dictionary.
947 CFDictionaryAddValue(traits, kCTFontSymbolicTrait, symTraits);
948
949 // Add the traits attribute to our attributes.
950 CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits);
951 CFRelease(traits);
952 }
953 CFRelease(symTraits);
954 }
955 }
956 // Create the font descriptor with our attributes
957 descriptor = CTFontDescriptorCreateWithAttributes(attributes);
2e587bb9 958 wxASSERT(descriptor != NULL);
f1c40652
SC
959
960 CFRelease(attributes);
961 }
962 // Return our font descriptor.
963 return descriptor ;
964}
965
966#endif
967
968void wxNativeFontInfo::Init()
969{
f1c40652
SC
970#if wxOSX_USE_ATSU_TEXT
971 m_atsuFontID = 0 ;
972 m_atsuAdditionalQDStyles = 0;
973 m_atsuFontValid = false;
974#if wxOSX_USE_CARBON
975 m_qdFontStyle = 0;
976 m_qdFontFamily = 0;
977#endif
f1c40652
SC
978#endif
979 m_pointSize = 0;
980 m_family = wxFONTFAMILY_DEFAULT;
981 m_style = wxFONTSTYLE_NORMAL;
982 m_weight = wxFONTWEIGHT_NORMAL;
983 m_underlined = false;
984 m_faceName.clear();
c443ff6f 985 m_encoding = wxFont::GetDefaultEncoding();
f1c40652
SC
986 m_descriptorValid = false;
987}
988
989#if wxOSX_USE_CORE_TEXT
990void wxNativeFontInfo::Init(CTFontDescriptorRef descr)
991{
992 Init();
03647350 993
03c28161 994 wxCFRef< CFNumberRef > sizevalue( (CFNumberRef) CTFontDescriptorCopyAttribute( descr, kCTFontSizeAttribute ) );
f1c40652
SC
995 float fsize;
996 if ( CFNumberGetValue( sizevalue , kCFNumberFloatType , &fsize ) )
997 m_pointSize = (int)( fsize + 0.5 );
998
03c28161 999 wxCFRef< CFDictionaryRef > traitsvalue( (CFDictionaryRef) CTFontDescriptorCopyAttribute( descr, kCTFontTraitsAttribute ) );
f1c40652
SC
1000 CTFontSymbolicTraits traits;
1001 if ( CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(traitsvalue,kCTFontSymbolicTrait),kCFNumberIntType,&traits) )
1002 {
1003 if ( traits & kCTFontItalicTrait )
1004 m_style = wxFONTSTYLE_ITALIC;
1005 if ( traits & kCTFontBoldTrait )
1006 m_weight = wxFONTWEIGHT_BOLD ;
1007 }
1008
03c28161 1009 wxCFStringRef familyName( (CFStringRef) CTFontDescriptorCopyAttribute(descr, kCTFontFamilyNameAttribute));
03647350 1010 m_faceName = familyName.AsString();
489468fe
SC
1011}
1012#endif
1013
f1c40652
SC
1014void wxNativeFontInfo::EnsureValid()
1015{
1016 if ( m_descriptorValid )
1017 return;
03647350 1018
f1c40652
SC
1019#if wxOSX_USE_ATSU_TEXT
1020 if ( !m_atsuFontValid )
1021 {
9a672c75
SC
1022#if !wxOSX_USE_CARBON
1023 // not needed outside
1024 wxInt16 m_qdFontFamily;
1025 wxInt16 m_qdFontStyle;
1026#endif
f1c40652
SC
1027 wxCFStringRef cf( m_faceName, wxLocale::GetSystemEncoding() );
1028 ATSFontFamilyRef atsfamily = ATSFontFamilyFindFromName( cf , kATSOptionFlagsDefault );
1029 if ( atsfamily == (ATSFontFamilyRef) -1 )
1030 {
1031 wxLogDebug( wxT("ATSFontFamilyFindFromName failed for ") + m_faceName );
1032 m_qdFontFamily = GetAppFont();
1033 }
1034 else
1035 {
1036 m_qdFontFamily = FMGetFontFamilyFromATSFontFamilyRef( atsfamily );
1037 }
1038
1039 m_qdFontStyle = 0;
1040 if (m_weight == wxFONTWEIGHT_BOLD)
1041 m_qdFontStyle |= bold;
1042 if (m_style == wxFONTSTYLE_ITALIC || m_style == wxFONTSTYLE_SLANT)
1043 m_qdFontStyle |= italic;
1044 if (m_underlined)
1045 m_qdFontStyle |= underline;
1046
489468fe 1047
f1c40652
SC
1048 // we try to get as much styles as possible into ATSU
1049
1050 // ATSUFontID and FMFont are equivalent
1051 FMFontStyle intrinsicStyle = 0 ;
1052 OSStatus status = FMGetFontFromFontFamilyInstance( m_qdFontFamily , m_qdFontStyle , (FMFont*)&m_atsuFontID , &intrinsicStyle);
ca910e1a
VZ
1053 if ( status != noErr )
1054 {
1055 wxFAIL_MSG( wxT("couldn't get an ATSUFont from font family") );
1056 }
f1c40652
SC
1057 m_atsuAdditionalQDStyles = m_qdFontStyle & (~intrinsicStyle );
1058 m_atsuFontValid = true;
1059 }
f1c40652
SC
1060#endif
1061 m_descriptorValid = true;
1062}
1063
1064void wxNativeFontInfo::Init(const wxNativeFontInfo& info)
489468fe 1065{
f1c40652 1066 Init();
f1c40652
SC
1067#if wxOSX_USE_ATSU_TEXT
1068 m_atsuFontValid = info.m_atsuFontValid;
1069 m_atsuFontID = info.m_atsuFontID ;
1070 m_atsuAdditionalQDStyles = info.m_atsuAdditionalQDStyles;
1071#if wxOSX_USE_CARBON
1072 m_qdFontFamily = info.m_qdFontFamily;
1073 m_qdFontStyle = info.m_qdFontStyle;
1074#endif
f1c40652
SC
1075#endif
1076 m_pointSize = info.m_pointSize;
1077 m_family = info.m_family;
1078 m_style = info.m_style;
1079 m_weight = info.m_weight;
1080 m_underlined = info.m_underlined;
1081 m_faceName = info.m_faceName;
1082 m_encoding = info.m_encoding;
1083 m_descriptorValid = info.m_descriptorValid;
1084}
1085
1086void wxNativeFontInfo::Init(int size,
1087 wxFontFamily family,
1088 wxFontStyle style,
1089 wxFontWeight weight,
1090 bool underlined,
1091 const wxString& faceName,
1092 wxFontEncoding encoding)
1093{
1094 Init();
1095 m_pointSize = size;
1096 m_family = family;
1097 m_style = style;
1098 m_weight = weight;
1099 m_underlined = underlined;
1100 m_faceName = faceName;
c443ff6f
SC
1101 if ( encoding == wxFONTENCODING_DEFAULT )
1102 encoding = wxFont::GetDefaultEncoding();
f1c40652 1103 m_encoding = encoding;
489468fe 1104
489468fe
SC
1105}
1106
f1c40652
SC
1107void wxNativeFontInfo::Free()
1108{
f1c40652
SC
1109#if wxOSX_USE_ATSU_TEXT
1110 m_atsuFontID = 0 ;
1111 m_atsuAdditionalQDStyles = 0;
1112 m_atsuFontValid = false;
489468fe 1113#endif
f1c40652
SC
1114 m_descriptorValid = false;
1115}
489468fe 1116
f1c40652 1117bool wxNativeFontInfo::FromString(const wxString& s)
489468fe 1118{
f1c40652 1119 long l;
489468fe 1120
9a83f860 1121 wxStringTokenizer tokenizer(s, wxT(";"));
489468fe 1122
f1c40652
SC
1123 wxString token = tokenizer.GetNextToken();
1124 //
1125 // Ignore the version for now
1126 //
1127
1128 token = tokenizer.GetNextToken();
1129 if ( !token.ToLong(&l) )
1130 return false;
1131 m_pointSize = (int)l;
1132
1133 token = tokenizer.GetNextToken();
1134 if ( !token.ToLong(&l) )
1135 return false;
1136 m_family = (wxFontFamily)l;
1137
1138 token = tokenizer.GetNextToken();
1139 if ( !token.ToLong(&l) )
1140 return false;
1141 m_style = (wxFontStyle)l;
1142
1143 token = tokenizer.GetNextToken();
1144 if ( !token.ToLong(&l) )
1145 return false;
1146 m_weight = (wxFontWeight)l;
1147
1148 token = tokenizer.GetNextToken();
1149 if ( !token.ToLong(&l) )
1150 return false;
1151 m_underlined = l != 0;
1152
1153 m_faceName = tokenizer.GetNextToken();
1154
1155#ifndef __WXMAC__
1156 if( !faceName )
1157 return false;
1158#endif
1159
1160 token = tokenizer.GetNextToken();
1161 if ( !token.ToLong(&l) )
1162 return false;
1163 m_encoding = (wxFontEncoding)l;
1164
1165 return true;
1166}
1167
1168wxString wxNativeFontInfo::ToString() const
1169{
1170 wxString s;
1171
9a83f860 1172 s.Printf(wxT("%d;%d;%d;%d;%d;%d;%s;%d"),
f1c40652
SC
1173 0, // version
1174 m_pointSize,
1175 m_family,
1176 (int)m_style,
1177 (int)m_weight,
1178 m_underlined,
1179 m_faceName.GetData(),
1180 (int)m_encoding);
1181
1182 return s;
1183}
1184
1185int wxNativeFontInfo::GetPointSize() const
1186{
1187 return m_pointSize;
1188}
1189
1190wxFontStyle wxNativeFontInfo::GetStyle() const
1191{
1192 return m_style;
1193}
1194
1195wxFontWeight wxNativeFontInfo::GetWeight() const
1196{
1197 return m_weight;
1198}
1199
1200bool wxNativeFontInfo::GetUnderlined() const
1201{
1202 return m_underlined;
1203}
1204
1205wxString wxNativeFontInfo::GetFaceName() const
1206{
1207 return m_faceName;
1208}
1209
1210wxFontFamily wxNativeFontInfo::GetFamily() const
1211{
1212 return m_family;
489468fe 1213}
f1c40652
SC
1214
1215wxFontEncoding wxNativeFontInfo::GetEncoding() const
1216{
1217 return m_encoding;
1218}
1219
1220// changing the font descriptor
1221
1222void wxNativeFontInfo::SetPointSize(int pointsize)
1223{
1224 if ( m_pointSize != pointsize )
1225 {
1226 m_pointSize = pointsize;
1227 Free();
1228 }
1229}
1230
1231void wxNativeFontInfo::SetStyle(wxFontStyle style_)
1232{
1233 if ( m_style != style_ )
1234 {
1235 m_style = style_;
1236 Free();
1237 }
1238}
1239
1240void wxNativeFontInfo::SetWeight(wxFontWeight weight_)
1241{
1242 if ( m_weight != weight_ )
1243 {
1244 m_weight = weight_;
1245 Free();
1246 }
1247}
1248
1249void wxNativeFontInfo::SetUnderlined(bool underlined_)
1250{
1251 if ( m_underlined != underlined_ )
1252 {
1253 m_underlined = underlined_;
1254 Free();
1255 }
1256}
1257
1258bool wxNativeFontInfo::SetFaceName(const wxString& facename_)
1259{
1260 if ( m_faceName != facename_ )
1261 {
1262 m_faceName = facename_;
1263 Free();
1264 }
1265 return true;
1266}
1267
1268void wxNativeFontInfo::SetFamily(wxFontFamily family_)
1269{
1270 if ( m_family != family_ )
1271 {
1272 m_family = family_;
1273 Free();
1274 }
1275}
1276
1277void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding_)
1278{
c443ff6f
SC
1279 if ( encoding_ == wxFONTENCODING_DEFAULT )
1280 encoding_ = wxFont::GetDefaultEncoding();
f1c40652
SC
1281 m_encoding = encoding_;
1282 // not reflected in native descriptors
c22ace4d 1283}