mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-05-30 19:40:38 +00:00
minor improvements
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@4017 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
2274bd4ecd
commit
80028023e4
2 changed files with 580 additions and 369 deletions
|
@ -1,3 +1,9 @@
|
|||
Thu Apr 1 20:45:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
|
||||
* Source/NSStringDrawing.m: improved paragraph style handling and
|
||||
added slight optimisation to restore (barely) tolerable performance.
|
||||
Further optimisation to wait until it all works properly.
|
||||
|
||||
1999-04-01 Adam Fedor <fedor@gnu.org>
|
||||
|
||||
* Model/test.m (main): Change GSContext to NSGraphicContext
|
||||
|
|
|
@ -31,54 +31,17 @@
|
|||
#include <AppKit/NSStringDrawing.h>
|
||||
#include <AppKit/AppKit.h>
|
||||
|
||||
/*
|
||||
* I know it's severely sub-optimal, but the NSString methods just
|
||||
* use NSAttributes string to do the job.
|
||||
*/
|
||||
@implementation NSString (NSStringDrawing)
|
||||
|
||||
- (void) drawAtPoint: (NSPoint)point withAttributes: (NSDictionary *)attrs
|
||||
{
|
||||
NSAttributedString *a;
|
||||
|
||||
a = [NSAttributedString allocWithZone: NSDefaultMallocZone()];
|
||||
[a initWithString: self attributes: attrs];
|
||||
[a drawAtPoint: point];
|
||||
[a release];
|
||||
}
|
||||
|
||||
- (void) drawInRect: (NSRect)rect withAttributes: (NSDictionary *)attrs
|
||||
{
|
||||
NSAttributedString *a;
|
||||
|
||||
a = [NSAttributedString allocWithZone: NSDefaultMallocZone()];
|
||||
[a initWithString: self attributes: attrs];
|
||||
[a drawInRect: rect];
|
||||
[a release];
|
||||
}
|
||||
|
||||
- (NSSize) sizeWithAttributes: (NSDictionary *)attrs
|
||||
{
|
||||
NSAttributedString *a;
|
||||
NSSize s;
|
||||
|
||||
a = [NSAttributedString allocWithZone: NSDefaultMallocZone()];
|
||||
[a initWithString: self attributes: attrs];
|
||||
s = [a size];
|
||||
[a release];
|
||||
return s;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation NSAttributedString (NSStringDrawing)
|
||||
|
||||
static NSCharacterSet *nlset;
|
||||
static NSCharacterSet *whitespace;
|
||||
static NSCharacterSet *newlines;
|
||||
static NSCharacterSet *separators;
|
||||
static NSFont *defFont;
|
||||
static NSParagraphStyle *defStyle;
|
||||
static NSColor *defFgCol;
|
||||
static NSColor *defBgCol;
|
||||
static SEL advSel = @selector(advancementForGlyph:);
|
||||
|
||||
static BOOL (*isSepImp)(NSCharacterSet*, SEL, unichar);
|
||||
|
||||
/*
|
||||
* Thne 'checkInit()' function is called to ensure that any static
|
||||
|
@ -91,17 +54,32 @@ checkInit()
|
|||
|
||||
if (beenHere == NO)
|
||||
{
|
||||
NSCharacterSet *not_ws;
|
||||
NSMutableCharacterSet *new_set;
|
||||
NSMutableCharacterSet *ms;
|
||||
|
||||
whitespace = [[NSCharacterSet whitespaceCharacterSet] retain];
|
||||
|
||||
/*
|
||||
* Build a character set containing only newline characters.
|
||||
*/
|
||||
not_ws = [[NSCharacterSet whitespaceCharacterSet] invertedSet];
|
||||
new_set = [[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy];
|
||||
[new_set formIntersectionWithCharacterSet: not_ws];
|
||||
nlset = [new_set copy];
|
||||
[new_set release];
|
||||
ms = [[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy];
|
||||
[ms formIntersectionWithCharacterSet: [whitespace invertedSet]];
|
||||
newlines = [ms copy];
|
||||
[ms release];
|
||||
|
||||
/*
|
||||
* Build a character set containing only word separators.
|
||||
*/
|
||||
#if 0 /* FIXME */
|
||||
ms = [[NSCharacterSet punctuationCharacterSet] mutableCopy];
|
||||
[ms formUnionWithCharacterSet: whitespace];
|
||||
separators = [ms copy];
|
||||
[ms release];
|
||||
#else
|
||||
separators = whitespace;
|
||||
#endif
|
||||
|
||||
isSepImp = (BOOL (*)(NSCharacterSet*, SEL, unichar))
|
||||
[separators methodForSelector: @selector(characterIsMember:)];
|
||||
|
||||
defStyle = [NSParagraphStyle defaultParagraphStyle];
|
||||
[defStyle retain];
|
||||
|
@ -117,25 +95,72 @@ checkInit()
|
|||
defFgCol = [NSColor textColor];
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
isSeparator(unichar c)
|
||||
{
|
||||
return (*isSepImp)(separators, @selector(characterIsMember:), c);
|
||||
}
|
||||
|
||||
#define ADVANCEMENT(X) (*advImp)(font, advSel, (X))
|
||||
|
||||
/*
|
||||
* The 'sizeLine()' function is called to determine the size of a single
|
||||
* line of text (specified by the 'range' argument) that may be part of
|
||||
* a larger attributed string.
|
||||
* If will also return the position of the baseline of the text within
|
||||
* the bounding rectangle as an offset from the bottom of the rectangle.
|
||||
* The 'line' range is shortened to indicate any line wrapping.
|
||||
*/
|
||||
static NSSize
|
||||
sizeLine(NSAttributedString *str, NSRange line, BOOL first, float *baseptr)
|
||||
sizeLine(NSAttributedString *str,
|
||||
NSParagraphStyle *style,
|
||||
NSRange *para,
|
||||
BOOL first,
|
||||
float *baseptr)
|
||||
{
|
||||
unsigned pos = line.location;
|
||||
unsigned end = NSMaxRange(line);
|
||||
unsigned pos = para->location;
|
||||
unsigned end = pos + para->length;
|
||||
unsigned lastSepIndex;
|
||||
float lastSepOffset;
|
||||
NSLineBreakMode lbm;
|
||||
NSArray *tabStops = [style tabStops];
|
||||
unsigned numTabs = [tabStops count];
|
||||
unsigned nextTab = 0;
|
||||
NSSize size = NSMakeSize(0, 0);
|
||||
float baseline = 0;
|
||||
float maxx;
|
||||
NSFont *oldFont = nil;
|
||||
NSSize (*advImp)(NSFont*, SEL, NSGlyph);
|
||||
|
||||
if (pos >= end)
|
||||
return size;
|
||||
|
||||
/*
|
||||
* Perform initial horizontal positioning
|
||||
*/
|
||||
if (first)
|
||||
size.width = [style firstLineHeadIndent];
|
||||
else
|
||||
size.width = [style headIndent];
|
||||
|
||||
/*
|
||||
* Initialise possible linebreak points.
|
||||
*/
|
||||
lbm = [style lineBreakMode];
|
||||
lastSepIndex = 0;
|
||||
lastSepOffset = size.width;
|
||||
|
||||
/*
|
||||
* Determine the end of a line - use a very large value if the style does
|
||||
* not give us an eol relative to our starting point.
|
||||
*/
|
||||
maxx = [style tailIndent];
|
||||
if (maxx <= 0.0)
|
||||
maxx = 1.0E8;
|
||||
|
||||
while (pos < end)
|
||||
{
|
||||
NSFont *font;
|
||||
NSParagraphStyle *style;
|
||||
int superscript;
|
||||
int ligature;
|
||||
float base;
|
||||
|
@ -155,25 +180,13 @@ sizeLine(NSAttributedString *str, NSRange line, BOOL first, float *baseptr)
|
|||
effectiveRange: &range];
|
||||
if (font == nil)
|
||||
font = defFont;
|
||||
maxRange = NSIntersectionRange(maxRange, range);
|
||||
|
||||
// Get style and range over which it applies.
|
||||
style = (NSParagraphStyle*)[str attribute: NSParagraphStyleAttributeName
|
||||
atIndex: pos
|
||||
effectiveRange: &range];
|
||||
if (style == nil)
|
||||
style = defStyle;
|
||||
maxRange = NSIntersectionRange(maxRange, range);
|
||||
/*
|
||||
* Perform initial horizontal positioning
|
||||
*/
|
||||
if (pos == line.location)
|
||||
if (font != oldFont)
|
||||
{
|
||||
if (first)
|
||||
size.width = [style firstLineHeadIndent];
|
||||
else
|
||||
size.width = [style headIndent];
|
||||
oldFont = font;
|
||||
advImp = (NSSize (*)(NSFont*, SEL, NSGlyph))
|
||||
[font methodForSelector: advSel];
|
||||
}
|
||||
maxRange = NSIntersectionRange(maxRange, range);
|
||||
|
||||
// Get baseline offset and range over which it applies.
|
||||
num = (NSNumber*)[str attribute: NSBaselineOffsetAttributeName
|
||||
|
@ -237,19 +250,25 @@ sizeLine(NSAttributedString *str, NSRange line, BOOL first, float *baseptr)
|
|||
*/
|
||||
// FIXME - ligature should have some effect on width.
|
||||
range = maxRange;
|
||||
pos = NSMaxRange(range); // Next position in string.
|
||||
if (range.length > 0)
|
||||
{
|
||||
unichar chars[range.length];
|
||||
NSArray *tabStops = [style tabStops];
|
||||
unsigned numTabs = [tabStops count];
|
||||
unsigned nextTab = 0;
|
||||
unsigned i;
|
||||
unsigned i = 0;
|
||||
float width = 0;
|
||||
|
||||
[[str string] getCharacters: chars range: range];
|
||||
for (i = 0; i < range.length; i++)
|
||||
while (i < range.length && width < maxx)
|
||||
{
|
||||
if (chars[i] == '\t')
|
||||
unsigned tabIndex = i;
|
||||
|
||||
while (tabIndex < range.length)
|
||||
{
|
||||
if (chars[tabIndex] == '\t')
|
||||
break;
|
||||
tabIndex++;
|
||||
}
|
||||
|
||||
if (tabIndex == i)
|
||||
{
|
||||
NSTextTab *tab;
|
||||
|
||||
|
@ -265,90 +284,218 @@ sizeLine(NSAttributedString *str, NSRange line, BOOL first, float *baseptr)
|
|||
nextTab++;
|
||||
}
|
||||
if (nextTab < numTabs)
|
||||
size.width = [tab location];
|
||||
width = [tab location];
|
||||
else
|
||||
size.width += [font advancementForGlyph: ' '].width;
|
||||
{
|
||||
NSSize adv;
|
||||
|
||||
adv = ADVANCEMENT(' ');
|
||||
width = size.width + adv.width;
|
||||
}
|
||||
if (width > maxx)
|
||||
break;
|
||||
/*
|
||||
* In case we need to word-wrap, we must record this
|
||||
* as a possible linebreak position.
|
||||
*/
|
||||
if (lbm == NSLineBreakByWordWrapping)
|
||||
{
|
||||
lastSepIndex = pos + i;
|
||||
lastSepOffset = size.width;
|
||||
}
|
||||
size.width = width;
|
||||
i++; // Point to next char.
|
||||
}
|
||||
else
|
||||
{
|
||||
size.width += [font advancementForGlyph: chars[i]].width;
|
||||
size.width += kern;
|
||||
while (i < tabIndex)
|
||||
{
|
||||
NSSize adv;
|
||||
|
||||
adv = ADVANCEMENT(chars[i]);
|
||||
width = size.width + adv.width + kern;
|
||||
if (width > maxx)
|
||||
break;
|
||||
if (lbm == NSLineBreakByWordWrapping
|
||||
&& isSeparator(chars[i]))
|
||||
{
|
||||
lastSepIndex = pos + i;
|
||||
lastSepOffset = size.width;
|
||||
}
|
||||
size.width = width;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (width > maxx)
|
||||
{
|
||||
if (lbm == NSLineBreakByWordWrapping)
|
||||
{
|
||||
unichar c;
|
||||
|
||||
/*
|
||||
* Word wrap - if the words are separated by whitespace
|
||||
* we discard the whitespace character - is this right?.
|
||||
*/
|
||||
pos = lastSepIndex;
|
||||
size.width = lastSepOffset;
|
||||
c = [[str string] characterAtIndex: pos];
|
||||
if ([whitespace characterIsMember: c])
|
||||
pos++;
|
||||
}
|
||||
else if (lbm == NSLineBreakByCharWrapping)
|
||||
{
|
||||
/*
|
||||
* Simply do a linebreak at the current character position.
|
||||
*/
|
||||
pos += i;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Truncate line.
|
||||
*/
|
||||
size.width = maxx;
|
||||
pos = end;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = NSMaxRange(range); // Next position in string.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust the range 'para' to specify the characters in this line.
|
||||
*/
|
||||
para->length = (pos - para->location);
|
||||
|
||||
if (baseptr)
|
||||
*baseptr = baseline;
|
||||
return size;
|
||||
}
|
||||
|
||||
/* FIXME completely ignores paragraph style attachments and other layout info */
|
||||
|
||||
/*
|
||||
* I know it's severely sub-optimal, but the NSString methods just
|
||||
* use NSAttributes string to do the job.
|
||||
*/
|
||||
@implementation NSString (NSStringDrawing)
|
||||
|
||||
- (void) drawAtPoint: (NSPoint)point withAttributes: (NSDictionary *)attrs
|
||||
{
|
||||
NSAttributedString *a;
|
||||
|
||||
a = [NSAttributedString allocWithZone: NSDefaultMallocZone()];
|
||||
[a initWithString: self attributes: attrs];
|
||||
[a drawAtPoint: point];
|
||||
[a release];
|
||||
}
|
||||
|
||||
- (void) drawInRect: (NSRect)rect withAttributes: (NSDictionary *)attrs
|
||||
{
|
||||
NSAttributedString *a;
|
||||
|
||||
a = [NSAttributedString allocWithZone: NSDefaultMallocZone()];
|
||||
[a initWithString: self attributes: attrs];
|
||||
[a drawInRect: rect];
|
||||
[a release];
|
||||
}
|
||||
|
||||
- (NSSize) sizeWithAttributes: (NSDictionary *)attrs
|
||||
{
|
||||
NSAttributedString *a;
|
||||
NSSize s;
|
||||
|
||||
a = [NSAttributedString allocWithZone: NSDefaultMallocZone()];
|
||||
[a initWithString: self attributes: attrs];
|
||||
s = [a size];
|
||||
[a release];
|
||||
return s;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation NSAttributedString (NSStringDrawing)
|
||||
|
||||
- (void) drawAtPoint: (NSPoint)point
|
||||
{
|
||||
NSGraphicsContext *ctxt = [NSGraphicsContext currentContext];
|
||||
NSString *allText = [self string];
|
||||
unsigned length = [allText length];
|
||||
unsigned linePos = 0;
|
||||
unsigned paraPos = 0;
|
||||
BOOL isFlipped = [[ctxt focusView] isFlipped];
|
||||
NSParagraphStyle *style = nil;
|
||||
BOOL first = YES;
|
||||
BOOL firstLineOfFirstPara = YES;
|
||||
NSFont *oldFont = nil;
|
||||
NSSize (*advImp)(NSFont*, SEL, NSGlyph);
|
||||
|
||||
checkInit();
|
||||
|
||||
/*
|
||||
* Now produce output on a per-line basis.
|
||||
*/
|
||||
while (linePos < length)
|
||||
while (paraPos < length)
|
||||
{
|
||||
NSRange para; // Range of current paragraph.
|
||||
NSRange line; // Range of current line.
|
||||
NSRange eol; // Rnage of newline character.
|
||||
NSRange eol; // Range of newline character.
|
||||
unsigned position; // Position in NSString.
|
||||
NSSize lineSize;
|
||||
float baseline;
|
||||
float xpos = 0;
|
||||
NSColor *bg = nil;
|
||||
float leading;
|
||||
BOOL firstLine = YES;
|
||||
|
||||
/*
|
||||
* Determine the range of the next line of text (in 'line') and set
|
||||
* 'linePos' to point after the terminating newline character (if any).
|
||||
* Determine the range of the next paragraph of text (in 'para') and set
|
||||
* 'paraPos' to point after the terminating newline character (if any).
|
||||
*/
|
||||
line = NSMakeRange(linePos, length - linePos);
|
||||
eol = [allText rangeOfCharacterFromSet: nlset
|
||||
para = NSMakeRange(paraPos, length - paraPos);
|
||||
eol = [allText rangeOfCharacterFromSet: newlines
|
||||
options: NSLiteralSearch
|
||||
range: line];
|
||||
range: para];
|
||||
|
||||
if (eol.length == 0)
|
||||
eol.location = length;
|
||||
else
|
||||
line.length = eol.location - line.location;
|
||||
linePos = NSMaxRange(eol);
|
||||
position = line.location;
|
||||
para.length = eol.location - para.location;
|
||||
paraPos = NSMaxRange(eol);
|
||||
position = para.location;
|
||||
|
||||
if (first == NO)
|
||||
do
|
||||
{
|
||||
NSParagraphStyle *newStyle;
|
||||
NSColor *bg;
|
||||
float leading;
|
||||
|
||||
if (firstLine == YES)
|
||||
{
|
||||
leading = [style paragraphSpacing];
|
||||
/*
|
||||
* Check to see if the new line begins with the same paragraph style
|
||||
* that the old ended in. This information is used to handle what
|
||||
* happens between lines and whether the new line is also a new
|
||||
* paragraph.
|
||||
* Check to see if the new line begins with the same paragraph
|
||||
* styl that the old ended in. This information is used to handle
|
||||
* what happens between lines and whether the new line is also a
|
||||
* new paragraph.
|
||||
*/
|
||||
newStyle = (NSParagraphStyle*)[self
|
||||
style = (NSParagraphStyle*)[self
|
||||
attribute: NSParagraphStyleAttributeName
|
||||
atIndex: position
|
||||
effectiveRange: 0];
|
||||
if ([style isEqual: newStyle])
|
||||
{
|
||||
leading = [style lineSpacing];
|
||||
}
|
||||
else
|
||||
{
|
||||
leading = [style paragraphSpacing];
|
||||
first = YES;
|
||||
leading = [style lineSpacing];
|
||||
}
|
||||
|
||||
if (firstLineOfFirstPara == YES)
|
||||
{
|
||||
firstLineOfFirstPara = NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isFlipped)
|
||||
point.y -= leading;
|
||||
else
|
||||
|
@ -356,7 +503,7 @@ sizeLine(NSAttributedString *str, NSRange line, BOOL first, float *baseptr)
|
|||
|
||||
/*
|
||||
* Fill the inter-line/interparagraph space with the background
|
||||
* color in use at the end of the last paragraph.
|
||||
* color in use at the end of the last line.
|
||||
*/
|
||||
bg = (NSColor*)[self attribute: NSBackgroundColorAttributeName
|
||||
atIndex: position - 1
|
||||
|
@ -381,9 +528,11 @@ sizeLine(NSAttributedString *str, NSRange line, BOOL first, float *baseptr)
|
|||
/*
|
||||
* Calculate sizing information for the entire line.
|
||||
*/
|
||||
lineSize = sizeLine(self, line, first, &baseline);
|
||||
line = para;
|
||||
lineSize = sizeLine(self, style, &line, firstLine, &baseline);
|
||||
firstLine = NO;
|
||||
|
||||
while (position < eol.location)
|
||||
while (position < NSMaxRange(line))
|
||||
{
|
||||
NSAttributedString *subAttr;
|
||||
NSString *subString;
|
||||
|
@ -410,6 +559,12 @@ sizeLine(NSAttributedString *str, NSRange line, BOOL first, float *baseptr)
|
|||
effectiveRange: &range];
|
||||
if (font == nil)
|
||||
font = defFont;
|
||||
if (font != oldFont)
|
||||
{
|
||||
oldFont = font;
|
||||
advImp = (NSSize (*)(NSFont*, SEL, NSGlyph))
|
||||
[font methodForSelector: advSel];
|
||||
}
|
||||
maxRange = NSIntersectionRange(maxRange, range);
|
||||
|
||||
// Get style and range over which it applies.
|
||||
|
@ -497,7 +652,7 @@ sizeLine(NSAttributedString *str, NSRange line, BOOL first, float *baseptr)
|
|||
fillrect.origin = point;
|
||||
fillrect.size = lineSize;
|
||||
|
||||
if (first)
|
||||
if (firstLine)
|
||||
xpos = [style firstLineHeadIndent];
|
||||
else
|
||||
xpos += [style headIndent];
|
||||
|
@ -513,10 +668,10 @@ sizeLine(NSAttributedString *str, NSRange line, BOOL first, float *baseptr)
|
|||
}
|
||||
|
||||
/*
|
||||
* Now, at last we have all the required text drawing attributes and
|
||||
* we have a range over which ALL of them apply. We update our
|
||||
* position to point past this range, then we grab the substring from
|
||||
* the range, draw it, and update our drawing position.
|
||||
* Now, at last we have all the required text drawing attributes
|
||||
* and we have a range over which ALL of them apply. We update
|
||||
* our position to point past this range, then we grab the
|
||||
* substring, draw it, and update our drawing position.
|
||||
*/
|
||||
range = maxRange;
|
||||
position = NSMaxRange(range); // Next position in string.
|
||||
|
@ -531,6 +686,7 @@ sizeLine(NSAttributedString *str, NSRange line, BOOL first, float *baseptr)
|
|||
NSArray *tabStops = [style tabStops];
|
||||
unsigned numTabs = [tabStops count];
|
||||
unsigned nextTab = 0;
|
||||
float width = xpos;
|
||||
unsigned i;
|
||||
|
||||
[[self string] getCharacters: chars range: range];
|
||||
|
@ -552,8 +708,8 @@ sizeLine(NSAttributedString *str, NSRange line, BOOL first, float *baseptr)
|
|||
NSTextTab *tab;
|
||||
|
||||
/*
|
||||
* Either advance to next tabstop or by a space
|
||||
* if there are no more tabstops.
|
||||
* Either advance to next tabstop or by
|
||||
* a space if there are no more tabstops.
|
||||
*/
|
||||
while (nextTab < numTabs)
|
||||
{
|
||||
|
@ -565,11 +721,19 @@ sizeLine(NSAttributedString *str, NSRange line, BOOL first, float *baseptr)
|
|||
if (nextTab < numTabs)
|
||||
xpos = [tab location];
|
||||
else
|
||||
xpos += [font advancementForGlyph: ' '].width;
|
||||
{
|
||||
NSSize adv;
|
||||
|
||||
adv = ADVANCEMENT(' ');
|
||||
xpos += adv.width;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
xpos += [font advancementForGlyph: chars[i]].width;
|
||||
NSSize adv;
|
||||
|
||||
adv = ADVANCEMENT(chars[i]);
|
||||
xpos += adv.width;
|
||||
xpos += kern;
|
||||
}
|
||||
}
|
||||
|
@ -599,58 +763,99 @@ sizeLine(NSAttributedString *str, NSRange line, BOOL first, float *baseptr)
|
|||
else
|
||||
ypos = point.y - lineSize.height + baseline + base;
|
||||
|
||||
for (i = 0; i < range.length; i++)
|
||||
i = 0;
|
||||
while (i < range.length)
|
||||
{
|
||||
if (chars[i] == '\t')
|
||||
unsigned tabIndex = i;
|
||||
|
||||
while (tabIndex < range.length)
|
||||
{
|
||||
if (chars[tabIndex] == '\t')
|
||||
break;
|
||||
tabIndex++;
|
||||
}
|
||||
|
||||
if (tabIndex == i)
|
||||
{
|
||||
NSTextTab *tab;
|
||||
|
||||
/*
|
||||
* Either advance to next tabstop or by a space
|
||||
* if there are no more tabstops.
|
||||
* Either advance to next tabstop or by a space if
|
||||
* there are no more tabstops.
|
||||
*/
|
||||
while (nextTab < numTabs)
|
||||
{
|
||||
tab = [tabStops objectAtIndex: nextTab];
|
||||
if ([tab location] > xpos)
|
||||
if ([tab location] > width)
|
||||
break;
|
||||
nextTab++;
|
||||
}
|
||||
if (nextTab < numTabs)
|
||||
xpos = [tab location];
|
||||
width = [tab location];
|
||||
else
|
||||
xpos += [font advancementForGlyph: ' '].width;
|
||||
{
|
||||
NSSize adv;
|
||||
|
||||
adv = ADVANCEMENT(' ');
|
||||
width += adv.width;
|
||||
}
|
||||
i++; // Point to next char.
|
||||
}
|
||||
else if (kern == 0)
|
||||
{
|
||||
char buf[tabIndex - i + 1];
|
||||
unsigned j;
|
||||
|
||||
for (j = i; j < tabIndex; j++)
|
||||
buf[j-i] = chars[j];
|
||||
buf[j-i] = '\0';
|
||||
DPSmoveto(ctxt, point.x + xpos, ypos);
|
||||
DPSshow(ctxt, buf);
|
||||
while (i < tabIndex)
|
||||
{
|
||||
NSSize adv;
|
||||
|
||||
adv = ADVANCEMENT(chars[i]);
|
||||
width += adv.width;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (i < tabIndex)
|
||||
{
|
||||
NSSize adv;
|
||||
char buf[2];
|
||||
|
||||
xpos += kern;
|
||||
DPSmoveto(ctxt, point.x + xpos, ypos);
|
||||
/*
|
||||
* FIXME Eugh - we simply assume that the unichar string
|
||||
* actually contains ascii characters and render them
|
||||
* using dpsshow
|
||||
*/
|
||||
width += kern;
|
||||
DPSmoveto(ctxt, point.x + width, ypos);
|
||||
buf[0] = chars[i];
|
||||
buf[1] = '\0';
|
||||
DPSshow(ctxt, buf);
|
||||
xpos += [font advancementForGlyph: chars[i]].width;
|
||||
adv = ADVANCEMENT(chars[i]);
|
||||
width += adv.width;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
xpos = width;
|
||||
}
|
||||
|
||||
if (underline == NSSingleUnderlineStyle)
|
||||
{
|
||||
DPSmoveto(ctxt, point.x, ypos);
|
||||
DPSlineto(ctxt, point.x + xpos - 1, ypos);
|
||||
DPSmoveto(ctxt, point.x + xpos, ypos);
|
||||
DPSlineto(ctxt, point.x + width - 1, ypos);
|
||||
}
|
||||
xpos = width;
|
||||
}
|
||||
}
|
||||
if (isFlipped)
|
||||
point.y += lineSize.height;
|
||||
else
|
||||
point.y -= lineSize.height;
|
||||
first = NO;
|
||||
firstLine = NO;
|
||||
para.length -= line.length;
|
||||
para.location += line.length;
|
||||
} while (para.location < eol.location);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue