diff --git a/include/wx/defs.h b/include/wx/defs.h index f21937cd23..1f3b1724dc 100644 --- a/include/wx/defs.h +++ b/include/wx/defs.h @@ -2943,6 +2943,7 @@ typedef const void * CFTypeRef; DECLARE_WXOSX_OPAQUE_CONST_CFREF( CFString ) typedef struct __CFString * CFMutableStringRef; +DECLARE_WXOSX_OPAQUE_CONST_CFREF( CFDictionary ) DECLARE_WXOSX_OPAQUE_CFREF( CFRunLoopSource ) DECLARE_WXOSX_OPAQUE_CONST_CFREF( CTFont ) diff --git a/include/wx/osx/font.h b/include/wx/osx/font.h index b82e948001..e32e7d7b63 100644 --- a/include/wx/osx/font.h +++ b/include/wx/osx/font.h @@ -144,6 +144,7 @@ public: #endif CTFontRef OSXGetCTFont() const; + CFDictionaryRef OSXGetCTFontAttributes() const; #if wxOSX_USE_COCOA WX_NSFont OSXGetNSFont() const; diff --git a/src/osx/carbon/font.cpp b/src/osx/carbon/font.cpp index fe0b259c46..5180ab66c9 100644 --- a/src/osx/carbon/font.cpp +++ b/src/osx/carbon/font.cpp @@ -158,6 +158,7 @@ protected: public: bool m_fontValid; wxCFRef m_ctFont; + wxCFRef m_ctFontAttributes; wxCFRef m_cgFont; #if wxOSX_USE_COCOA WX_NSFont m_nsFont; @@ -176,6 +177,7 @@ wxFontRefData::wxFontRefData(const wxFontRefData& data) : wxGDIRefData() m_info = data.m_info; m_fontValid = data.m_fontValid; m_ctFont = data.m_ctFont; + m_ctFontAttributes = data.m_ctFontAttributes; m_cgFont = data.m_cgFont; #if wxOSX_USE_COCOA m_nsFont = (NSFont*) wxMacCocoaRetain(data.m_nsFont); @@ -271,6 +273,11 @@ wxFontRefData::wxFontRefData(wxOSXSystemFont font, int size) break; } m_ctFont.reset(CTFontCreateUIFontForLanguage( uifont, (CGFloat) size, NULL )); + CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + m_ctFontAttributes.reset(dict); + CFDictionarySetValue(dict, kCTFontAttributeName, m_ctFont.get() ); + CFDictionarySetValue(dict, kCTForegroundColorFromContextAttributeName, kCFBooleanTrue); + wxCFRef descr; descr.reset( CTFontCopyFontDescriptor( m_ctFont ) ); m_info.Init(descr); @@ -288,6 +295,16 @@ wxFontRefData::wxFontRefData(wxOSXSystemFont font, int size) static const CGAffineTransform kSlantTransform = CGAffineTransformMake( 1, 0, tan(wxDegToRad(11)), 1, 0, 0 ); +namespace +{ + +struct CachedFontEntry { + wxCFRef< CTFontRef > font; + wxCFRef< CFDictionaryRef > fontAttributes; +} ; + +} // anonymous namespace + void wxFontRefData::MacFindFont() { if ( m_fontValid ) @@ -306,10 +323,19 @@ void wxFontRefData::MacFindFont() // use font caching wxString lookupnameWithSize = wxString::Format( "%s_%u_%d", m_info.m_faceName, traits, m_info.m_pointSize ); - static std::map< std::wstring , wxCFRef< CTFontRef > > fontcache ; - m_ctFont = fontcache[ std::wstring(lookupnameWithSize.wc_str()) ]; - if ( !m_ctFont ) + static std::map< wxString, CachedFontEntry > fontcache ; + + CachedFontEntry& entry = fontcache[ lookupnameWithSize ]; + m_ctFont = entry.font; + m_ctFontAttributes = entry.fontAttributes; + if ( m_ctFont ) { + // use cached version + } + else + { + CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + m_ctFontAttributes.reset(dict); wxStringToStringHashMap::const_iterator it = gs_FontFamilyToPSName.find(m_info.m_faceName); @@ -350,11 +376,23 @@ void wxFontRefData::MacFindFont() fontWithTraits = CTFontCreateCopyWithSymbolicTraits( m_ctFont, 0, remainingTransform, remainingTraits, remainingTraits ); if ( fontWithTraits == NULL ) { - // give in on the bold, try native oblique + // try native oblique, emulate bold later fontWithTraits = CTFontCreateCopyWithSymbolicTraits( m_ctFont, 0, NULL, kCTFontItalicTrait, kCTFontItalicTrait ); } + else + { + remainingTraits &= ~kCTFontBoldTrait; + } } } + + // we have to emulate bold + if ( remainingTraits & kCTFontBoldTrait ) + { + // 3 times as thick, negative value because we want effect on stroke and fill (not only stroke) + const float strokewidth = -3.0; + CFDictionarySetValue(dict, kCTStrokeWidthAttributeName, CFNumberCreate( NULL, kCFNumberFloatType, &strokewidth)); + } if ( fontWithTraits == NULL ) { @@ -366,6 +404,11 @@ void wxFontRefData::MacFindFont() m_ctFont.reset(fontWithTraits); } } + CFDictionarySetValue(dict, kCTFontAttributeName, m_ctFont.get() ); + CFDictionarySetValue(dict, kCTForegroundColorFromContextAttributeName, kCFBooleanTrue); + + entry.font = m_ctFont; + entry.fontAttributes = m_ctFontAttributes; } m_cgFont.reset(CTFontCopyGraphicsFont(m_ctFont, NULL)); @@ -378,7 +421,7 @@ void wxFontRefData::MacFindFont() #endif m_fontValid = true; } - + bool wxFontRefData::IsFixedWidth() const { CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(m_ctFont); @@ -659,6 +702,16 @@ CTFontRef wxFont::OSXGetCTFont() const return (CTFontRef)(M_FONTDATA->m_ctFont); } +CFDictionaryRef wxFont::OSXGetCTFontAttributes() const +{ + wxCHECK_MSG( M_FONTDATA != NULL , NULL, wxT("invalid font") ); + + // cast away constness otherwise lazy font resolution is not possible + const_cast(this)->RealizeResource(); + + return (CFDictionaryRef)(M_FONTDATA->m_ctFontAttributes); +} + #if wxOSX_USE_COCOA_OR_CARBON CGFontRef wxFont::OSXGetCGFont() const diff --git a/src/osx/carbon/graphics.cpp b/src/osx/carbon/graphics.cpp index 033d6ee6a1..5d2492554b 100644 --- a/src/osx/carbon/graphics.cpp +++ b/src/osx/carbon/graphics.cpp @@ -824,6 +824,7 @@ public: ~wxMacCoreGraphicsFontData(); CTFontRef OSXGetCTFont() const { return m_ctFont ; } + CFDictionaryRef OSXGetCTFontAttributes() const { return m_ctFontAttributes; } wxColour GetColour() const { return m_colour ; } bool GetUnderlined() const { return m_underlined ; } @@ -837,6 +838,7 @@ private : bool m_underlined, m_strikethrough; wxCFRef< CTFontRef > m_ctFont; + wxCFRef< CFDictionaryRef > m_ctFontAttributes; #if wxOSX_USE_IPHONE UIFont* m_uiFont; #endif @@ -849,6 +851,7 @@ wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* rendere m_strikethrough = font.GetStrikethrough(); m_ctFont.reset( wxMacCreateCTFont( font ) ); + m_ctFontAttributes.reset( wxCFRetain( font.OSXGetCTFontAttributes() ) ); #if wxOSX_USE_IPHONE m_uiFont = CreateUIFont(font); wxMacCocoaRetain( m_uiFont ); @@ -2220,21 +2223,10 @@ void wxMacCoreGraphicsContext::DoDrawText( const wxString &str, wxDouble x, wxDo wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData(); wxCFStringRef text(str, wxLocale::GetSystemEncoding() ); - CTFontRef font = fref->OSXGetCTFont(); CGColorRef col = wxMacCreateCGColor( fref->GetColour() ); -#if 0 - // right now there's no way to get continuous underlines, only words, so we emulate it - CTUnderlineStyle ustyle = fref->GetUnderlined() ? kCTUnderlineStyleSingle : kCTUnderlineStyleNone ; - wxCFRef underlined( CFNumberCreate(NULL, kCFNumberSInt32Type, &ustyle) ); - CFStringRef keys[] = { kCTFontAttributeName , kCTForegroundColorAttributeName, kCTUnderlineStyleAttributeName }; - CFTypeRef values[] = { font, col, underlined }; -#else - CFStringRef keys[] = { kCTFontAttributeName , kCTForegroundColorAttributeName }; - CFTypeRef values[] = { font, col }; -#endif - wxCFRef attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**) &keys, (const void**) &values, - WXSIZEOF( keys ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) ); - wxCFRef attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, attributes) ); + CTFontRef font = fref->OSXGetCTFont(); + + wxCFRef attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, fref->OSXGetCTFontAttributes()) ); wxCFRef line( CTLineCreateWithAttributedString(attrtext) ); y += CTFontGetAscent(font); @@ -2246,6 +2238,7 @@ void wxMacCoreGraphicsContext::DoDrawText( const wxString &str, wxDouble x, wxDo CGContextScaleCTM(m_cgContext, 1, -1); CGContextSetTextMatrix(m_cgContext, CGAffineTransformIdentity); + CGContextSetFillColorWithColor( m_cgContext, col ); CTLineDraw( line, m_cgContext ); if ( fref->GetUnderlined() ) { @@ -2316,14 +2309,10 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid strToMeasure = wxS(" "); wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData(); - CTFontRef font = fref->OSXGetCTFont(); wxCFStringRef text(strToMeasure, wxLocale::GetSystemEncoding() ); - CFStringRef keys[] = { kCTFontAttributeName }; - CFTypeRef values[] = { font }; - wxCFRef attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**) &keys, (const void**) &values, - WXSIZEOF( keys ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) ); - wxCFRef attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, attributes) ); + + wxCFRef attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, fref->OSXGetCTFontAttributes() ) ); wxCFRef line( CTLineCreateWithAttributedString(attrtext) ); CGFloat a, d, l, w; @@ -2336,7 +2325,6 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid if ( height ) *height = a+d+l; } - if ( descent ) *descent = d; if ( externalLeading ) @@ -2355,14 +2343,9 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr return; wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData(); - CTFontRef font = fref->OSXGetCTFont(); wxCFStringRef t(text, wxLocale::GetSystemEncoding() ); - CFStringRef keys[] = { kCTFontAttributeName }; - CFTypeRef values[] = { font }; - wxCFRef attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**) &keys, (const void**) &values, - WXSIZEOF( keys ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) ); - wxCFRef attrtext( CFAttributedStringCreate(kCFAllocatorDefault, t, attributes) ); + wxCFRef attrtext( CFAttributedStringCreate(kCFAllocatorDefault, t, fref->OSXGetCTFontAttributes()) ); wxCFRef line( CTLineCreateWithAttributedString(attrtext) ); widths.reserve(text.length());