* Source/GSHorizontalTypesetter.m: Use thread dictionary to hold

the instance of the typesetter for that thread.
	* Source/NSStringDrawing.m: Add locks to methods to prevent modification
	of static variables by separate threads from causing the application
	to get glyph generation errors.
	NOTE: These changes based on suggestions/ideas from Doug 
	Simons <doug@riverrock.org>.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@28219 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
gcasa 2009-04-15 01:27:42 +00:00
parent 1162ab09f8
commit a14429a2df
3 changed files with 328 additions and 183 deletions

View file

@ -1,3 +1,13 @@
2009-04-14 21:24-EDT Gregory John Casamento <greg.casamento@gmail.com>
* Source/GSHorizontalTypesetter.m: Use thread dictionary to hold
the instance of the typesetter for that thread.
* Source/NSStringDrawing.m: Add locks to methods to prevent modification
of static variables by separate threads from causing the application
to get glyph generation errors.
NOTE: These changes based on suggestions/ideas from Doug
Simons <doug@riverrock.org>.
2009-04-12 15:16-EDT Gregory John Casamento <greg_casamento@yahoo.com> 2009-04-12 15:16-EDT Gregory John Casamento <greg_casamento@yahoo.com>
* Source/GSWindowDecorationView.m: initialize offsets to prevent * Source/GSWindowDecorationView.m: initialize offsets to prevent

View file

@ -78,12 +78,21 @@ cache fairly aggressively without having to worry about memory consumption.
+(GSHorizontalTypesetter *) sharedInstance +(GSHorizontalTypesetter *) sharedInstance
{ {
static GSHorizontalTypesetter *shared; NSMutableDictionary *threadDict =
[[NSThread currentThread] threadDictionary];
GSHorizontalTypesetter *shared =
[threadDict objectForKey: @"sharedHorizontalTypesetter"];
if (!shared) if (!shared)
{
shared = [[self alloc] init]; shared = [[self alloc] init];
return shared; [threadDict setObject: shared
forKey: @"sharedHorizontalTypesetter"];
RELEASE(shared);
} }
return shared;
}
#define CACHE_INITIAL 192 #define CACHE_INITIAL 192
#define CACHE_STEP 192 #define CACHE_STEP 192

View file

@ -33,6 +33,7 @@
#include <math.h> #include <math.h>
#include <Foundation/NSException.h> #include <Foundation/NSException.h>
#include <Foundation/NSLock.h>
#include "AppKit/NSAffineTransform.h" #include "AppKit/NSAffineTransform.h"
#include "AppKit/NSLayoutManager.h" #include "AppKit/NSLayoutManager.h"
@ -88,6 +89,7 @@ static NSTextStorage *scratchTextStorage;
static NSLayoutManager *scratchLayoutManager; static NSLayoutManager *scratchLayoutManager;
static NSTextContainer *scratchTextContainer; static NSTextContainer *scratchTextContainer;
static NSRecursiveLock *cacheLock = nil;
static int total, hits, misses, hash_hits; static int total, hits, misses, hash_hits;
@ -149,6 +151,19 @@ static void init_string_drawing(void)
} }
} }
static void cache_lock()
{
if(cacheLock == nil)
{
cacheLock = [[NSRecursiveLock alloc] init];
}
[cacheLock lock];
}
static void cache_unlock()
{
[cacheLock unlock];
}
static int cache_match(int hasSize, NSSize size, int useScreenFonts, int *matched) static int cache_match(int hasSize, NSSize size, int useScreenFonts, int *matched)
{ {
@ -266,7 +281,6 @@ static int cache_lookup_string(NSString *string, NSDictionary *attributes,
if (!did_init) if (!did_init)
init_string_drawing(); init_string_drawing();
/* /*
This is a hack, but it's an efficient way of getting the layout manager This is a hack, but it's an efficient way of getting the layout manager
to just ditch all old information, and here, we don't want it to try to to just ditch all old information, and here, we don't want it to try to
@ -290,9 +304,11 @@ static int cache_lookup_string(NSString *string, NSDictionary *attributes,
[scratchTextStorage endEditing]; [scratchTextStorage endEditing];
ci = cache_match(hasSize, size, useScreenFonts, &hit); ci = cache_match(hasSize, size, useScreenFonts, &hit);
if (hit)
return ci;
if (hit)
{
return ci;
}
c = &cache[ci]; c = &cache[ci];
textStorage = c->textStorage; textStorage = c->textStorage;
@ -328,8 +344,11 @@ static int cache_lookup_attributed_string(NSAttributedString *string,
withAttributedString: string]; withAttributedString: string];
ci = cache_match(hasSize, size, useScreenFonts, &hit); ci = cache_match(hasSize, size, useScreenFonts, &hit);
if (hit) if (hit)
{
return ci; return ci;
}
c = &cache[ci]; c = &cache[ci];
@ -365,8 +384,6 @@ static int use_screen_fonts(void)
} }
} }
/* /*
This is an ugly hack to get text to display correctly in non-flipped views. This is an ugly hack to get text to display correctly in non-flipped views.
@ -389,6 +406,10 @@ glyphs to be drawn upside-down, so we need to tell NSFont to flip the fonts.
NSRange r; NSRange r;
NSGraphicsContext *ctxt = GSCurrentContext(); NSGraphicsContext *ctxt = GSCurrentContext();
cache_lock();
NS_DURING
{
ci = cache_lookup_attributed_string(self, 0, NSZeroSize, use_screen_fonts()); ci = cache_lookup_attributed_string(self, 0, NSZeroSize, use_screen_fonts());
c = &cache[ci]; c = &cache[ci];
@ -413,6 +434,14 @@ glyphs to be drawn upside-down, so we need to tell NSFont to flip the fonts.
[c->layoutManager drawGlyphsForGlyphRange: r [c->layoutManager drawGlyphsForGlyphRange: r
atPoint: point]; atPoint: point];
}
NS_HANDLER
{
cache_unlock();
[localException raise];
}
NS_ENDHANDLER;
cache_unlock();
if (![[NSView focusView] isFlipped]) if (![[NSView focusView] isFlipped])
{ {
@ -433,6 +462,11 @@ glyphs to be drawn upside-down, so we need to tell NSFont to flip the fonts.
if (rect.size.width <= 0 || rect.size.height <= 0) if (rect.size.width <= 0 || rect.size.height <= 0)
return; return;
cache_lock();
NS_DURING
{
ci = cache_lookup_attributed_string(self, 1, rect.size, use_screen_fonts()); ci = cache_lookup_attributed_string(self, 1, rect.size, use_screen_fonts());
c = &cache[ci]; c = &cache[ci];
@ -474,6 +508,14 @@ glyphs to be drawn upside-down, so we need to tell NSFont to flip the fonts.
[c->layoutManager drawGlyphsForGlyphRange: r [c->layoutManager drawGlyphsForGlyphRange: r
atPoint: rect.origin]; atPoint: rect.origin];
}
NS_HANDLER
{
cache_unlock();
[localException raise];
}
NS_ENDHANDLER;
cache_unlock();
[NSFont _setFontFlipHack: NO]; [NSFont _setFontFlipHack: NO];
if (![[NSView focusView] isFlipped]) if (![[NSView focusView] isFlipped])
@ -498,20 +540,40 @@ glyphs to be drawn upside-down, so we need to tell NSFont to flip the fonts.
- (NSSize) size - (NSSize) size
{ {
int ci; int ci;
NSSize result;
cache_lock();
NS_DURING
{
ci = cache_lookup_attributed_string(self, 0, NSZeroSize, 1); ci = cache_lookup_attributed_string(self, 0, NSZeroSize, 1);
/* /*
An argument could be made for using NSMaxX/NSMaxY here, but that fails An argument could be made for using NSMaxX/NSMaxY here, but that fails
horribly on right-aligned strings. For now, we handle that case in a horribly on right-aligned strings. For now, we handle that case in a
useful way and ignore indents. useful way and ignore indents.
*/ */
return cache[ci].usedRect.size;
result = cache[ci].usedRect.size;
}
NS_HANDLER
{
cache_unlock();
[localException raise];
}
NS_ENDHANDLER;
cache_unlock();
return result;
} }
- (NSRect) boundingRectWithSize: (NSSize)size - (NSRect) boundingRectWithSize: (NSSize)size
options: (NSStringDrawingOptions)options options: (NSStringDrawingOptions)options
{ {
int ci; int ci;
NSRect result;
cache_lock();
NS_DURING
{
// FIXME: This ignores options // FIXME: This ignores options
ci = cache_lookup_attributed_string(self, 1, size, 1); ci = cache_lookup_attributed_string(self, 1, size, 1);
/* /*
@ -519,7 +581,18 @@ glyphs to be drawn upside-down, so we need to tell NSFont to flip the fonts.
horribly on right-aligned strings. For now, we handle that case in a horribly on right-aligned strings. For now, we handle that case in a
useful way and ignore indents. useful way and ignore indents.
*/ */
return cache[ci].usedRect;
result = cache[ci].usedRect;
}
NS_HANDLER
{
cache_unlock();
[localException raise];
}
NS_ENDHANDLER;
cache_unlock();
return result;
} }
@end @end
@ -538,6 +611,9 @@ NSAttributedString to do the job.
NSRange r; NSRange r;
NSGraphicsContext *ctxt = GSCurrentContext(); NSGraphicsContext *ctxt = GSCurrentContext();
cache_lock();
NS_DURING
{
ci = cache_lookup_string(self, attrs, 0, NSZeroSize, use_screen_fonts()); ci = cache_lookup_string(self, attrs, 0, NSZeroSize, use_screen_fonts());
c = &cache[ci]; c = &cache[ci];
@ -562,6 +638,14 @@ NSAttributedString to do the job.
[c->layoutManager drawGlyphsForGlyphRange: r [c->layoutManager drawGlyphsForGlyphRange: r
atPoint: point]; atPoint: point];
}
NS_HANDLER
{
cache_unlock();
[localException raise];
}
NS_ENDHANDLER;
cache_unlock();
if (![[NSView focusView] isFlipped]) if (![[NSView focusView] isFlipped])
{ {
@ -582,6 +666,9 @@ NSAttributedString to do the job.
if (rect.size.width <= 0 || rect.size.height <= 0) if (rect.size.width <= 0 || rect.size.height <= 0)
return; return;
cache_lock();
NS_DURING
{
ci = cache_lookup_string(self, attrs, 1, rect.size, use_screen_fonts()); ci = cache_lookup_string(self, attrs, 1, rect.size, use_screen_fonts());
c = &cache[ci]; c = &cache[ci];
@ -623,6 +710,14 @@ NSAttributedString to do the job.
[c->layoutManager drawGlyphsForGlyphRange: r [c->layoutManager drawGlyphsForGlyphRange: r
atPoint: rect.origin]; atPoint: rect.origin];
}
NS_HANDLER
{
cache_unlock();
[localException raise];
}
NS_ENDHANDLER;
cache_unlock();
[NSFont _setFontFlipHack: NO]; [NSFont _setFontFlipHack: NO];
if (![[NSView focusView] isFlipped]) if (![[NSView focusView] isFlipped])
@ -648,13 +743,29 @@ NSAttributedString to do the job.
- (NSSize) sizeWithAttributes: (NSDictionary *)attrs - (NSSize) sizeWithAttributes: (NSDictionary *)attrs
{ {
int ci; int ci;
NSSize result;
cache_lock();
NS_DURING
{
ci = cache_lookup_string(self, attrs, 0, NSZeroSize, 1); ci = cache_lookup_string(self, attrs, 0, NSZeroSize, 1);
/* /*
An argument could be made for using NSMaxX/NSMaxY here, but that fails An argument could be made for using NSMaxX/NSMaxY here, but that fails
horribly on right-aligned strings (which may be the right thing). For now, horribly on right-aligned strings (which may be the right thing). For now,
we handle that case in a useful way and ignore indents. we handle that case in a useful way and ignore indents.
*/ */
return cache[ci].usedRect.size;
result = cache[ci].usedRect.size;
}
NS_HANDLER
{
cache_unlock();
[localException raise];
}
NS_ENDHANDLER;
cache_unlock();
return result;
} }
- (NSRect) boundingRectWithSize: (NSSize)size - (NSRect) boundingRectWithSize: (NSSize)size
@ -662,7 +773,11 @@ NSAttributedString to do the job.
attributes: (NSDictionary *)attributes attributes: (NSDictionary *)attributes
{ {
int ci; int ci;
NSRect result;
cache_lock();
NS_DURING
{
// FIXME: This ignores options // FIXME: This ignores options
ci = cache_lookup_string(self, attributes, 1, size, 1); ci = cache_lookup_string(self, attributes, 1, size, 1);
/* /*
@ -670,7 +785,18 @@ NSAttributedString to do the job.
horribly on right-aligned strings (which may be the right thing). For now, horribly on right-aligned strings (which may be the right thing). For now,
we handle that case in a useful way and ignore indents. we handle that case in a useful way and ignore indents.
*/ */
return cache[ci].usedRect;
result = cache[ci].usedRect;
}
NS_HANDLER
{
cache_unlock();
[localException raise];
}
NS_ENDHANDLER;
cache_unlock();
return result;
} }
@end @end