Author: fredkiefer
Date: Sun Feb 12 16:47:17 2017
New Revision: 40334

URL: http://svn.gna.org/viewcvs/gnustep?rev=40334&view=rev
Log:
* Source/NSStringDrawing.m: Clean up string drawing cache code.

Modified:
    libs/gui/trunk/ChangeLog
    libs/gui/trunk/Source/NSStringDrawing.m

Modified: libs/gui/trunk/ChangeLog
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/gui/trunk/ChangeLog?rev=40334&r1=40333&r2=40334&view=diff
==============================================================================
--- libs/gui/trunk/ChangeLog    (original)
+++ libs/gui/trunk/ChangeLog    Sun Feb 12 16:47:17 2017
@@ -1,3 +1,7 @@
+2017-02-12 Fred Kiefer <[email protected]>
+
+       * Source/NSStringDrawing.m: Clean up string drawing cache code.
+
 2017-01-08 Fred Kiefer <[email protected]>
 
        * Source/NSMenu.m (-_isVisible, -_isMain): Add two helper

Modified: libs/gui/trunk/Source/NSStringDrawing.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/gui/trunk/Source/NSStringDrawing.m?rev=40334&r1=40333&r2=40334&view=diff
==============================================================================
--- libs/gui/trunk/Source/NSStringDrawing.m     (original)
+++ libs/gui/trunk/Source/NSStringDrawing.m     Sun Feb 12 16:47:17 2017
@@ -3,7 +3,7 @@
    <abstract>Categories which add drawing capabilities to NSAttributedString
    and NSString.</abstract>
 
-   Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2003, 2004, 2017 Free Software Foundation, Inc.
 
    Author: Richard Frith-Macdonald <[email protected]>
    Date: Mar 1999 - rewrite from scratch
@@ -53,6 +53,8 @@
 A size of 16 and these constants give a hit rate of 80%-90% for normal app
 use (based on real world statistics gathered with the help of some users
 from #GNUstep).
+We use the last entry of the cache as a scratch element to set up an initial 
+text network.
 */
 #define NUM_CACHE_ENTRIES 16
 #define HIT_BOOST         2
@@ -62,8 +64,8 @@
 typedef struct
 {
   int used;
-  unsigned int string_hash;
-  int hasSize, useScreenFonts;
+  NSUInteger string_hash;
+  BOOL hasSize, useScreenFonts;
 
   NSTextStorage *textStorage;
   NSLayoutManager *layoutManager;
@@ -75,11 +77,8 @@
 
 
 static BOOL did_init = NO;
-static cache_t cache[NUM_CACHE_ENTRIES];
-
-static NSTextStorage   *scratchTextStorage;
-static NSLayoutManager *scratchLayoutManager;
-static NSTextContainer *scratchTextContainer;
+static cache_t cache[NUM_CACHE_ENTRIES + 1];
+
 
 static NSRecursiveLock *cacheLock = nil;
 
@@ -128,18 +127,9 @@
       [layoutManager addTextContainer: textContainer];
       [textContainer release];
       
-      if (i < NUM_CACHE_ENTRIES)
-       {
-         cache[i].textStorage = textStorage;
-         cache[i].layoutManager = layoutManager;
-         cache[i].textContainer = textContainer;
-       }
-      else
-       {
-         scratchTextStorage = textStorage;
-         scratchLayoutManager = layoutManager;
-         scratchTextContainer = textContainer;
-       }
+      cache[i].textStorage = textStorage;
+      cache[i].layoutManager = layoutManager;
+      cache[i].textContainer = textContainer;
     }
 }
 
@@ -163,13 +153,11 @@
   [cacheLock unlock];
 }
 
-static inline BOOL is_size_match(cache_t *c, int hasSize, NSSize size)
-{
-  if ((!c->hasSize && !hasSize) ||
-      (c->hasSize && hasSize && c->givenSize.width == size.width
-       && c->givenSize.height == size.height) /* ||
-      (!c->hasSize && hasSize && size.width >= NSMaxX(c->usedRect)
-      && size.height >= NSMaxY(c->usedRect))*/)
+static inline BOOL is_size_match(cache_t *c, cache_t *scratch)
+{
+  if ((!c->hasSize && !scratch->hasSize) ||
+      (c->hasSize && scratch->hasSize
+       && NSEqualSizes(c->givenSize, scratch->givenSize)))
     {
       return YES;
     }
@@ -179,21 +167,33 @@
     }
 }
 
-static int cache_match(int hasSize, NSSize size, int useScreenFonts, int 
*matched)
+static inline BOOL is_match(cache_t *c, cache_t *scratch)
+{
+  if (c->string_hash != scratch->string_hash
+      || c->useScreenFonts != scratch->useScreenFonts)
+    return NO;
+
+#ifdef STATS
+  hash_hits++;
+#endif
+
+  if (![scratch->textStorage isEqualToAttributedString: c->textStorage])
+    return NO;
+
+  /* String and attributes match, check size. */
+  return is_size_match(c, scratch);
+}
+
+static cache_t *cache_match(cache_t *scratch, BOOL *matched)
 {
   int i, j;
   cache_t *c;
-  int least_used;
-  int replace;
-  int orig_used;
-  unsigned int string_hash = [[scratchTextStorage string] hash];
+  int least_used = -1;
+  int replace = -1;
 
 #ifdef STATS
   total++;
 #endif
-
-  *matched = 1;
-  replace = least_used = -1;
 
   /*
   A deterministic pattern for replacing cache entries can hit ugly worst
@@ -206,7 +206,9 @@
   for (i = 0; i < NUM_CACHE_ENTRIES; i++, j++)
     {
       if (j == NUM_CACHE_ENTRIES)
-       j = 0;
+        {
+          j = 0;
+        }
       c = cache + j;
       if (least_used == -1 || c->used < least_used)
        {
@@ -217,32 +219,27 @@
       if (!c->used)
        continue;
 
-      orig_used = c->used;
-      if (c->used > MISS_COST)
-       c->used -= MISS_COST;
-      else
-       c->used = 1;
-
-      if (c->string_hash != string_hash
-         || c->useScreenFonts != useScreenFonts)
-       continue;
-
-#ifdef STATS
-      hash_hits++;
-#endif
-
-      if (![scratchTextStorage isEqualToAttributedString: c->textStorage])
-       continue;
-
-      /* String and attributes match, check size. */
-      if (is_size_match(c, hasSize, size))
-       {
-         c->used = orig_used + HIT_BOOST;
+      if (is_match(c, scratch))
+       {
 #ifdef STATS
          hits++;
 #endif
-         return j;
-       }
+
+         c->used += HIT_BOOST;
+          *matched = YES;
+         return c;
+       }
+      else
+        {
+          if (c->used > MISS_COST)
+            {
+              c->used -= MISS_COST;
+            }
+          else
+            {
+              c->used = 1;
+            }
+        }
     }
 
   NSCAssert(replace != -1, @"Couldn't find a cache entry to replace.");
@@ -250,30 +247,56 @@
 #ifdef STATS
   misses++;
 #endif
-  *matched = 0;
-
-  c = cache + replace;
-  c->used = 1;
-  c->string_hash = string_hash;
-  c->hasSize = hasSize;
-  c->useScreenFonts = useScreenFonts;
-  c->givenSize = size;
-
-  {
-    id temp;
-
-#define SWAP(a, b) temp = a; a = b; b = temp;
-    SWAP(scratchTextStorage, c->textStorage)
-    SWAP(scratchLayoutManager, c->layoutManager)
-    SWAP(scratchTextContainer, c->textContainer)
-#undef SWAP
-  }
-
-  return replace;
+  *matched = NO;
+
+  /* We did not find a matching entry, return the least used one */
+  return cache + replace;
+}
+
+static cache_t *cache_lookup(BOOL hasSize, NSSize size, BOOL useScreenFonts)
+{
+  BOOL hit;
+  cache_t *c;
+  cache_t *scratch = cache + NUM_CACHE_ENTRIES;
+
+  scratch->used = 1;
+  scratch->string_hash = [[scratch->textStorage string] hash];
+  scratch->hasSize = hasSize;
+  scratch->useScreenFonts = useScreenFonts;
+  scratch->givenSize = size;
+  
+  c = cache_match(scratch, &hit);
+  if (!hit)
+    {
+      // Swap c and scratch
+      cache_t temp;
+
+      temp = *c;
+      *c = *scratch;
+      *scratch = temp;
+
+      // Cache miss, need to set up the text system
+      if (hasSize)
+        {
+          [c->textContainer setContainerSize: NSMakeSize(size.width, 
size.height)];
+        }
+      else
+        {
+          [c->textContainer setContainerSize: NSMakeSize(LARGE_SIZE, 
LARGE_SIZE)];
+        }
+      [c->layoutManager setUsesScreenFonts: useScreenFonts];
+      
+      c->usedRect = [c->layoutManager usedRectForTextContainer: 
c->textContainer];
+    }
+
+  return c;
 }
 
 static inline void prepare_string(NSString *string, NSDictionary *attributes)
 {
+  cache_t *scratch = cache + NUM_CACHE_ENTRIES;
+  NSTextStorage *scratchTextStorage = scratch->textStorage;
+
   [scratchTextStorage beginEditing];
   [scratchTextStorage replaceCharactersInRange: NSMakeRange(0, 
[scratchTextStorage length])
                                     withString: string];
@@ -287,39 +310,14 @@
 
 static inline void prepare_attributed_string(NSAttributedString *string)
 {
+  cache_t *scratch = cache + NUM_CACHE_ENTRIES;
+  NSTextStorage *scratchTextStorage = scratch->textStorage;
+
   [scratchTextStorage replaceCharactersInRange: NSMakeRange(0, 
[scratchTextStorage length])
                           withAttributedString: string];
 }
 
-static int cache_lookup(int hasSize, NSSize size, int useScreenFonts)
-{
-  cache_t *c;
-  int ci, hit;
-  NSLayoutManager *layoutManager;
-  NSTextContainer *textContainer;
-
-  ci = cache_match(hasSize, size, useScreenFonts, &hit);
-  if (hit)
-    {
-      return ci;
-    }
-  // Cache miss, need to set up the text system
-  c = &cache[ci];
-  layoutManager = c->layoutManager;
-  textContainer = c->textContainer;
-  
-  if (hasSize)
-    [textContainer setContainerSize: NSMakeSize(size.width, size.height)];
-  else
-    [textContainer setContainerSize: NSMakeSize(LARGE_SIZE, LARGE_SIZE)];
-  [layoutManager setUsesScreenFonts: useScreenFonts];
-  
-  c->usedRect = [layoutManager usedRectForTextContainer: textContainer];
-
-  return ci;
-}
-
-static int use_screen_fonts(void)
+static BOOL use_screen_fonts(void)
 {
   NSGraphicsContext            *ctxt = GSCurrentContext();
   NSAffineTransform            *ctm = GSCurrentCTM(ctxt);
@@ -327,11 +325,11 @@
 
   if (ts.m11 != 1.0 || ts.m12 != 0.0 || ts.m21 != 0.0 || fabs(ts.m22) != 1.0)
     {
-      return 0;
+      return NO;
     }
   else
     {
-      return 1;
+      return YES;
     }
 }
 
@@ -351,19 +349,15 @@
 
 - (void) drawAtPoint: (NSPoint)point
 {
-  int ci;
-  cache_t *c;
-
+  cache_t *c;
   NSRange r;
   NSGraphicsContext *ctxt = GSCurrentContext();
 
   cache_lock();
-
   NS_DURING
     {
       prepare_attributed_string(self);
-      ci = cache_lookup(0, NSZeroSize, use_screen_fonts());
-      c = &cache[ci];
+      c = cache_lookup(NO, NSZeroSize, use_screen_fonts());
       
       r = NSMakeRange(0, [c->layoutManager numberOfGlyphs]);
       
@@ -412,9 +406,7 @@
               options: (NSStringDrawingOptions)options
 {
   // FIXME: This ignores options
-  int ci;
-  cache_t *c;
-
+  cache_t *c;
   NSRange r;
   BOOL need_clip = NO;
   NSGraphicsContext *ctxt = GSCurrentContext();
@@ -423,12 +415,10 @@
     return;
       
   cache_lock();
-
   NS_DURING
     {
       prepare_attributed_string(self);
-      ci = cache_lookup(1, rect.size, use_screen_fonts());
-      c = &cache[ci];
+      c = cache_lookup(YES, rect.size, use_screen_fonts());
       
       /*
        If the used rect fits completely in the rect we draw in, we save time
@@ -500,16 +490,16 @@
                         options: (NSStringDrawingOptions)options
 {
   // FIXME: This ignores options
-  int ci;
+  cache_t *c;
   NSRect result = NSZeroRect;
-  int hasSize = NSEqualSizes(NSZeroSize, size) ? 0 : 1;
+  BOOL hasSize = !NSEqualSizes(NSZeroSize, size);
 
   cache_lock();
   NS_DURING
     {    
       prepare_attributed_string(self);
-      ci = cache_lookup(hasSize, size, 1);
-      result = cache[ci].usedRect;
+      c = cache_lookup(hasSize, size, NO);
+      result = c->usedRect;
     }
   NS_HANDLER
     {
@@ -529,9 +519,7 @@
 
 - (void) drawAtPoint: (NSPoint)point withAttributes: (NSDictionary *)attrs
 {
-  int ci;
-  cache_t *c;
-
+  cache_t *c;
   NSRange r;
   NSGraphicsContext *ctxt = GSCurrentContext();
 
@@ -539,8 +527,7 @@
   NS_DURING
     {
       prepare_string(self, attrs);
-      ci = cache_lookup(0, NSZeroSize, use_screen_fonts());
-      c = &cache[ci];
+      c = cache_lookup(NO, NSZeroSize, use_screen_fonts());
       
       r = NSMakeRange(0, [c->layoutManager numberOfGlyphs]);
       
@@ -590,9 +577,7 @@
            attributes: (NSDictionary *)attrs
 {
   // FIXME: This ignores options
-  int ci;
-  cache_t *c;
-
+  cache_t *c;
   NSRange r;
   BOOL need_clip = NO;
   NSGraphicsContext *ctxt = GSCurrentContext();
@@ -604,8 +589,7 @@
   NS_DURING
     {    
       prepare_string(self, attrs);
-      ci = cache_lookup(1, rect.size, use_screen_fonts());
-      c = &cache[ci];
+      c = cache_lookup(YES, rect.size, use_screen_fonts());
       
       /*
        If the used rect fits completely in the rect we draw in, we save time
@@ -679,16 +663,16 @@
                      attributes: (NSDictionary *)attrs
 {
   // FIXME: This ignores options
-  int ci;
+  cache_t *c;
   NSRect result = NSZeroRect;
-  int hasSize = NSEqualSizes(NSZeroSize, size) ? 0 : 1;
+  BOOL hasSize = !NSEqualSizes(NSZeroSize, size);
 
   cache_lock();
   NS_DURING
     {
       prepare_string(self, attrs);
-      ci = cache_lookup(hasSize, size, 1);
-      result = cache[ci].usedRect;
+      c = cache_lookup(hasSize, size, NO);
+      result = c->usedRect;
     }
   NS_HANDLER
     {


_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs

Reply via email to