From 4dd1f5e2164b8d4e4f1b5a3e7df934f82f3c5783 Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Fri, 2 Jun 2006 14:17:41 +0000 Subject: STR #1305: partial fix. FLTK on Mac with --enable-quartz now uses ATSU instead of CG to render text. First of all, it is a lot faster, but more importantly, character positions are now all at integer positions. This is not as beatiful as standard Mac text, but required by the FLTK internals. I seriously doubt that anyone who's not a typesette will notice the difference. But - and there's always a but, isn't there? This commit does not handle the ASCII-to-UTF16 conversion yet, so all characters above 127 are junk. Also, there are still a lot of problems with the Quartz support in general. Most prominently, we still get a lot of messages about invalid contexts which ruins the clipping. So in conclusion (this must be the longest SVN commit annotation ever) this modification fixes the main reason why I did not finish the Quartz port. After fixing this, there's hope that we will wrap even that dirty little corner of FLTK up for good! git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@5171 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- src/Fl_Font.H | 4 ++- src/fl_font_mac.cxx | 84 +++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 68 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/Fl_Font.H b/src/Fl_Font.H index 966962312..2ff197111 100644 --- a/src/Fl_Font.H +++ b/src/Fl_Font.H @@ -60,9 +60,11 @@ public: bool knowMetrics; # elif defined(__APPLE_QUARTZ__) FL_EXPORT Fl_FontSize(const char* fontname, int size); + ATSUTextLayout layout; + ATSUStyle style; + short ascent, descent, q_width; char *q_name; int size; - short ascent, descent, q_width; # elif USE_XFT XftFont* font; const char* encoding; diff --git a/src/fl_font_mac.cxx b/src/fl_font_mac.cxx index b9a5f5bbb..9e11e4eb7 100644 --- a/src/fl_font_mac.cxx +++ b/src/fl_font_mac.cxx @@ -57,24 +57,53 @@ Fl_FontSize::Fl_FontSize(const char* name, int Size) { for (int i=0; i<256; i++) width[i] = fOut->widMax; minsize = maxsize = size; #elif defined(__APPLE_QUARTZ__) + // OpenGL needs those for its font handling q_name = strdup(name); size = Size; + OSStatus err; + // fill our structure with a few default values ascent = Size*3/4; descent = Size-ascent; q_width = Size*2/3; minsize = maxsize = Size; - // Using ATS to get the genral Glyph size information - CFStringRef cfname = CFStringCreateWithCString(0L, q_name, kCFStringEncodingASCII); + // now use ATS to get the actual Glyph size information + CFStringRef cfname = CFStringCreateWithCString(0L, name, kCFStringEncodingASCII); ATSFontRef font = ATSFontFindFromName(cfname, kATSOptionFlagsDefault); if (font) { ATSFontMetrics m = { 0 }; ATSFontGetHorizontalMetrics(font, kATSOptionFlagsDefault, &m); - if (m.avgAdvanceWidth) q_width = int(m.avgAdvanceWidth*size); - // playing with the offsets a little to make standard sizes fit - if (m.ascent) ascent = int(m.ascent*size-0.5f); - if (m.descent) descent = -int(m.descent*size-1.5f); + if (m.avgAdvanceWidth) q_width = int(m.avgAdvanceWidth*Size); + // playing with the offsets a little to make standard sizes fit + if (m.ascent) ascent = int(m.ascent*Size-0.5f); + if (m.descent) descent = -int(m.descent*Size-1.5f); } CFRelease(cfname); + // now we allocate everything needed to render text in this font later + // get us the default layout and style + err = ATSUCreateTextLayout(&layout); + UniChar mTxt[2] = { 65, 0 }; + err = ATSUSetTextPointerLocation(layout, mTxt, kATSUFromTextBeginning, 1, 1); + err = ATSUCreateStyle(&style); + err = ATSUSetRunStyle(layout, style, kATSUFromTextBeginning, kATSUToTextEnd); + // now set the actual font, size and attributes + Fixed fsize = IntToFixed(Size); + ATSUFontID fontID = FMGetFontFromATSFontRef(font); + ATSUAttributeTag sTag[] = { kATSUFontTag, kATSUSizeTag }; + ByteCount sBytes[] = { sizeof(ATSUFontID), sizeof(Fixed) }; + ATSUAttributeValuePtr sAttr[] = { &fontID, &fsize }; + err = ATSUSetAttributes(style, 2, sTag, sBytes, sAttr); + // next, make sure that Quartz will only render at integer coordinates + ATSLineLayoutOptions llo = kATSLineUseDeviceMetrics|kATSLineDisableAllLayoutOperations; + ATSUAttributeTag aTag[] = { kATSULineLayoutOptionsTag }; + ByteCount aBytes[] = { sizeof(ATSLineLayoutOptions) }; + ATSUAttributeValuePtr aAttr[] = { &llo }; + err = ATSUSetLineControls (layout, kATSUFromTextBeginning, 1, aTag, aBytes, aAttr); + // now we are finally ready to measure some letter to get the bounding box + Fixed bBefore, bAfter, bAscent, bDescent; + err = ATSUGetUnjustifiedBounds(layout, kATSUFromTextBeginning, 1, &bBefore, &bAfter, &bAscent, &bDescent); + ascent = FixedToInt(bAscent); + descent = FixedToInt(bDescent); + q_width = FixedToInt(bAfter); #endif } @@ -97,7 +126,8 @@ Fl_FontSize::~Fl_FontSize() { */ if (this == fl_fontsize) fl_fontsize = 0; #ifdef __APPLE_QUARTZ__ - free(q_name); + ATSUDisposeTextLayout(layout); + ATSUDisposeStyle(style); #endif } @@ -161,9 +191,7 @@ void fl_font(Fl_FontSize* s) { fl_fontsize->knowMetrics = 1; } #elif defined(__APPLE_QUARTZ__) - if (!s) return; - if (!fl_gc) return; // no worries, we will assign the font to the context later - CGContextSelectFont(fl_gc, s->q_name, (float)s->size, kCGEncodingMacRoman); + // we will use fl_fontsize later to access the required style and layout #else # error : need to defined either Quartz or Quickdraw #endif @@ -212,14 +240,21 @@ double fl_width(const char* txt, int n) { if (w) w->make_current(); if (!fl_gc) return -1; } - // according to the Apple developer docs, this is the correct way to - // find the length of a rendered text... - CGContextSetTextPosition(fl_gc, 0, 0); - CGContextSetTextDrawingMode(fl_gc, kCGTextInvisible); - CGContextShowText(fl_gc, txt, n); - CGContextSetTextDrawingMode(fl_gc, kCGTextFill); - CGPoint p = CGContextGetTextPosition(fl_gc); - return p.x; + OSStatus err; + // convert to UTF-16 first + int i; + UniChar uniStr[n+1]; + for (i=0; ilayout; + err = ATSUSetTextPointerLocation(layout, uniStr, kATSUFromTextBeginning, n, n); + // now measure the bounding box + Fixed bBefore, bAfter, bAscent, bDescent; + err = ATSUGetUnjustifiedBounds(layout, kATSUFromTextBeginning, n, &bBefore, &bAfter, &bAscent, &bDescent); + return FixedToInt(bAfter); #endif } @@ -244,7 +279,18 @@ void fl_draw(const char *str, int n, float x, float y) { #ifdef __APPLE_QD__ fl_draw(str, n, (int)x, (int)y); #elif defined(__APPLE_QUARTZ__) - CGContextShowTextAtPoint(fl_gc, x, y, str, n); + OSStatus err; + // convert to UTF-16 first + int i; + UniChar uniStr[n+1]; + for (i=0; ilayout; + err = ATSUSetTextPointerLocation(layout, uniStr, kATSUFromTextBeginning, n, n); + err = ATSUDrawText(layout, kATSUFromTextBeginning, n, FloatToFixed(x), FloatToFixed(y)); #else # error : neither Quartz no Quickdraw chosen #endif -- cgit v1.2.3