From e1b4c6ddc6e2a980a7ffbf7c3f81ffc929c234d0 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Sun, 10 Jul 2011 11:24:11 +1000 Subject: Display and measure text in different encodings. --- cocoa/PlatCocoa.mm | 82 ++++++++++++++++++++++++++++++++++-------------- cocoa/QuartzTextLayout.h | 12 +++++-- 2 files changed, 69 insertions(+), 25 deletions(-) diff --git a/cocoa/PlatCocoa.mm b/cocoa/PlatCocoa.mm index dba386750..4465e36ae 100644 --- a/cocoa/PlatCocoa.mm +++ b/cocoa/PlatCocoa.mm @@ -149,6 +149,10 @@ Font::~Font() //-------------------------------------------------------------------------------------------------- +static int FontCharacterSet(Font &f) { + return reinterpret_cast(f.GetID())->getCharacterSet(); +} + /** * Creates a Quartz 2D font with the given properties. * TODO: rewrite to use NSFont. @@ -905,55 +909,86 @@ CFStringEncoding EncodingFromCharacterSet(bool unicode, int characterSet) void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore) { + CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); ColourDesired colour(fore.AsLong()); CGColorRef color = CGColorCreateGenericRGB(colour.GetRed()/255.0,colour.GetGreen()/255.0,colour.GetBlue()/255.0,1.0); QuartzTextStyle* style = reinterpret_cast(font_.GetID()); style->setCTStyleColor(color); - textLayout->setText (reinterpret_cast(s), len, *reinterpret_cast(font_.GetID())); + textLayout->setText (reinterpret_cast(s), len, encoding, *reinterpret_cast(font_.GetID())); textLayout->draw(rc.left, ybase); } +static size_t utf8LengthFromLead(unsigned char uch) { + if (uch >= (0x80 + 0x40 + 0x20 + 0x10)) { + return 4; + } else if (uch >= (0x80 + 0x40 + 0x20)) { + return 3; + } else if (uch >= (0x80)) { + return 2; + } else { + return 1; + } +} + //-------------------------------------------------------------------------------------------------- void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) { + CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); for (int i = 0; i < len; i++) positions [i] = 0; - textLayout->setText (reinterpret_cast(s), len, *reinterpret_cast(font_.GetID())); + textLayout->setText (reinterpret_cast(s), len, encoding, *reinterpret_cast(font_.GetID())); CTLineRef mLine = textLayout->getCTLine(); assert(mLine != NULL); - CGFloat* secondaryOffset= 0; - int unicodeCharStart = 0; - for ( int i = 0; i < len+1; i ++ ){ - unsigned char uch = s[i]; - CFIndex charIndex = unicodeCharStart+1; - CGFloat advance = CTLineGetOffsetForStringIndex(mLine, charIndex, secondaryOffset); - - if ( unicodeMode ) - { - unsigned char mask = 0xc0; - int lcount = 1; - // Add one additonal byte for each extra high order one in the byte - while ( uch >= mask && lcount < 8 ) - { - positions[i++] = (int)(advance+0.5); - lcount ++; - mask = mask >> 1 | 0x80; // add an additional one in the highest order position + if (unicodeMode) { + // Map the widths given for UTF-16 characters back onto the UTF-8 input string + int fit = textLayout->getStringLength(); + int ui=0; + const unsigned char *us = reinterpret_cast(s); + int i=0; + while (ui 0) + lastPos = positions[i-1]; + while (isetText (reinterpret_cast(s), len, *reinterpret_cast(font_.GetID())); + CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); + textLayout->setText (reinterpret_cast(s), len, encoding, *reinterpret_cast(font_.GetID())); return textLayout->MeasureStringWidth(); } @@ -964,7 +999,8 @@ int SurfaceImpl::WidthChar(Font &font_, char ch) { char str[2] = { ch, '\0' }; if (font_.GetID()) { - textLayout->setText (reinterpret_cast(str), 1, *reinterpret_cast(font_.GetID())); + CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); + textLayout->setText (reinterpret_cast(str), 1, encoding, *reinterpret_cast(font_.GetID())); return textLayout->MeasureStringWidth(); } diff --git a/cocoa/QuartzTextLayout.h b/cocoa/QuartzTextLayout.h index 033ac98fb..c789ed10f 100644 --- a/cocoa/QuartzTextLayout.h +++ b/cocoa/QuartzTextLayout.h @@ -24,6 +24,7 @@ public: { mString = NULL; mLine = NULL; + stringLength = 0; setContext(context); } @@ -41,12 +42,14 @@ public: } } - inline void setText( const UInt8* buffer, size_t byteLength, const QuartzTextStyle& r ) + inline void setText( const UInt8* buffer, size_t byteLength, CFStringEncoding encoding, const QuartzTextStyle& r ) { - CFStringRef str = CFStringCreateWithBytes( NULL, buffer, byteLength, kCFStringEncodingUTF8, false ); + CFStringRef str = CFStringCreateWithBytes( NULL, buffer, byteLength, encoding, false ); if (!str) return; + stringLength = CFStringGetLength(str); + CFMutableDictionaryRef stringAttribs = r.getCTStyle(); if (mString != NULL) @@ -89,6 +92,10 @@ public: return mLine; } + CFIndex getStringLength() { + return stringLength; + } + inline void setContext (CGContextRef context) { gc = context; @@ -98,6 +105,7 @@ private: CGContextRef gc; CFAttributedStringRef mString; CTLineRef mLine; + CFIndex stringLength; }; #endif -- cgit v1.2.3