Started reorganising the code.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@7802 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Fred Kiefer 2000-10-12 23:03:30 +00:00
parent b97acdeb63
commit 9a7641c764

View file

@ -33,6 +33,8 @@
// For the encoding functions // For the encoding functions
#include <base/Unicode.h> #include <base/Unicode.h>
#define NO_R_MARGIN 1.0E8
/* /*
* A function called by NSApplication to ensure that this file is linked * A function called by NSApplication to ensure that this file is linked
* when it should be. * when it should be.
@ -107,6 +109,7 @@ typedef struct {
typedef struct { typedef struct {
NSFont *font; // Last font used. NSFont *font; // Last font used.
NSStringEncoding enc; // The encoding of the font
NSColor *color; // Last color used. NSColor *color; // Last color used.
NSGraphicsContext *ctxt; // Drawing context. NSGraphicsContext *ctxt; // Drawing context.
BOOL flip; // If view is flipped. BOOL flip; // If view is flipped.
@ -162,6 +165,7 @@ drawRun(GSTextRun *run, NSPoint origin, GSDrawInfo *draw)
{ {
[run->font set]; [run->font set];
draw->font = run->font; draw->font = run->font;
draw->enc = [run->font mostCompatibleStringEncoding];
} }
/* /*
@ -172,7 +176,7 @@ drawRun(GSTextRun *run, NSPoint origin, GSDrawInfo *draw)
{ {
char buf[run->glyphCount + 1]; char buf[run->glyphCount + 1];
unsigned i; unsigned i;
NSStringEncoding enc = [run->font mostCompatibleStringEncoding]; NSStringEncoding enc = draw->enc;
// glyph is an unicode char value // glyph is an unicode char value
// if the font has non-standard encoding we need to remap it. // if the font has non-standard encoding we need to remap it.
@ -198,7 +202,7 @@ drawRun(GSTextRun *run, NSPoint origin, GSDrawInfo *draw)
{ {
char buf[2]; char buf[2];
unsigned i; unsigned i;
NSStringEncoding enc = [run->font mostCompatibleStringEncoding]; NSStringEncoding enc = draw->enc;
buf[1] = '\0'; buf[1] = '\0';
for (i = 0; i < run->glyphCount; i++) for (i = 0; i < run->glyphCount; i++)
@ -308,7 +312,6 @@ setupRun(GSTextRun *run, unsigned length, unichar *chars, unsigned pos,
/* /*
* Calculate height of line from font information and base offset. * Calculate height of line from font information and base offset.
* FIXME - should include superscript information here.
*/ */
below = -([run->font descender]); below = -([run->font descender]);
above = [run->font pointSize]; above = [run->font pointSize];
@ -642,7 +645,7 @@ drawLine(GSTextLine *line, NSGraphicsContext *ctxt, NSPoint origin, BOOL flip)
static GSTextChunk* static GSTextChunk*
setupLine(GSTextLine *line, NSAttributedString *str, NSRange range, setupLine(GSTextLine *line, NSAttributedString *str, NSRange range,
GSGlyphArray *g, NSParagraphStyle *style, BOOL first) GSGlyphArray *g, NSParagraphStyle *style, float rMargin, BOOL first)
{ {
GSTextChunk *lastChunk = 0; GSTextChunk *lastChunk = 0;
NSString *string = [str string]; NSString *string = [str string];
@ -652,14 +655,13 @@ setupLine(GSTextLine *line, NSAttributedString *str, NSRange range,
unsigned end = NSMaxRange(range); unsigned end = NSMaxRange(range);
unsigned numTabs = [tabs count]; unsigned numTabs = [tabs count];
unsigned nextTab = 0; unsigned nextTab = 0;
#define NO_R_MARGIN 1.0E8
line->alignment = [style alignment]; line->alignment = [style alignment];
line->lineBreakMode = [style lineBreakMode]; line->lineBreakMode = [style lineBreakMode];
line->height = [style minimumLineHeight]; line->height = [style minimumLineHeight];
line->rmargin = [style tailIndent]; line->rmargin = [style tailIndent];
if (line->rmargin <= 0.0) if (line->rmargin <= 0.0)
line->rmargin = NO_R_MARGIN; line->rmargin += rMargin;
if (first) if (first)
line->indent = [style firstLineHeadIndent]; line->indent = [style firstLineHeadIndent];
@ -811,13 +813,25 @@ setupLine(GSTextLine *line, NSAttributedString *str, NSRange range,
if (lastChunk->xpos + lastChunk->width > line->rmargin) if (lastChunk->xpos + lastChunk->width > line->rmargin)
{ {
NSLineBreakMode lbm = line->lineBreakMode; NSLineBreakMode lbm = line->lineBreakMode;
unsigned pos; unsigned pos = 0;
unisgned i;
float xpos = lastChunk->xpos;
// find the first character that does not fit on the line
for (i = chunkRange.location; i < NSMaxRange(chunkRange); i++)
{
float adv = g[i].adv.width;
if (xpos + adv > line->rmargin)
break;
xpos += adv;
}
if (lbm == NSLineBreakByWordWrapping) if (lbm == NSLineBreakByWordWrapping)
{ {
// Get break position from string // Get break position from string
pos = [str lineBreakBeforeIndex: i pos = [str lineBreakBeforeIndex: i
withinRange: range]; withinRange: chunkRange];
} }
else if (lbm == NSLineBreakByCharWrapping) else if (lbm == NSLineBreakByCharWrapping)
{ {
@ -827,8 +841,18 @@ setupLine(GSTextLine *line, NSAttributedString *str, NSRange range,
else else
{ {
// Truncate line. // Truncate line.
pos = end; //pos = NSMaxRange(chunkRange);
} }
// Break up the last chunk
// FIXME We should try to reuse as much as possible
if (pos)
{
NSRange newRange = NSMakeRange(chunkRange.location, pos-chunkRange.location);
end = pos;
empty_chunk(lastChunk);
setupChunk(lastChunk, str, newRange, g, lastChunk->last);
}
} }
*/ */
@ -855,17 +879,14 @@ setupLine(GSTextLine *line, NSAttributedString *str, NSRange range,
return 0; return 0;
} }
static void
drawAttributedString(NSAttributedString *str, NSRange aRange, NSPoint point, float width,
@implementation NSAttributedString (NSStringDrawing) NSGraphicsContext *ctxt)
- (void) drawAtPoint: (NSPoint)point
{ {
NSGraphicsContext *ctxt = GSCurrentContext();
BOOL isFlipped = [[ctxt focusView] isFlipped]; BOOL isFlipped = [[ctxt focusView] isFlipped];
NSString *allText = [self string]; NSString *allText = [str string];
unsigned length = [allText length]; unsigned length = NSMaxRange(aRange);
unsigned paraPos = 0; unsigned paraPos = aRange.location;
NSRange styleRange; NSRange styleRange;
NSParagraphStyle *style = nil; NSParagraphStyle *style = nil;
GSTextLine current; GSTextLine current;
@ -902,7 +923,7 @@ setupLine(GSTextLine *line, NSAttributedString *str, NSRange range,
{ {
if (style == nil || NSMaxRange(styleRange) > position) if (style == nil || NSMaxRange(styleRange) > position)
{ {
style = (NSParagraphStyle*)[self style = (NSParagraphStyle*)[str
attribute: NSParagraphStyleAttributeName attribute: NSParagraphStyleAttributeName
atIndex: position atIndex: position
effectiveRange: &styleRange]; effectiveRange: &styleRange];
@ -922,7 +943,7 @@ setupLine(GSTextLine *line, NSAttributedString *str, NSRange range,
garray.size = line.length; garray.size = line.length;
garray.glyphs = info; garray.glyphs = info;
setupLine(&current, self, line, &garray, style, YES); setupLine(&current, str, line, &garray, style, width, YES);
drawLine(&current, ctxt, point, isFlipped); drawLine(&current, ctxt, point, isFlipped);
if (isFlipped) if (isFlipped)
@ -939,42 +960,16 @@ setupLine(GSTextLine *line, NSAttributedString *str, NSRange range,
} }
} }
- (void) drawInRect: (NSRect)rect static NSSize
sizeAttributedString(NSAttributedString *str, NSRange aRange)
{ {
NSPoint point; NSString *allText = [str string];
NSView *view = [NSView focusView]; unsigned length = NSMaxRange(aRange);
unsigned paraPos = aRange.location;
/* FIXME: This is an extremely lossy and temporary workaround for
the fact that we should draw only inside rect. */
NSGraphicsContext *ctxt = GSCurrentContext();
DPSgsave(ctxt);
NSRectClip (rect);
/*
* Since [-drawAtPoint:] positions the top-left corner of the text at
* the point, we locate the top-left corner of the rectangle to do the
* drawing.
*/
point.x = rect.origin.x;
if ([view isFlipped])
point.y = rect.origin.y;
else
point.y = rect.origin.y + rect.size.height;
[self drawAtPoint: point];
/* Restore matching the DPSgsave used in the temporary workaround */
DPSgrestore(ctxt);
}
- (NSSize) size
{
NSString *allText = [self string];
unsigned length = [allText length];
unsigned paraPos = 0;
NSParagraphStyle *style = nil; NSParagraphStyle *style = nil;
GSTextLine current; GSTextLine current;
NSSize size = NSMakeSize(0,0); NSSize size = NSMakeSize(0,0);
float rMargin = NO_R_MARGIN;
checkInit(); checkInit();
@ -1006,7 +1001,7 @@ setupLine(GSTextLine *line, NSAttributedString *str, NSRange range,
{ {
if (firstLine == YES) if (firstLine == YES)
{ {
style = (NSParagraphStyle*)[self style = (NSParagraphStyle*)[str
attribute: NSParagraphStyleAttributeName attribute: NSParagraphStyleAttributeName
atIndex: position atIndex: position
effectiveRange: 0]; effectiveRange: 0];
@ -1021,18 +1016,13 @@ setupLine(GSTextLine *line, NSAttributedString *str, NSRange range,
{ {
GSGlyphInfo info[line.length]; GSGlyphInfo info[line.length];
GSGlyphArray garray; GSGlyphArray garray;
GSTextChunk *chunk;
garray.used = 0; garray.used = 0;
garray.glyphs = info; garray.glyphs = info;
setupLine(&current, self, line, &garray, style, YES); setupLine(&current, str, line, &garray, style, rMargin, YES);
if (current.width > size.width)
chunk = &current.chunk0; size.width = current.width;
while (chunk->next != 0)
chunk = chunk->next;
if (chunk->xpos + chunk->width > size.width)
size.width = chunk->xpos + chunk->width;
size.height += current.height + current.leading; size.height += current.height + current.leading;
emptyLine(&current); emptyLine(&current);
@ -1045,22 +1035,93 @@ setupLine(GSTextLine *line, NSAttributedString *str, NSRange range,
return size; return size;
} }
@implementation NSAttributedString (NSStringDrawing)
- (void) drawAtPoint: (NSPoint)point
{
NSGraphicsContext *ctxt = GSCurrentContext();
drawAttributedString(self, NSMakeRange(0, [self length]), point, NO_R_MARGIN,
ctxt);
}
- (void) drawInRect: (NSRect)rect
{
NSPoint point;
NSView *view = [NSView focusView];
/* FIXME: This is an extremely lossy and temporary workaround for
the fact that we should draw only inside rect. */
NSGraphicsContext *ctxt = GSCurrentContext();
DPSgsave(ctxt);
NSRectClip (rect);
/*
* Since [-drawAtPoint:] positions the top-left corner of the text at
* the point, we locate the top-left corner of the rectangle to do the
* drawing.
*/
point.x = rect.origin.x;
if ([view isFlipped])
point.y = rect.origin.y;
else
point.y = rect.origin.y + rect.size.height;
drawAttributedString(self, NSMakeRange(0, [self length]), point, rect.size.width,
ctxt);
/* Restore matching the DPSgsave used in the temporary workaround */
DPSgrestore(ctxt);
}
- (NSSize) size
{
return sizeAttributedString(self, NSMakeRange(0, [self length]));
}
// GNUstep extensions. // GNUstep extensions.
// Are they off any use?
- (NSSize) sizeRange: (NSRange) lineRange - (NSSize) sizeRange: (NSRange) lineRange
{ {
return [[self attributedSubstringFromRange: lineRange] size]; return sizeAttributedString(self, lineRange);
} }
- (void) drawRange: (NSRange) lineRange atPoint: (NSPoint) aPoint - (void) drawRange: (NSRange) lineRange atPoint: (NSPoint) point
{ {
[[self attributedSubstringFromRange: lineRange] drawAtPoint: aPoint]; NSGraphicsContext *ctxt = GSCurrentContext();
drawAttributedString(self, lineRange, point, NO_R_MARGIN,
ctxt);
} }
- (void) drawRange: (NSRange) lineRange inRect: (NSRect)aRect - (void) drawRange: (NSRange) lineRange inRect: (NSRect)rect
{ {
[[self attributedSubstringFromRange: lineRange] drawInRect: aRect]; NSPoint point;
NSView *view = [NSView focusView];
/* FIXME: This is an extremely lossy and temporary workaround for
the fact that we should draw only inside rect. */
NSGraphicsContext *ctxt = GSCurrentContext();
DPSgsave(ctxt);
NSRectClip (rect);
/*
* Since [-drawAtPoint:] positions the top-left corner of the text at
* the point, we locate the top-left corner of the rectangle to do the
* drawing.
*/
point.x = rect.origin.x;
if ([view isFlipped])
point.y = rect.origin.y;
else
point.y = rect.origin.y + rect.size.height;
drawAttributedString(self, lineRange, point, rect.size.width,
ctxt);
/* Restore matching the DPSgsave used in the temporary workaround */
DPSgrestore(ctxt);
} }
@end @end