Author: matt
Date: 2011-10-02 15:34:05 -0700 (Sun, 02 Oct 2011)
New Revision: 9118
Log:
FLTK3/OSX (this should probably be applied to FLTK1.3 as well): move some code 
around for the character width caching. Caching character widths in 128 
character blocks was extremely expensive if most characters in that block need 
substitute fonts. This was very visible when opening a pulldown menu with OS X 
special charcters which would take up to two seconds on the Max! Now, if a 
substitute font is needed, we defer width calculation until the character is 
actually needed, speeding the code up by a factor of 127 in the best case.

Modified:
   branches/branch-3.0/src/fltk3/cocoa_font.cxx

Modified: branches/branch-3.0/src/fltk3/cocoa_font.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/cocoa_font.cxx        2011-10-02 19:56:19 UTC 
(rev 9117)
+++ branches/branch-3.0/src/fltk3/cocoa_font.cxx        2011-10-02 22:34:05 UTC 
(rev 9118)
@@ -296,52 +296,70 @@
 
 static double fl_mac_width(const UniChar* txt, int n, Fl_Font_Descriptor 
*fontsize) {
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
-if (fl_mac_os_version >= 100500) {
-  double retval = 0;
-  UniChar uni;
-  int i;
-  for (i = 0; i < n; i++) { // loop over txt
-    uni = txt[i];
-    if (uni >= 0xD800 && uni <= 0xDBFF) { // handles the surrogate range
-      retval += surrogate_width(&txt[i], fontsize);
-      i++; // because a pair of UniChar's represent a single character
-      continue;
-    }
-    const int block = 0x10000 / (sizeof(fontsize->width)/sizeof(float*)); // 
block size
-    // r: index of the character block containing uni
-    unsigned int r = uni >> 7; // change 7 if sizeof(width) is changed
-    if (!fontsize->width[r]) { // this character block has not been hit yet
-//fprintf(stderr,"r=%d size=%d name=%s\n",r,fltk3::fontsize->size, 
fltk3::fontsize->q_name);
-      // allocate memory to hold width of each character in the block
-      fontsize->width[r] = (float*) malloc(sizeof(float) * block);
-      UniChar ii = r * block;
-      CGSize advance_size;
-      CGGlyph glyph;
-      for (int j = 0; j < block; j++) { // loop over the block
+  if (fl_mac_os_version >= 100500) {
+    static int nEx = 0;
+    double retval = 0;
+    UniChar uni;
+    int i;
+    for (i = 0; i < n; i++) { // loop over txt
+      uni = txt[i];
+      if (uni >= 0xD800 && uni <= 0xDBFF) { // handles the surrogate range
+        retval += surrogate_width(&txt[i], fontsize);
+        i++; // because a pair of UniChar's represent a single character
+        continue;
+      }
+      const int block = 0x10000 / (sizeof(fontsize->width)/sizeof(float*)); // 
block size
+                                                                            // 
r: index of the character block containing uni
+      unsigned int r = uni >> 7; // change 7 if sizeof(width) is changed
+      if (!fontsize->width[r]) { // this character block has not been hit yet
+                                 //fprintf(stderr,"r=%d size=%d 
name=%s\n",r,fltk3::fontsize->size, fltk3::fontsize->q_name);
+                                 // allocate memory to hold width of each 
character in the block
+        fontsize->width[r] = (float*) malloc(sizeof(float) * block);
+        UniChar ii = r * block;
+        CGSize advance_size;
+        CGGlyph glyph;
+        for (int j = 0; j < block; j++) { // loop over the block
+          CTFontRef font2 = fontsize->fontref;
+          bool must_release = false;
+          // ii spans all characters of this block
+          bool b = CTFontGetGlyphsForCharacters(font2, &ii, &glyph, 1);
+          if (b) 
+            CTFontGetAdvancesForGlyphs(font2, kCTFontHorizontalOrientation, 
&glyph, &advance_size, 1);
+          else 
+            advance_size.width = -1e9; // calculate this later
+          // the width of one character of this block of characters
+          fontsize->width[r][j] = advance_size.width;
+          if (must_release) CFRelease(font2);
+          ii++;
+        }
+      }
+      // sum the widths of all characters of txt
+      double wdt = fontsize->width[r][uni & (block-1)];
+      if (wdt==-1e9) {
+        UniChar ii = uni;
+        CGSize advance_size;
+        CGGlyph glyph;
        CTFontRef font2 = fontsize->fontref;
        bool must_release = false;
        // ii spans all characters of this block
        bool b = CTFontGetGlyphsForCharacters(font2, &ii, &glyph, 1);
        if (!b) { // the current font doesn't contain this char
-         CFStringRef str = CFStringCreateWithCharactersNoCopy(NULL, &ii, 1, 
kCFAllocatorNull);
-         // find a font that contains it
-         font2 = CTFontCreateForString(font2, str, CFRangeMake(0,1));
-         must_release = true;
-         CFRelease(str);
-         b = CTFontGetGlyphsForCharacters(font2, &ii, &glyph, 1);
-         }
+          CFStringRef str = CFStringCreateWithCharactersNoCopy(NULL, &ii, 1, 
kCFAllocatorNull);
+          // find a font that contains it
+          font2 = CTFontCreateForString(font2, str, CFRangeMake(0,1));
+          must_release = true;
+          CFRelease(str);
+          b = CTFontGetGlyphsForCharacters(font2, &ii, &glyph, 1);
+        }
        if (b) CTFontGetAdvancesForGlyphs(font2, kCTFontHorizontalOrientation, 
&glyph, &advance_size, 1);
        else advance_size.width = 0.;
        // the width of one character of this block of characters
-       fontsize->width[r][j] = advance_size.width;
+       wdt = fontsize->width[r][uni & (block-1)] = advance_size.width;
        if (must_release) CFRelease(font2);
-       ii++;
       }
+      retval += wdt;
     }
-    // sum the widths of all characters of txt
-    retval += fontsize->width[r][uni & (block-1)];
-  }
-  return retval;
+    return retval;
 } else {
 #endif
 #if ! __LP64__

_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit

Reply via email to