Implement extra line fragment handling.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@15968 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
alexm 2003-02-16 03:18:35 +00:00
parent b95e8bf3f4
commit 56a6fbe50d
5 changed files with 157 additions and 28 deletions

View file

@ -1,3 +1,16 @@
2003-02-16 04:14 Alexander Malmberg <alexander@malmberg.org>
* Headers/gnustep/gui/GSLayoutManager.h, Source/GSLayoutManager.m:
Add methods for setting and getting the extra line fragment
information.
* Source/GSHorizontalTypesetter.m (-layoutLineNewParagraph:): Set
the extra line fragment information as required.
* Source/NSLayoutManager.m: Use the extra line fragment information
to position the insertion point properly when it's placed after the
last character in the text.
2003-02-15 18:22 Alexander Malmberg <alexander@malmberg.org> 2003-02-15 18:22 Alexander Malmberg <alexander@malmberg.org>
* Headers/gnustep/gui/NSTextView.h, Source/NSLayoutManager.m, * Headers/gnustep/gui/NSTextView.h, Source/NSLayoutManager.m,

View file

@ -266,6 +266,21 @@ manager might be substituting screen fonts. */
effectiveRange: (NSRange *)effectiveGlyphRange; effectiveRange: (NSRange *)effectiveGlyphRange;
/*
The typesetter may set this to mark where the rectangle the insertion point
is to be placed if the insertion point is beyond the last character of the
text. The extra text container is reset to nil any time layout is
invalidated.
*/
-(void) setExtraLineFragmentRect: (NSRect)linefrag
usedRect: (NSRect)used
textContainer: (NSTextContainer *)tc;
-(NSRect) extraLineFragmentRect;
-(NSRect) extraLineFragmentUsedRect;
-(NSTextContainer *) extraLineFragmentTextContainer;
/* Extension, but without this, there's no way to get the starting locations /* Extension, but without this, there's no way to get the starting locations
of the nominally spaced glyphs. */ of the nominally spaced glyphs. */
- (NSRange) rangeOfNominallySpacedGlyphsContainingIndex:(unsigned int)glyphIndex - (NSRange) rangeOfNominallySpacedGlyphsContainingIndex:(unsigned int)glyphIndex

View file

@ -187,10 +187,10 @@ the last time or not, we wouldn't need to clear the cache every time */
cache = realloc(cache,sizeof(glyph_cache_t) * cache_size); cache = realloc(cache,sizeof(glyph_cache_t) * cache_size);
} }
for (g = &cache[cache_length];cache_length < new_length;cache_length++,g++) for (g = &cache[cache_length]; cache_length < new_length; cache_length++, g++)
{ {
g->g = [curLayoutManager glyphAtIndex: cache_base + cache_length g->g = [curLayoutManager glyphAtIndex: cache_base + cache_length
isValidIndex: &valid]; isValidIndex: &valid];
if (!valid) if (!valid)
{ {
at_end = YES; at_end = YES;
@ -444,9 +444,9 @@ restart:
tindent = [curTextContainer containerSize].width + tindent; tindent = [curTextContainer containerSize].width + tindent;
remain = NSMakeRect(hindent, remain = NSMakeRect(hindent,
curPoint.y, curPoint.y,
tindent - hindent, tindent - hindent,
line_height + [curParagraphStyle lineSpacing]); line_height + [curParagraphStyle lineSpacing]);
} }
/* /*
@ -518,6 +518,8 @@ restart:
/* /*
Main glyph layout loop. Main glyph layout loop.
*/ */
/* TODO: handling of newParagraph is ugly. must be set on all exits
from this loop */
while (1) while (1)
{ {
// printf("at %3i+%3i\n",cache_base,i); // printf("at %3i+%3i\n",cache_base,i);
@ -530,10 +532,16 @@ restart:
if (i >= cache_length) if (i >= cache_length)
{ {
if (at_end) if (at_end)
break; {
newParagraph = NO;
break;
}
[self _cacheGlyphs: cache_length + 16]; [self _cacheGlyphs: cache_length + 16];
if (i == cache_length) if (i >= cache_length)
break; {
newParagraph = NO;
break;
}
g = cache + i; g = cache + i;
} }
@ -600,7 +608,10 @@ restart:
prev_had_non_nominal_width = NO; prev_had_non_nominal_width = NO;
if (ch == 0xa) if (ch == 0xa)
break; {
newParagraph = YES;
break;
}
if (ch == 0x9) if (ch == 0x9)
{ {
@ -810,7 +821,10 @@ restart:
lf++; lf++;
lfi++; lfi++;
if (lfi == num_line_frags) if (lfi == num_line_frags)
break; {
newParagraph = NO;
break;
}
first_glyph = i; first_glyph = i;
} }
else else
@ -843,8 +857,6 @@ restart:
[self rightAlignLine: line_frags : num_line_frags]; [self rightAlignLine: line_frags : num_line_frags];
else if ([curParagraphStyle alignment] == NSCenterTextAlignment) else if ([curParagraphStyle alignment] == NSCenterTextAlignment)
[self centerAlignLine: line_frags : num_line_frags]; [self centerAlignLine: line_frags : num_line_frags];
newParagraph = YES;
} }
else else
{ {
@ -857,7 +869,6 @@ restart:
[self centerAlignLine: line_frags : num_line_frags]; [self centerAlignLine: line_frags : num_line_frags];
lfi--; lfi--;
newParagraph = NO;
} }
/* Layout is complete. Package it and give it to the layout manager. */ /* Layout is complete. Package it and give it to the layout manager. */
@ -930,8 +941,52 @@ restart:
line_frags = NULL; line_frags = NULL;
} }
/* TODO: if we're really at the end, we should probably set the extra /* Check if we're at the end. */
line frag stuff here */ {
BOOL valid;
[curLayoutManager glyphAtIndex: curGlyph
isValidIndex: &valid];
if (!valid)
{
/*
We've typeset all glyphs, and thus return 2. If we ended with a
new-line, we set the extra line frag rect here so the insertion point
will be properly positioned after a trailing newline in the text.
*/
if (newParagraph)
{
NSRect r, r2, remain;
float hindent, tindent;
hindent = [curParagraphStyle firstLineHeadIndent];
tindent = [curParagraphStyle tailIndent];
if (tindent <= 0.0)
tindent = [curTextContainer containerSize].width + tindent;
line_height = [curFont defaultLineHeightForFont];
r = NSMakeRect(hindent,
curPoint.y,
tindent - hindent,
line_height + [curParagraphStyle lineSpacing]);
r = [curTextContainer lineFragmentRectForProposedRect: r
sweepDirection: NSLineSweepRight
movementDirection: NSLineMoveDown
remainingRect: &remain];
if (!NSEqualRects(r, NSZeroRect))
{
r2 = r;
r2.size.width = 1;
[curLayoutManager setExtraLineFragmentRect: r
usedRect: r2
textContainer: curTextContainer];
}
}
return 2;
}
}
if (newParagraph) if (newParagraph)
return 3; return 3;
else else

View file

@ -1901,6 +1901,12 @@ forStartOfGlyphRange: (NSRange)glyphRange
used = NSZeroRect; used = NSZeroRect;
for (i = 0, lf = tc->linefrags; i < tc->num_linefrags; i++, lf++) for (i = 0, lf = tc->linefrags; i < tc->num_linefrags; i++, lf++)
used = NSUnionRect(used, lf->used_rect); used = NSUnionRect(used, lf->used_rect);
if (container == extra_textcontainer)
{
used = NSUnionRect(used, extra_used_rect);
}
return used; return used;
} }
@ -2024,6 +2030,32 @@ forStartOfGlyphRange: (NSRange)glyphRange
*gindex = [self firstUnlaidGlyphIndex]; *gindex = [self firstUnlaidGlyphIndex];
} }
-(void) setExtraLineFragmentRect: (NSRect)linefrag
usedRect: (NSRect)used
textContainer: (NSTextContainer *)tc
{
extra_rect = linefrag;
extra_used_rect = used;
extra_textcontainer = tc;
}
-(NSRect) extraLineFragmentRect
{
return extra_rect;
}
-(NSRect) extraLineFragmentUsedRect
{
return extra_used_rect;
}
-(NSTextContainer *) extraLineFragmentTextContainer
{
return extra_textcontainer;
}
@end @end

View file

@ -589,13 +589,8 @@ Insertion point positioning and movement.
{ {
if (cindex == [[_textStorage string] length]) if (cindex == [[_textStorage string] length])
{ {
if (!cindex) *fraction = 0.0;
{ return (unsigned int)-1;
*fraction = 0.0;
return (unsigned int)-1;
}
*fraction = 1.0;
return [self numberOfGlyphs] - 1;
} }
else else
{ {
@ -639,12 +634,29 @@ has the same y origin and height as the line frag rect it is in.
fractionThrough: &fraction_through]; fractionThrough: &fraction_through];
if (glyph_index == (unsigned int)-1) if (glyph_index == (unsigned int)-1)
{ {
if (num_textcontainers > 0) /* Need complete layout information. */
*textContainer = 0; [self _doLayout];
else if (extra_textcontainer)
*textContainer = -1; {
/* TODO: use extra rect, etc. */ for (tc = textcontainers, i = 0; i < num_textcontainers; i++, tc++)
return NSMakeRect(1,1,1,13); if (tc == textcontainers)
break;
NSAssert(i < num_textcontainers, @"invalid extraTextContainer");
*textContainer = i;
r = extra_rect;
r.size.width = 1;
return r;
}
glyph_index = [self numberOfGlyphs] - 1;
if (glyph_index == (unsigned int)-1)
{
/* No information is available. */
/* will be -1 if there are no text containers */
*textContainer = num_textcontainers - 1;
return NSMakeRect(1, 1, 1, 15);
}
fraction_through = 1.0;
} }
[self _doLayoutToGlyph: glyph_index]; [self _doLayoutToGlyph: glyph_index];
@ -861,6 +873,8 @@ has the same y origin and height as the line frag rect it is in.
} }
else else
{ {
if (i == tc->num_linefrags)
i--, lf--;
/* Find the target line. Move at least (should be up to?) /* Find the target line. Move at least (should be up to?)
distance, and at least one line. */ distance, and at least one line. */
for (; i >= 0; i--, lf--) for (; i >= 0; i--, lf--)