mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-05-31 19:50:48 +00:00
* 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:
parent
1162ab09f8
commit
a14429a2df
3 changed files with 328 additions and 183 deletions
10
ChangeLog
10
ChangeLog
|
@ -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>
|
||||
|
||||
* Source/GSWindowDecorationView.m: initialize offsets to prevent
|
||||
|
|
|
@ -78,12 +78,21 @@ cache fairly aggressively without having to worry about memory consumption.
|
|||
|
||||
+(GSHorizontalTypesetter *) sharedInstance
|
||||
{
|
||||
static GSHorizontalTypesetter *shared;
|
||||
NSMutableDictionary *threadDict =
|
||||
[[NSThread currentThread] threadDictionary];
|
||||
GSHorizontalTypesetter *shared =
|
||||
[threadDict objectForKey: @"sharedHorizontalTypesetter"];
|
||||
|
||||
if (!shared)
|
||||
{
|
||||
shared = [[self alloc] init];
|
||||
return shared;
|
||||
[threadDict setObject: shared
|
||||
forKey: @"sharedHorizontalTypesetter"];
|
||||
RELEASE(shared);
|
||||
}
|
||||
|
||||
return shared;
|
||||
}
|
||||
|
||||
#define CACHE_INITIAL 192
|
||||
#define CACHE_STEP 192
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <math.h>
|
||||
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSLock.h>
|
||||
|
||||
#include "AppKit/NSAffineTransform.h"
|
||||
#include "AppKit/NSLayoutManager.h"
|
||||
|
@ -88,6 +89,7 @@ static NSTextStorage *scratchTextStorage;
|
|||
static NSLayoutManager *scratchLayoutManager;
|
||||
static NSTextContainer *scratchTextContainer;
|
||||
|
||||
static NSRecursiveLock *cacheLock = nil;
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -266,7 +281,6 @@ static int cache_lookup_string(NSString *string, NSDictionary *attributes,
|
|||
if (!did_init)
|
||||
init_string_drawing();
|
||||
|
||||
|
||||
/*
|
||||
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
|
||||
|
@ -290,9 +304,11 @@ static int cache_lookup_string(NSString *string, NSDictionary *attributes,
|
|||
[scratchTextStorage endEditing];
|
||||
|
||||
ci = cache_match(hasSize, size, useScreenFonts, &hit);
|
||||
if (hit)
|
||||
return ci;
|
||||
|
||||
if (hit)
|
||||
{
|
||||
return ci;
|
||||
}
|
||||
c = &cache[ci];
|
||||
|
||||
textStorage = c->textStorage;
|
||||
|
@ -328,8 +344,11 @@ static int cache_lookup_attributed_string(NSAttributedString *string,
|
|||
withAttributedString: string];
|
||||
|
||||
ci = cache_match(hasSize, size, useScreenFonts, &hit);
|
||||
|
||||
if (hit)
|
||||
{
|
||||
return 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.
|
||||
|
||||
|
@ -389,6 +406,10 @@ glyphs to be drawn upside-down, so we need to tell NSFont to flip the fonts.
|
|||
NSRange r;
|
||||
NSGraphicsContext *ctxt = GSCurrentContext();
|
||||
|
||||
cache_lock();
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
ci = cache_lookup_attributed_string(self, 0, NSZeroSize, use_screen_fonts());
|
||||
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
|
||||
atPoint: point];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
cache_unlock();
|
||||
[localException raise];
|
||||
}
|
||||
NS_ENDHANDLER;
|
||||
cache_unlock();
|
||||
|
||||
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)
|
||||
return;
|
||||
|
||||
|
||||
cache_lock();
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
ci = cache_lookup_attributed_string(self, 1, rect.size, use_screen_fonts());
|
||||
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
|
||||
atPoint: rect.origin];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
cache_unlock();
|
||||
[localException raise];
|
||||
}
|
||||
NS_ENDHANDLER;
|
||||
cache_unlock();
|
||||
|
||||
[NSFont _setFontFlipHack: NO];
|
||||
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
|
||||
{
|
||||
int ci;
|
||||
NSSize result;
|
||||
|
||||
cache_lock();
|
||||
NS_DURING
|
||||
{
|
||||
ci = cache_lookup_attributed_string(self, 0, NSZeroSize, 1);
|
||||
/*
|
||||
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
|
||||
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
|
||||
options: (NSStringDrawingOptions)options
|
||||
{
|
||||
int ci;
|
||||
NSRect result;
|
||||
|
||||
cache_lock();
|
||||
NS_DURING
|
||||
{
|
||||
// FIXME: This ignores options
|
||||
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
|
||||
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
|
||||
|
@ -538,6 +611,9 @@ NSAttributedString to do the job.
|
|||
NSRange r;
|
||||
NSGraphicsContext *ctxt = GSCurrentContext();
|
||||
|
||||
cache_lock();
|
||||
NS_DURING
|
||||
{
|
||||
ci = cache_lookup_string(self, attrs, 0, NSZeroSize, use_screen_fonts());
|
||||
c = &cache[ci];
|
||||
|
||||
|
@ -562,6 +638,14 @@ NSAttributedString to do the job.
|
|||
|
||||
[c->layoutManager drawGlyphsForGlyphRange: r
|
||||
atPoint: point];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
cache_unlock();
|
||||
[localException raise];
|
||||
}
|
||||
NS_ENDHANDLER;
|
||||
cache_unlock();
|
||||
|
||||
if (![[NSView focusView] isFlipped])
|
||||
{
|
||||
|
@ -582,6 +666,9 @@ NSAttributedString to do the job.
|
|||
if (rect.size.width <= 0 || rect.size.height <= 0)
|
||||
return;
|
||||
|
||||
cache_lock();
|
||||
NS_DURING
|
||||
{
|
||||
ci = cache_lookup_string(self, attrs, 1, rect.size, use_screen_fonts());
|
||||
c = &cache[ci];
|
||||
|
||||
|
@ -623,6 +710,14 @@ NSAttributedString to do the job.
|
|||
|
||||
[c->layoutManager drawGlyphsForGlyphRange: r
|
||||
atPoint: rect.origin];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
cache_unlock();
|
||||
[localException raise];
|
||||
}
|
||||
NS_ENDHANDLER;
|
||||
cache_unlock();
|
||||
|
||||
[NSFont _setFontFlipHack: NO];
|
||||
if (![[NSView focusView] isFlipped])
|
||||
|
@ -648,13 +743,29 @@ NSAttributedString to do the job.
|
|||
- (NSSize) sizeWithAttributes: (NSDictionary *)attrs
|
||||
{
|
||||
int ci;
|
||||
NSSize result;
|
||||
|
||||
cache_lock();
|
||||
NS_DURING
|
||||
{
|
||||
ci = cache_lookup_string(self, attrs, 0, NSZeroSize, 1);
|
||||
/*
|
||||
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,
|
||||
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
|
||||
|
@ -662,7 +773,11 @@ NSAttributedString to do the job.
|
|||
attributes: (NSDictionary *)attributes
|
||||
{
|
||||
int ci;
|
||||
NSRect result;
|
||||
|
||||
cache_lock();
|
||||
NS_DURING
|
||||
{
|
||||
// FIXME: This ignores options
|
||||
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,
|
||||
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue