aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--cocoa/PlatCocoa.mm82
-rw-r--r--cocoa/QuartzTextLayout.h12
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<QuartzTextStyle *>(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<QuartzTextStyle*>(font_.GetID());
style->setCTStyleColor(color);
- textLayout->setText (reinterpret_cast<const UInt8*>(s), len, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
+ textLayout->setText (reinterpret_cast<const UInt8*>(s), len, encoding, *reinterpret_cast<QuartzTextStyle*>(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<const UInt8*>(s), len, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
+ textLayout->setText (reinterpret_cast<const UInt8*>(s), len, encoding, *reinterpret_cast<QuartzTextStyle*>(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<const unsigned char *>(s);
+ int i=0;
+ while (ui<fit) {
+ size_t lenChar = utf8LengthFromLead(us[i]);
+ size_t codeUnits = (lenChar < 4) ? 1 : 2;
+ CGFloat xPosition = CTLineGetOffsetForStringIndex(mLine, ui+1, NULL);
+ for (unsigned int bytePos=0; (bytePos<lenChar) && (i<len); bytePos++) {
+ positions[i++] = lround(xPosition);
}
+ ui += codeUnits;
+ }
+ int lastPos = 0;
+ if (i > 0)
+ lastPos = positions[i-1];
+ while (i<len) {
+ positions[i++] = lastPos;
+ }
+ } else if (codePage) {
+ int ui = 0;
+ for (int i=0;i<len;) {
+ size_t lenChar = Platform::IsDBCSLeadByte(codePage, s[i]) ? 2 : 1;
+ CGFloat xPosition = CTLineGetOffsetForStringIndex(mLine, ui+1, NULL);
+ for (unsigned int bytePos=0; (bytePos<lenChar) && (i<len); bytePos++) {
+ positions[i++] = lround(xPosition);
+ }
+ ui++;
+ }
+ } else { // Single byte encoding
+ for (int i=0;i<len;i++) {
+ CGFloat xPosition = CTLineGetOffsetForStringIndex(mLine, i+1, NULL);
+ positions[i] = lround(xPosition);
}
- positions[i] = (int)(advance+0.5);
- unicodeCharStart++;
}
+
}
int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
if (font_.GetID())
{
- textLayout->setText (reinterpret_cast<const UInt8*>(s), len, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
+ CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_));
+ textLayout->setText (reinterpret_cast<const UInt8*>(s), len, encoding, *reinterpret_cast<QuartzTextStyle*>(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<const UInt8*>(str), 1, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
+ CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_));
+ textLayout->setText (reinterpret_cast<const UInt8*>(str), 1, encoding, *reinterpret_cast<QuartzTextStyle*>(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