Minor updates to glyph stuff

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@8566 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 2001-01-12 12:32:32 +00:00
parent a5bedce2f0
commit 29b391060f

View file

@ -33,6 +33,8 @@
#include <AppKit/NSWindow.h> #include <AppKit/NSWindow.h>
#include <Foundation/NSException.h> #include <Foundation/NSException.h>
#define glyphChunks ((GSIArray)_glyphChunks)
/* /*
* Glyph attributes known to the layout manager. * Glyph attributes known to the layout manager.
*/ */
@ -254,6 +256,39 @@ GSDestroyGlyphChunk(GSGlyphChunk *chunk)
NSZoneFree(NSDefaultMallocZone(), chunk); NSZoneFree(NSDefaultMallocZone(), chunk);
} }
static void
GSDestroyChunks(GSIArray *where)
{
if (*where != 0)
{
unsigned i;
/*
* Release all glyph chunk information
*/
i = GSIArrayCount(*where);
while (i-- > 0)
{
GSGlyphChunk *chunk;
chunk = (GSGlyphChunk*)(GSIArrayItemAtIndex(*where, i).ptr);
// FIXME GSRemoveGlyphChunk(glyphChunks, i);
GSDestroyGlyphChunk(chunk);
}
GSIArrayEmpty(*where);
NSZoneFree(NSDefaultMallocZone(), *where);
*where = 0;
}
}
static void
GSCreateChunks(GSIArray *where)
{
GSDestroyChunks(where);
*where = NSZoneMalloc(NSDefaultMallocZone(), sizeof(GSIArray_t));
GSIArrayInitWithZoneAndCapacity(*where, NSDefaultMallocZone(), 8);
}
static inline unsigned static inline unsigned
GSCharIndexForGlyphInChunk(GSGlyphChunk *chunk, unsigned index) GSCharIndexForGlyphInChunk(GSGlyphChunk *chunk, unsigned index)
{ {
@ -270,9 +305,17 @@ GSChunkForCharIndex(GSIArray chunks, unsigned charIndex)
tmp.charIndex = charIndex; tmp.charIndex = charIndex;
pos = GSIArrayInsertionPosition(chunks, (GSIArrayItem)(void*)&tmp, pos = GSIArrayInsertionPosition(chunks, (GSIArrayItem)(void*)&tmp,
charIndexSort); charIndexSort);
// pos is the index of the next chunk *after* the one we want. /*
* pos is the index of the next chunk *after* the one we want.
* if it is zero, we have an empty list - so we create the first chunk.
*/
if (pos == 0) if (pos == 0)
return 0; {
GSGlyphChunk *chunk = GSCreateGlyphChunk(0);
GSIArrayInsertItem(chunks, (GSIArrayItem)(void*)chunk, 0);
return chunk;
}
pos--; pos--;
return (GSGlyphChunk*)(GSIArrayItemAtIndex(chunks, pos).ptr); return (GSGlyphChunk*)(GSIArrayItemAtIndex(chunks, pos).ptr);
} }
@ -286,9 +329,17 @@ GSChunkForGlyphIndex(GSIArray chunks, unsigned glyphIndex)
tmp.glyphIndex = glyphIndex; tmp.glyphIndex = glyphIndex;
pos = GSIArrayInsertionPosition(chunks, (GSIArrayItem)(void*)&tmp, pos = GSIArrayInsertionPosition(chunks, (GSIArrayItem)(void*)&tmp,
glyphIndexSort); glyphIndexSort);
// pos is the index of the next chunk *after* the one we want. /*
* pos is the index of the next chunk *after* the one we want.
* if it is zero, we have an empty list - so we create the first chunk.
*/
if (pos == 0) if (pos == 0)
return 0; {
GSGlyphChunk *chunk = GSCreateGlyphChunk(0);
GSIArrayInsertItem(chunks, (GSIArrayItem)(void*)chunk, 0);
return chunk;
}
pos--; pos--;
return (GSGlyphChunk*)(GSIArrayItemAtIndex(chunks, pos).ptr); return (GSGlyphChunk*)(GSIArrayItemAtIndex(chunks, pos).ptr);
} }
@ -494,34 +545,13 @@ GSChunkForGlyphIndex(GSIArray chunks, unsigned glyphIndex)
_fragmentRuns = [GSRunStorage new]; _fragmentRuns = [GSRunStorage new];
_locationRuns = [GSRunStorage new]; _locationRuns = [GSRunStorage new];
_glyphChunks = NSZoneMalloc(NSDefaultMallocZone(), sizeof(GSIArray_t)); GSCreateChunks((GSIArray*)&_glyphChunks);
GSIArrayInitWithZoneAndCapacity((GSIArray)_glyphChunks,
NSDefaultMallocZone(), 8);
return self; return self;
} }
- (void) dealloc - (void) dealloc
{ {
if (_glyphChunks != 0) GSDestroyChunks((GSIArray*)&_glyphChunks);
{
unsigned i;
/*
* Release all glyph chunk information
*/
i = GSIArrayCount(_glyphChunks);
while (i-- > 0)
{
GSGlyphChunk *chunk;
chunk = (GSGlyphChunk*)(GSIArrayItemAtIndex(_glyphChunks, i).ptr);
// FIXME GSRemoveGlyphChunk((GSIArray)_glyphChunks, i);
GSDestroyGlyphChunk(chunk);
}
GSIArrayEmpty(_glyphChunks);
NSZoneFree(NSDefaultMallocZone(), _glyphChunks);
_glyphChunks = 0;
}
RELEASE (_textContainers); RELEASE (_textContainers);
RELEASE (_containerRuns); RELEASE (_containerRuns);
@ -567,19 +597,19 @@ GSChunkForGlyphIndex(GSIArray chunks, unsigned glyphIndex)
// to the new one. // to the new one.
- (void) replaceTextStorage: (NSTextStorage*)newTextStorage - (void) replaceTextStorage: (NSTextStorage*)newTextStorage
{ {
NSArray *layoutManagers = [_textStorage layoutManagers]; NSArray *layoutManagers = [_textStorage layoutManagers];
NSEnumerator *enumerator = [layoutManagers objectEnumerator]; NSEnumerator *enumerator = [layoutManagers objectEnumerator];
NSLayoutManager *object; NSLayoutManager *object;
// Remove layout managers from old NSTextStorage object and add them to the // Remove layout managers from old NSTextStorage object and add them to the
// new one. NSTextStorage's addLayoutManager invokes NSLayoutManager's // new one. NSTextStorage's addLayoutManager invokes NSLayoutManager's
// setTextStorage method automatically, and that includes self. // setTextStorage method automatically, and that includes self.
while ((object = (NSLayoutManager*)[enumerator nextObject]) != nil) while ((object = (NSLayoutManager*)[enumerator nextObject]) != nil)
{ {
[_textStorage removeLayoutManager: object]; [_textStorage removeLayoutManager: object];
[newTextStorage addLayoutManager: object]; [newTextStorage addLayoutManager: object];
} }
} }
/* /*
@ -828,7 +858,7 @@ invalidatedRange.length);
atGlyphIndex: (unsigned)glyphIndex atGlyphIndex: (unsigned)glyphIndex
characterIndex: (unsigned)charIndex characterIndex: (unsigned)charIndex
{ {
unsigned chunkCount = GSIArrayCount(_glyphChunks); unsigned chunkCount = GSIArrayCount(glyphChunks);
GSGlyphAttrs attrs = { 0 }; GSGlyphAttrs attrs = { 0 };
GSGlyphChunk *chunk; GSGlyphChunk *chunk;
@ -841,11 +871,12 @@ invalidatedRange.length);
chunk = GSCreateGlyphChunk(charIndex); chunk = GSCreateGlyphChunk(charIndex);
GSIArrayAddItem(&chunk->glyphs, (GSIArrayItem)aGlyph); GSIArrayAddItem(&chunk->glyphs, (GSIArrayItem)aGlyph);
GSIArrayAddItem(&chunk->attrs, (GSIArrayItem)attrs); GSIArrayAddItem(&chunk->attrs, (GSIArrayItem)attrs);
GSIArrayAddItem(_glyphChunks, (GSIArrayItem)(void*)chunk); GSIArrayAddItem(glyphChunks, (GSIArrayItem)(void*)chunk);
} }
else else
{ {
unsigned glyphCount; unsigned glyphCount;
unsigned glyphOffset;
unsigned chunkIndex; unsigned chunkIndex;
GSGlyphChunk tmpChunk; GSGlyphChunk tmpChunk;
unsigned pos; unsigned pos;
@ -855,26 +886,25 @@ invalidatedRange.length);
* a glyphIndex less than or equal to the index we were given. * a glyphIndex less than or equal to the index we were given.
*/ */
tmpChunk.glyphIndex = glyphIndex; tmpChunk.glyphIndex = glyphIndex;
chunkIndex = GSIArrayInsertionPosition((GSIArray)_glyphChunks, chunkIndex = GSIArrayInsertionPosition(glyphChunks,
(GSIArrayItem)(void*)&tmpChunk, glyphIndexSort); (GSIArrayItem)(void*)&tmpChunk, glyphIndexSort);
chunkIndex--; chunkIndex--;
chunk = (GSGlyphChunk*)GSIArrayItemAtIndex((GSIArray)_glyphChunks, chunk = (GSGlyphChunk*)GSIArrayItemAtIndex(glyphChunks, chunkIndex).ptr;
chunkIndex).ptr;
/* /*
* Check for the case where we have been given an index that's * Check for the case where we have been given an index that's
* beyond the end of the last chunk. * beyond the end of the last chunk.
*/ */
glyphCount = GSIArrayCount(&chunk->glyphs); glyphCount = GSIArrayCount(&chunk->glyphs);
glyphIndex -= chunk->glyphIndex; glyphOffset = glyphIndex - chunk->glyphIndex;
if (glyphIndex > glyphCount) if (glyphOffset > glyphCount)
{ {
[NSException raise: NSRangeException [NSException raise: NSRangeException
format: @"insertGlyph:glyphIndex:characterIndex: " format: @"insertGlyph:glyphIndex:characterIndex: "
@"glyph index out of range"]; @"glyph index out of range"];
} }
if (glyphIndex == 0) // Before first glyph in chunk if (glyphOffset == 0) // Before first glyph in chunk
{ {
if (chunk->charIndex < charIndex) if (chunk->charIndex < charIndex)
{ {
@ -887,7 +917,7 @@ invalidatedRange.length);
GSGlyphChunk *previous; GSGlyphChunk *previous;
unsigned c; unsigned c;
previous = (GSGlyphChunk*)GSIArrayItemAtIndex(_glyphChunks, previous = (GSGlyphChunk*)GSIArrayItemAtIndex(glyphChunks,
chunkIndex-1).ptr; chunkIndex-1).ptr;
c = GSIArrayCount(&previous->attrs); c = GSIArrayCount(&previous->attrs);
c = previous->charIndex c = previous->charIndex
@ -900,12 +930,12 @@ invalidatedRange.length);
} }
} }
} }
else if (glyphIndex == glyphCount) // After last glyph in chunk else if (glyphOffset == glyphCount) // After last glyph in chunk
{ {
unsigned c; unsigned c;
c = chunk->charIndex c = chunk->charIndex
+ (GSIArrayItemAtIndex(&chunk->attrs, glyphIndex-1).ext).offset; + (GSIArrayItemAtIndex(&chunk->attrs, glyphOffset-1).ext).offset;
if (charIndex < c) if (charIndex < c)
{ {
[NSException raise: NSRangeException [NSException raise: NSRangeException
@ -916,7 +946,7 @@ invalidatedRange.length);
{ {
GSGlyphChunk *next; GSGlyphChunk *next;
next = (GSGlyphChunk*)GSIArrayItemAtIndex(_glyphChunks, next = (GSGlyphChunk*)GSIArrayItemAtIndex(glyphChunks,
chunkIndex+1).ptr; chunkIndex+1).ptr;
if (next->charIndex < charIndex) if (next->charIndex < charIndex)
{ {
@ -932,7 +962,7 @@ invalidatedRange.length);
unsigned p; unsigned p;
p = chunk->charIndex p = chunk->charIndex
+ (GSIArrayItemAtIndex(&chunk->attrs, glyphIndex-1).ext).offset; + (GSIArrayItemAtIndex(&chunk->attrs, glyphOffset-1).ext).offset;
if (p > charIndex) if (p > charIndex)
{ {
[NSException raise: NSRangeException [NSException raise: NSRangeException
@ -940,7 +970,7 @@ invalidatedRange.length);
@"character index less than that of previous glyph"]; @"character index less than that of previous glyph"];
} }
n = chunk->charIndex n = chunk->charIndex
+ (GSIArrayItemAtIndex(&chunk->attrs, glyphIndex).ext).offset; + (GSIArrayItemAtIndex(&chunk->attrs, glyphOffset).ext).offset;
if (n < charIndex) if (n < charIndex)
{ {
[NSException raise: NSRangeException [NSException raise: NSRangeException
@ -950,31 +980,77 @@ invalidatedRange.length);
} }
/* /*
* Shall we add to the chunk or create a new one? * Shall we add to the chunk or is it big enough already?
*/ */
if (glyphCount >= 200) // arbitrary if (glyphCount > 100 && glyphCount+1 == GSIArrayCapacity(&chunk->glyphs))
{ {
// chunk = GSSplitChunk(_glyphChunks, chunkIndex, glyphIndex); /*
// chunkIndex++; * Shall we split the chunk?
// glyphIndex = 0; */
if (glyphCount == glyphOffset)
{
GSGlyphChunk *newChunk = 0;
/*
* try to insert at the start of the next chunk if possible.
*/
if (chunkIndex < chunkCount - 1)
{
GSGlyphChunk *next;
next = (GSGlyphChunk*)GSIArrayItemAtIndex(glyphChunks,
chunkIndex+1).ptr;
if (GSIArrayCount(&next->glyphs)
< GSIArrayCapacity(&next->glyphs))
{
newChunk = next;
}
}
if (newChunk == 0)
{
/*
* next chunk is too big - add a new one.
*/
newChunk = GSCreateGlyphChunk(charIndex);
GSIArrayInsertItem(glyphChunks, (GSIArrayItem)(void*)newChunk,
chunkIndex+1);
}
chunk = newChunk;
}
else
{
// chunk = GSSplitChunk(glyphChunks, chunkIndex, glyphOffset);
}
chunkIndex++;
glyphOffset = 0;
} }
if (glyphIndex == 0 && chunk->charIndex != charIndex) /*
* Special handling for insertion at the start of a chunk - we
* need to update the index values for the chunk, and (possibly)
* the character offsets of every glyph in the chunk.
*/
if (glyphOffset == 0)
{ {
int diff = chunk->charIndex - charIndex; chunk->glyphIndex = glyphIndex;
if (chunk->charIndex != charIndex)
/*
* Changing character index of entire chunk.
*/
for (pos = 0; pos < glyphCount; pos++)
{ {
GSGlyphAttrs tmp; int diff = chunk->charIndex - charIndex;
tmp = GSIArrayItemAtIndex(&chunk->attrs, pos).ext; /*
tmp.offset += diff; * Changing character index of entire chunk.
GSIArraySetItemAtIndex(&chunk->attrs, (GSIArrayItem)tmp, pos); */
for (pos = 0; pos < glyphCount; pos++)
{
GSGlyphAttrs tmp;
tmp = GSIArrayItemAtIndex(&chunk->attrs, pos).ext;
tmp.offset += diff;
GSIArraySetItemAtIndex(&chunk->attrs, (GSIArrayItem)tmp, pos);
}
} }
} }
attrs.offset = charIndex - chunk->charIndex; attrs.offset = charIndex - chunk->charIndex;
GSIArrayAddItem(&chunk->glyphs, (GSIArrayItem)aGlyph); GSIArrayAddItem(&chunk->glyphs, (GSIArrayItem)aGlyph);
GSIArrayAddItem(&chunk->attrs, (GSIArrayItem)attrs); GSIArrayAddItem(&chunk->attrs, (GSIArrayItem)attrs);
@ -985,8 +1061,7 @@ invalidatedRange.length);
*/ */
for (pos = chunkIndex+1; pos < chunkCount; pos++) for (pos = chunkIndex+1; pos < chunkCount; pos++)
{ {
chunk = (GSGlyphChunk*)GSIArrayItemAtIndex((GSIArray)_glyphChunks, chunk = (GSGlyphChunk*)GSIArrayItemAtIndex(glyphChunks, pos).ptr;
pos).ptr;
chunk->glyphIndex++; chunk->glyphIndex++;
} }
} }
@ -1015,32 +1090,18 @@ invalidatedRange.length);
- (NSGlyph) glyphAtIndex: (unsigned)index - (NSGlyph) glyphAtIndex: (unsigned)index
isValidIndex: (BOOL*)flag isValidIndex: (BOOL*)flag
{ {
unsigned numChunks; GSGlyphChunk *chunk;
unsigned total = 0;
unsigned i;
// FIXME - cheat by forcing all glyphs to be generated in -numberOfGlyphs. chunk = GSChunkForGlyphIndex(glyphChunks, index);
if (index >= [self numberOfGlyphs]) while (chunk->glyphIndex + GSIArrayCount(&chunk->glyphs) < index)
{ {
*flag = NO; break; // FIXME - should try to extend layout?
return NSNullGlyph;
} }
numChunks = GSIArrayCount(_glyphChunks); if (chunk->glyphIndex + GSIArrayCount(&chunk->glyphs) > index)
for (i = 0; i < numChunks; i++)
{ {
GSGlyphChunk *chunk; *flag = YES;
index -= chunk->glyphIndex;
chunk = (GSGlyphChunk*)GSIArrayItemAtIndex(_glyphChunks, i).ptr; return (NSGlyph)GSIArrayItemAtIndex(&chunk->glyphs, index).ulng;
if (total + GSIArrayCount(&chunk->glyphs) > index)
{
*flag = YES;
index -= total;
return (NSGlyph)GSIArrayItemAtIndex(&chunk->glyphs, index).ulng;
}
else
{
total += GSIArrayCount(&chunk->glyphs);
}
} }
*flag = NO; *flag = NO;
return NSNullGlyph; return NSNullGlyph;
@ -1053,20 +1114,22 @@ invalidatedRange.length);
withGlyph: (NSGlyph)newGlyph withGlyph: (NSGlyph)newGlyph
{ {
GSGlyphChunk *chunk; GSGlyphChunk *chunk;
unsigned glyphCount;
chunk = GSChunkForGlyphIndex((GSIArray)_glyphChunks, index); chunk = GSChunkForGlyphIndex(glyphChunks, index);
if (chunk != 0) glyphCount = GSIArrayCount(&chunk->glyphs);
if (glyphCount <= index)
{ {
unsigned glyphCount = GSIArrayCount(&chunk->glyphs); /*
* Force generation of glyphs from characters ... raises exception
index -= chunk->glyphIndex; * if the glyph index given is too large.
if (glyphCount > index) */
{ [self glyphAtIndex: index];
GSIArraySetItemAtIndex(&chunk->glyphs, (GSIArrayItem)newGlyph, index); chunk = GSChunkForGlyphIndex(glyphChunks, index);
return; glyphCount = GSIArrayCount(&chunk->glyphs);
}
} }
// FIXME ... what to do on error? index -= chunk->glyphIndex;
GSIArraySetItemAtIndex(&chunk->glyphs, (GSIArrayItem)newGlyph, index);
} }
// This causes glyph generation similarly to asking for a single // This causes glyph generation similarly to asking for a single
@ -1082,7 +1145,59 @@ invalidatedRange.length);
- (unsigned) getGlyphs: (NSGlyph*)glyphArray - (unsigned) getGlyphs: (NSGlyph*)glyphArray
range: (NSRange)glyphRange range: (NSRange)glyphRange
{ {
return (unsigned)0; unsigned packed = 0;
unsigned toFetch = glyphRange.length;
if (toFetch > 0)
{
GSGlyphChunk *chunk;
GSGlyphChunk tmp;
unsigned chunkIndex;
unsigned pos;
/*
* Force generation of glyphs to fill range.
*/
[self glyphAtIndex: NSMaxRange(glyphRange)-1];
/*
* Use binary search to locate the first chunk, and set pos to
* indicate the first glyph in the chunk that we are interested in.
*/
tmp.glyphIndex = glyphRange.location;
chunkIndex = GSIArrayInsertionPosition(glyphChunks,
(GSIArrayItem)(void*)&tmp, glyphIndexSort);
chunk = (GSGlyphChunk*)(GSIArrayItemAtIndex(glyphChunks,
--chunkIndex).ptr);
pos = glyphRange.location - chunk->glyphIndex;
/*
* Now return glyphs, excluding those 'not shown'
*/
while (toFetch-- > 0)
{
GSGlyphAttrs attrs;
attrs = GSIArrayItemAtIndex(&chunk->attrs, pos).ext;
if (attrs.isNotShown == 0)
{
glyphArray[packed++]
= (NSGlyph)GSIArrayItemAtIndex(&chunk->glyphs, pos).ulng;
}
/*
* Move on to next chunk if necessary.
*/
if (++pos == GSIArrayCount(&chunk->glyphs))
{
chunk = (GSGlyphChunk*)(GSIArrayItemAtIndex(glyphChunks,
++chunkIndex).ptr);
pos = 0;
}
}
}
glyphArray[packed] = 0;
return packed;
} }
// Removes all glyphs in the given range from the storage. // Removes all glyphs in the given range from the storage.