From cf000e7e020bb2b0b71c71ffea2ad709233a6993 Mon Sep 17 00:00:00 2001 From: ARATA Mizuki Date: Sat, 26 Mar 2016 13:31:35 +0900 Subject: [PATCH] Fix GetPartialTextExtents() to handle non-BMP chars under OS X On OS X, wxString operates on UTF-32 code units, but CoreText API use UTF-16 code units. So we need to take care of surrogate pairs. Closes https://github.com/wxWidgets/wxWidgets/pull/261 --- docs/changes.txt | 1 + src/osx/carbon/graphics.cpp | 16 +++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 91016e75e1..0a2951edcb 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -81,6 +81,7 @@ wxMSW: wxOSX: +- Fix handling of non-BMP characters in GetPartialTextExtents() (ARATA Mizuki). - Remove extra borders around wxFilePickerCtrl (John Roberts). - Set up extensions filter correctly in wxFileDialog (nick863). - Turn off automatic quotes substitutions in wxTextCtrl (Xlord2). diff --git a/src/osx/carbon/graphics.cpp b/src/osx/carbon/graphics.cpp index 2d9cb960f0..9919a47a31 100644 --- a/src/osx/carbon/graphics.cpp +++ b/src/osx/carbon/graphics.cpp @@ -2360,8 +2360,7 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const { - widths.Empty(); - widths.Add(0, text.length()); + widths.clear(); wxCHECK_RET( !m_font.IsNull(), wxT("wxMacCoreGraphicsContext::DrawText - no valid font set") ); @@ -2379,10 +2378,17 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr wxCFRef attrtext( CFAttributedStringCreate(kCFAllocatorDefault, t, attributes) ); wxCFRef line( CTLineCreateWithAttributedString(attrtext) ); - int chars = text.length(); - for ( int pos = 0; pos < (int)chars; pos ++ ) + widths.reserve(text.length()); + CFIndex u16index = 1; + for ( wxString::const_iterator iter = text.begin(); iter != text.end(); ++iter, ++u16index ) { - widths[pos] = CTLineGetOffsetForStringIndex( line, pos+1 , NULL ); + // Take care of surrogate pairs: they take two, not one, of UTF-16 code + // units used by CoreText. + if ( *iter >= 0x10000 ) + { + ++u16index; + } + widths.push_back( CTLineGetOffsetForStringIndex( line, u16index, NULL ) ); } CheckInvariants();