mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-06-03 15:40:43 +00:00
Implement text attachment handling.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@15825 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
36aea1c23d
commit
132c6dc661
9 changed files with 503 additions and 85 deletions
23
ChangeLog
23
ChangeLog
|
@ -1,3 +1,26 @@
|
||||||
|
2003-01-31 21:59 Alexander Malmberg <alexander@malmberg.org>
|
||||||
|
|
||||||
|
* Headers/gnustep/gui/GSLayoutManager.h,
|
||||||
|
Headers/gnustep/gui/GSLayoutManager_internal.h,
|
||||||
|
Source/GSLayoutManager.m: Implement [GSLayoutManager
|
||||||
|
-setAttachmentSize:forGlyphRange:].
|
||||||
|
|
||||||
|
* Source/NSLayoutManager.m (-drawGlyphsForGlyphRange:atPoint:):
|
||||||
|
Implement drawing of attachments.
|
||||||
|
|
||||||
|
* Headers/gnustep/gui/NSFont.h: Add GSAttachmentGlyph to mark
|
||||||
|
attachments in a glyph context.
|
||||||
|
|
||||||
|
* Source/GSHorizontalLayoutManager.m: Cleanups and comments.
|
||||||
|
(-layoutLineNewParagraph:): Rewrite line height and baseline
|
||||||
|
handling. Implement typesetting of attachments.
|
||||||
|
|
||||||
|
* Headers/gnustep/gui/NSTextAttachment.h: Add documentation.
|
||||||
|
|
||||||
|
* Source/NSTextAttachment.m (-cellFrameForTextContainer:
|
||||||
|
proposedLineFragment:glyphPosition:characterIndex:): Return the
|
||||||
|
correct position.
|
||||||
|
|
||||||
Thu Jan 30 16:31:16 2003 Nicola Pero <n.pero@mi.flashnet.it>
|
Thu Jan 30 16:31:16 2003 Nicola Pero <n.pero@mi.flashnet.it>
|
||||||
|
|
||||||
* Source/GNUmakefile (NSMenuItem.m_FILE_FLAGS): Use -Wno-protocol
|
* Source/GNUmakefile (NSMenuItem.m_FILE_FLAGS): Use -Wno-protocol
|
||||||
|
|
|
@ -203,10 +203,6 @@ subclassing). */
|
||||||
forGlyphAtIndex: (unsigned int)glyphIndex;
|
forGlyphAtIndex: (unsigned int)glyphIndex;
|
||||||
|
|
||||||
|
|
||||||
- (void) setAttachmentSize: (NSSize)attachmentSize
|
|
||||||
forGlyphRange: (NSRange)glyphRange; /* not OPENSTEP */
|
|
||||||
|
|
||||||
|
|
||||||
/* Returns the font actually used for a range of glyphs. This isn't
|
/* Returns the font actually used for a range of glyphs. This isn't
|
||||||
necessarily the font specified by NSFontAttributeName; both the typesetter
|
necessarily the font specified by NSFontAttributeName; both the typesetter
|
||||||
and the layout manager can substitute a different font (the typesetter might
|
and the layout manager can substitute a different font (the typesetter might
|
||||||
|
@ -258,6 +254,9 @@ manager might be substituting screen fonts. */
|
||||||
- (void) setLocation: (NSPoint)location
|
- (void) setLocation: (NSPoint)location
|
||||||
forStartOfGlyphRange: (NSRange)glyphRange;
|
forStartOfGlyphRange: (NSRange)glyphRange;
|
||||||
|
|
||||||
|
- (void) setAttachmentSize: (NSSize)attachmentSize
|
||||||
|
forGlyphRange: (NSRange)glyphRange; /* not OPENSTEP */
|
||||||
|
|
||||||
|
|
||||||
- (NSTextContainer *) textContainerForGlyphAtIndex: (unsigned int)glyphIndex
|
- (NSTextContainer *) textContainerForGlyphAtIndex: (unsigned int)glyphIndex
|
||||||
effectiveRange: (NSRange *)effectiveRange;
|
effectiveRange: (NSRange *)effectiveRange;
|
||||||
|
|
|
@ -56,7 +56,7 @@ typedef struct GSLayoutManager_glyph_run_head_s
|
||||||
/* char_length must always be accurate. glyph_length is the number of
|
/* char_length must always be accurate. glyph_length is the number of
|
||||||
valid glyphs counting from the start. For a level 0 head, it's the number
|
valid glyphs counting from the start. For a level 0 head, it's the number
|
||||||
of glyphs in that run. */
|
of glyphs in that run. */
|
||||||
int glyph_length,char_length;
|
int glyph_length, char_length;
|
||||||
|
|
||||||
/* Glyph generation is complete for all created runs. */
|
/* Glyph generation is complete for all created runs. */
|
||||||
unsigned int complete:1;
|
unsigned int complete:1;
|
||||||
|
@ -135,25 +135,34 @@ typedef struct GSLayoutManager_glyph_run_s
|
||||||
/* All positions and lengths in glyphs */
|
/* All positions and lengths in glyphs */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
unsigned int pos,length;
|
unsigned int pos, length;
|
||||||
NSPoint p;
|
NSPoint p;
|
||||||
} linefrag_point_t;
|
} linefrag_point_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
NSRect rect,used_rect;
|
unsigned int pos, length;
|
||||||
unsigned int pos,length;
|
NSSize size;
|
||||||
|
} linefrag_attachment_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
NSRect rect, used_rect;
|
||||||
|
unsigned int pos, length;
|
||||||
|
|
||||||
linefrag_point_t *points;
|
linefrag_point_t *points;
|
||||||
int num_points;
|
int num_points;
|
||||||
|
|
||||||
|
linefrag_attachment_t *attachments;
|
||||||
|
int num_attachments;
|
||||||
} linefrag_t;
|
} linefrag_t;
|
||||||
|
|
||||||
typedef struct GSLayoutManager_textcontainer_s
|
typedef struct GSLayoutManager_textcontainer_s
|
||||||
{
|
{
|
||||||
NSTextContainer *textContainer;
|
NSTextContainer *textContainer;
|
||||||
|
|
||||||
BOOL started,complete;
|
BOOL started, complete;
|
||||||
unsigned int pos,length;
|
unsigned int pos, length;
|
||||||
|
|
||||||
linefrag_t *linefrags;
|
linefrag_t *linefrags;
|
||||||
int num_linefrags;
|
int num_linefrags;
|
||||||
|
@ -199,7 +208,7 @@ run, i is the glyph index in the run. */
|
||||||
|
|
||||||
/* Steps forward to the next glyph. If there is no next glyph, r will be
|
/* Steps forward to the next glyph. If there is no next glyph, r will be
|
||||||
the last run and i==r->head.glyph_length. */
|
the last run and i==r->head.glyph_length. */
|
||||||
#define GLYPH_STEP_FORWARD(r,i,pos,cpos) \
|
#define GLYPH_STEP_FORWARD(r, i, pos, cpos) \
|
||||||
{ \
|
{ \
|
||||||
i++; \
|
i++; \
|
||||||
while (i==r->head.glyph_length) \
|
while (i==r->head.glyph_length) \
|
||||||
|
@ -219,7 +228,7 @@ the last run and i==r->head.glyph_length. */
|
||||||
|
|
||||||
/* Steps backward to the previous glyph. If there is no previous glyph, r
|
/* Steps backward to the previous glyph. If there is no previous glyph, r
|
||||||
will be the first glyph and i==-1. */
|
will be the first glyph and i==-1. */
|
||||||
#define GLYPH_STEP_BACKWARD(r,i,pos,cpos) \
|
#define GLYPH_STEP_BACKWARD(r, i, pos, cpos) \
|
||||||
{ \
|
{ \
|
||||||
i--; \
|
i--; \
|
||||||
while (i<0 && r->prev) \
|
while (i<0 && r->prev) \
|
||||||
|
@ -238,11 +247,11 @@ condition holds. r, i, pos, and cpos must be simple variables. When done, r,
|
||||||
i, pos, and cpos will be set for the first glyph for which the condition
|
i, pos, and cpos will be set for the first glyph for which the condition
|
||||||
doesn't hold. If there is no such glyph, r is the last run and
|
doesn't hold. If there is no such glyph, r is the last run and
|
||||||
i==r->head.glyph_length. */
|
i==r->head.glyph_length. */
|
||||||
#define GLYPH_SCAN_FORWARD(r,i,pos,cpos,condition) \
|
#define GLYPH_SCAN_FORWARD(r, i, pos, cpos, condition) \
|
||||||
{ \
|
{ \
|
||||||
while (condition) \
|
while (condition) \
|
||||||
{ \
|
{ \
|
||||||
GLYPH_STEP_FORWARD(r,i,pos,cpos) \
|
GLYPH_STEP_FORWARD(r, i, pos, cpos) \
|
||||||
if (i==r->head.glyph_length) \
|
if (i==r->head.glyph_length) \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
|
@ -251,18 +260,18 @@ i==r->head.glyph_length. */
|
||||||
/* Scan backward. r, i, pos, and cpos will be set to the first glyph for
|
/* Scan backward. r, i, pos, and cpos will be set to the first glyph for
|
||||||
which condition doesn't hold. If there is no such glyph, r is the first run
|
which condition doesn't hold. If there is no such glyph, r is the first run
|
||||||
and i==-1. */
|
and i==-1. */
|
||||||
#define GLYPH_SCAN_BACKWARD(r,i,pos,cpos,condition) \
|
#define GLYPH_SCAN_BACKWARD(r, i, pos, cpos, condition) \
|
||||||
{ \
|
{ \
|
||||||
while (condition) \
|
while (condition) \
|
||||||
{ \
|
{ \
|
||||||
GLYPH_STEP_BACKWARD(r,i,pos,cpos) \
|
GLYPH_STEP_BACKWARD(r, i, pos, cpos) \
|
||||||
if (i==-1) \
|
if (i==-1) \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
glyph_run_t *GSLayoutManager_run_for_glyph_index(unsigned int glyphIndex,
|
glyph_run_t *GSLayoutManager_run_for_glyph_index(unsigned int glyphIndex,
|
||||||
glyph_run_head_t *glyphs,unsigned int *glyph_pos,unsigned int *char_pos);
|
glyph_run_head_t *glyphs, unsigned int *glyph_pos, unsigned int *char_pos);
|
||||||
#define run_for_glyph_index GSLayoutManager_run_for_glyph_index
|
#define run_for_glyph_index GSLayoutManager_run_for_glyph_index
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -41,6 +41,7 @@ typedef unsigned int NSGlyph;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NSControlGlyph = 0x00ffffff,
|
NSControlGlyph = 0x00ffffff,
|
||||||
|
GSAttachmentGlyph = 0x00fffffe,
|
||||||
NSNullGlyph = 0x0
|
NSNullGlyph = 0x0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -72,12 +72,47 @@ enum {
|
||||||
- (void)highlight:(BOOL)flag
|
- (void)highlight:(BOOL)flag
|
||||||
withFrame:(NSRect)cellFrame
|
withFrame:(NSRect)cellFrame
|
||||||
inView:(NSView *)controlView;
|
inView:(NSView *)controlView;
|
||||||
|
|
||||||
|
|
||||||
|
/** The old way of placing the cell. The text system will never call
|
||||||
|
these directly (TODO: make sure it doesn't), but other things might. The
|
||||||
|
class implements the new method by calling these, so subclasses can
|
||||||
|
easily change behavior by overriding these. **/
|
||||||
|
|
||||||
- (NSSize)cellSize;
|
- (NSSize)cellSize;
|
||||||
|
|
||||||
|
/* Returns the offset from the current point when typesetting to the lower
|
||||||
|
left corner of the cell. The class returns (0,0). Positive y is probably
|
||||||
|
up. (TODO) */
|
||||||
- (NSPoint)cellBaselineOffset;
|
- (NSPoint)cellBaselineOffset;
|
||||||
- (NSRect)cellFrameForTextContainer:(NSTextContainer *)textContainer
|
|
||||||
proposedLineFragment:(NSRect)lineFrag
|
|
||||||
glyphPosition:(NSPoint)position
|
/** The new way of placing the cell. **/
|
||||||
characterIndex:(unsigned)charIndex;
|
|
||||||
|
/* Returns the rectangle in which the cell should be drawn. The rectangle
|
||||||
|
is relative to the current point when typesetting. Positive y is probably
|
||||||
|
up. (TODO)
|
||||||
|
|
||||||
|
lineFrag is the line frag rect that this cell might be placed in, and
|
||||||
|
position is the current position in that line frag rect (positive y is
|
||||||
|
probably down (TODO)). Note that the line frag rect and glyph position
|
||||||
|
may not be where the cell is actually placed.
|
||||||
|
|
||||||
|
Note that this might be called many times for the same attachment. Eg. if
|
||||||
|
you return a rectangle that won't fit in the proposed line frag rect, the
|
||||||
|
typesetter might try to adjust things so it will fit. It will then send
|
||||||
|
this message with a new proposed line frag rect and glyph position. Thus,
|
||||||
|
great care must be taken when using the line frag rect to calculate the
|
||||||
|
returned rectangle to prevent the typesetting process from getting stuck.
|
||||||
|
|
||||||
|
The class uses -cellSize and -cellBaselineOffset to return a rect.
|
||||||
|
*/
|
||||||
|
-(NSRect) cellFrameForTextContainer: (NSTextContainer *)textContainer
|
||||||
|
proposedLineFragment: (NSRect)lineFrag
|
||||||
|
glyphPosition: (NSPoint)position
|
||||||
|
characterIndex: (unsigned int)charIndex;
|
||||||
|
|
||||||
|
|
||||||
- (BOOL)wantsToTrackMouse;
|
- (BOOL)wantsToTrackMouse;
|
||||||
- (BOOL)wantsToTrackMouseForEvent:(NSEvent *)theEvent
|
- (BOOL)wantsToTrackMouseForEvent:(NSEvent *)theEvent
|
||||||
inRect:(NSRect)cellFrame
|
inRect:(NSRect)cellFrame
|
||||||
|
|
|
@ -36,8 +36,15 @@
|
||||||
#include "AppKit/NSTextStorage.h"
|
#include "AppKit/NSTextStorage.h"
|
||||||
#include "AppKit/NSParagraphStyle.h"
|
#include "AppKit/NSParagraphStyle.h"
|
||||||
#include "AppKit/NSTextContainer.h"
|
#include "AppKit/NSTextContainer.h"
|
||||||
|
#include "AppKit/NSTextAttachment.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Note that unless the user creates extra instances, there will only be one
|
||||||
|
instance of GSHorizontalTypesetter for all text typesetting, so we can
|
||||||
|
cache fairly aggressively without having to worry about memory consumption.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
@implementation GSHorizontalTypesetter
|
@implementation GSHorizontalTypesetter
|
||||||
|
|
||||||
|
@ -69,6 +76,7 @@ static GSHorizontalTypesetter *shared;
|
||||||
|
|
||||||
typedef struct GSHorizontalTypesetter_glyph_cache_s
|
typedef struct GSHorizontalTypesetter_glyph_cache_s
|
||||||
{
|
{
|
||||||
|
/* These fields are filled in by the caching: */
|
||||||
NSGlyph g;
|
NSGlyph g;
|
||||||
int char_index;
|
int char_index;
|
||||||
|
|
||||||
|
@ -81,9 +89,10 @@ typedef struct GSHorizontalTypesetter_glyph_cache_s
|
||||||
int superscript;
|
int superscript;
|
||||||
} attributes;
|
} attributes;
|
||||||
|
|
||||||
|
/* These fields are filled in during layout: */
|
||||||
BOOL nominal;
|
BOOL nominal;
|
||||||
NSPoint pos; /* relative to the baseline */
|
NSPoint pos; /* relative to the line's baseline */
|
||||||
float width;
|
NSSize size; /* height is used only for attachments */
|
||||||
BOOL dont_show, outside_line_frag;
|
BOOL dont_show, outside_line_frag;
|
||||||
} glyph_cache_t;
|
} glyph_cache_t;
|
||||||
|
|
||||||
|
@ -242,11 +251,11 @@ been cached.
|
||||||
if (gi > 0)
|
if (gi > 0)
|
||||||
{
|
{
|
||||||
g->pos = g[-1].pos;
|
g->pos = g[-1].pos;
|
||||||
g->pos.x += g[-1].width;
|
g->pos.x += g[-1].size.width;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
g->pos = NSMakePoint(0,0);
|
g->pos = NSMakePoint(0,0);
|
||||||
g->width = 0;
|
g->size.width = 0;
|
||||||
return gi + 1 + cache_base;
|
return gi + 1 + cache_base;
|
||||||
}
|
}
|
||||||
gi--;
|
gi--;
|
||||||
|
@ -339,8 +348,28 @@ typedef struct
|
||||||
|
|
||||||
-(int) layoutLineNewParagraph: (BOOL)newParagraph
|
-(int) layoutLineNewParagraph: (BOOL)newParagraph
|
||||||
{
|
{
|
||||||
NSRect rect,remain;
|
NSRect rect, remain;
|
||||||
float line_height,max_line_height,baseline;
|
|
||||||
|
/* Baseline and line height handling. */
|
||||||
|
float line_height; /* Current line height. */
|
||||||
|
float max_line_height; /* Maximum line height (usually from the paragraph style). */
|
||||||
|
float baseline; /* Baseline position (0 is top of line-height, positive is down). */
|
||||||
|
float ascender; /* Amount of space we want above the baseline (always>=0). */
|
||||||
|
float descender; /* Amount of space we want below the baseline (always>=0). */
|
||||||
|
/*
|
||||||
|
These are values for the line as a whole. We start out by initializing
|
||||||
|
for the first glyph on the line and then update these as we add more
|
||||||
|
glyphs.
|
||||||
|
|
||||||
|
If we need to increase the line height, we jump back to 'restart:' and
|
||||||
|
rebuild our array of line frag rects.
|
||||||
|
|
||||||
|
(TODO (optimization): if we're dealing with a "simple rectangular
|
||||||
|
text container", we should try to extend the existing line frag in place
|
||||||
|
before jumping back to do all the expensive checking).
|
||||||
|
|
||||||
|
Normally, baseline==ascender.
|
||||||
|
*/
|
||||||
|
|
||||||
line_frag_t *line_frags = NULL;
|
line_frag_t *line_frags = NULL;
|
||||||
int num_line_frags = 0;
|
int num_line_frags = 0;
|
||||||
|
@ -352,6 +381,7 @@ typedef struct
|
||||||
if (!cache_length && at_end)
|
if (!cache_length && at_end)
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
|
/* Set up our initial baseline info. */
|
||||||
{
|
{
|
||||||
float min = [curParagraphStyle minimumLineHeight];
|
float min = [curParagraphStyle minimumLineHeight];
|
||||||
max_line_height = [curParagraphStyle maximumLineHeight];
|
max_line_height = [curParagraphStyle maximumLineHeight];
|
||||||
|
@ -361,7 +391,13 @@ typedef struct
|
||||||
max_line_height = min;
|
max_line_height = min;
|
||||||
|
|
||||||
line_height = [cache->font defaultLineHeightForFont];
|
line_height = [cache->font defaultLineHeightForFont];
|
||||||
baseline = ([cache->font ascender] + [cache->font descender] + line_height) / 2.0;
|
ascender = [cache->font ascender];
|
||||||
|
descender = [cache->font descender];
|
||||||
|
|
||||||
|
#define COMPUTE_BASELINE baseline = ascender
|
||||||
|
|
||||||
|
COMPUTE_BASELINE;
|
||||||
|
|
||||||
if (line_height < min)
|
if (line_height < min)
|
||||||
line_height = min;
|
line_height = min;
|
||||||
|
|
||||||
|
@ -371,7 +407,22 @@ typedef struct
|
||||||
|
|
||||||
/* If we find out that we need to increase the line height, we have to
|
/* If we find out that we need to increase the line height, we have to
|
||||||
start over. The increased line height might give _completely_ different
|
start over. The increased line height might give _completely_ different
|
||||||
line frag rects, so we can't reuse much of the layout information. */
|
line frag rects, so we can't reuse the layout information. */
|
||||||
|
|
||||||
|
|
||||||
|
#define WANT_LINE_HEIGHT(h) \
|
||||||
|
do { \
|
||||||
|
float __new_height = (h); \
|
||||||
|
if (max_line_height > 0 && __new_height > max_line_height) \
|
||||||
|
__new_height = max_line_height; \
|
||||||
|
if (__new_height > line_height) \
|
||||||
|
{ \
|
||||||
|
line_height = __new_height; \
|
||||||
|
COMPUTE_BASELINE; \
|
||||||
|
goto restart; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
// printf("start: at (%g %g) line_height = %g, baseline = %g\n",curPoint.x,curPoint.y,line_height,baseline);
|
// printf("start: at (%g %g) line_height = %g, baseline = %g\n",curPoint.x,curPoint.y,line_height,baseline);
|
||||||
{
|
{
|
||||||
|
@ -391,6 +442,14 @@ restart:
|
||||||
line_height + [curParagraphStyle lineSpacing]);
|
line_height + [curParagraphStyle lineSpacing]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Build a list of all line frag rects for this line.
|
||||||
|
|
||||||
|
TODO: it's very convenient to do this in advance, but it might be
|
||||||
|
inefficient, and in theory, we might end up with an insane number of line
|
||||||
|
rects (eg. a text container with "hole"-columns every 100 points and
|
||||||
|
width 1e8)
|
||||||
|
*/
|
||||||
num_line_frags = 0;
|
num_line_frags = 0;
|
||||||
if (line_frags)
|
if (line_frags)
|
||||||
{
|
{
|
||||||
|
@ -424,25 +483,42 @@ restart:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
NSFont *f = cache->font;
|
|
||||||
glyph_cache_t *g;
|
glyph_cache_t *g;
|
||||||
|
|
||||||
|
NSPoint p;
|
||||||
|
|
||||||
|
NSFont *f = cache->font;
|
||||||
|
float f_ascender = [f ascender], f_descender = [f descender];
|
||||||
|
|
||||||
NSGlyph last_glyph = NSNullGlyph;
|
NSGlyph last_glyph = NSNullGlyph;
|
||||||
NSPoint last_p,p;
|
NSPoint last_p;
|
||||||
|
|
||||||
unsigned int first_glyph;
|
unsigned int first_glyph;
|
||||||
line_frag_t *lf = line_frags;
|
line_frag_t *lf = line_frags;
|
||||||
int lfi = 0;
|
int lfi = 0;
|
||||||
|
|
||||||
|
BOOL prev_was_attachment;
|
||||||
|
|
||||||
|
|
||||||
last_p = p = NSMakePoint(0,0);
|
last_p = p = NSMakePoint(0,0);
|
||||||
|
|
||||||
g = cache;
|
g = cache;
|
||||||
first_glyph = 0;
|
first_glyph = 0;
|
||||||
|
prev_was_attachment = NO;
|
||||||
|
/*
|
||||||
|
Main glyph layout loop.
|
||||||
|
*/
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
relayout:
|
/*printf("at %3i+%2i, glyph %08x, char %04x (%i)\n",
|
||||||
|
cache_base,i,
|
||||||
|
g->g,
|
||||||
|
[[curTextStorage string] characterAtIndex: g->char_index],g->char_index);*/
|
||||||
|
|
||||||
|
/* Update the cache. */
|
||||||
if (i >= cache_length)
|
if (i >= cache_length)
|
||||||
{
|
{
|
||||||
if (at_end)
|
if (at_end)
|
||||||
|
@ -452,45 +528,184 @@ restart:
|
||||||
break;
|
break;
|
||||||
g = cache + i;
|
g = cache + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
At this point:
|
||||||
|
|
||||||
|
p is the current point (sortof); the point where a nominally
|
||||||
|
spaced glyph would be placed.
|
||||||
|
|
||||||
|
g is the current glyph. i is the current glyph index, relative to
|
||||||
|
the start of the cache.
|
||||||
|
|
||||||
|
last_p and last_glyph are used for kerning and hold the previous
|
||||||
|
glyph and its position. If there's no previous glyph (for kerning
|
||||||
|
purposes), last_glyph is NSNullGlyph and last_p is undefined.
|
||||||
|
|
||||||
|
lf and lfi track the current line frag rect. first_glyph is the
|
||||||
|
first glyph in the current line frag rect.
|
||||||
|
|
||||||
|
Note that the variables tracking the previous glyph shouldn't be
|
||||||
|
updated until we know that the current glyph will fit in the line
|
||||||
|
frag rect.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* If there's a font change, check if the baseline or line height
|
||||||
|
needs adjusting. We update the ascender and descender too, even
|
||||||
|
though there might not actually be any glyphs for this font.
|
||||||
|
(TODO?) */
|
||||||
if (g->font != f)
|
if (g->font != f)
|
||||||
{
|
{
|
||||||
float new_height;
|
float new_height, new_ascender, new_descender;
|
||||||
f = g->font;
|
f = g->font;
|
||||||
|
f_ascender = [f ascender];
|
||||||
|
f_descender = [f descender];
|
||||||
last_glyph = NSNullGlyph;
|
last_glyph = NSNullGlyph;
|
||||||
|
|
||||||
new_height = [f defaultLineHeightForFont];
|
new_height = [f defaultLineHeightForFont];
|
||||||
if (max_line_height > 0 && new_height > max_line_height)
|
new_ascender = [f ascender];
|
||||||
new_height = max_line_height;
|
new_descender = [f descender];
|
||||||
if (new_height > line_height)
|
|
||||||
{
|
if (new_ascender > ascender)
|
||||||
line_height = new_height;
|
ascender = new_ascender;
|
||||||
baseline = ([cache->font ascender] + [cache->font descender] + line_height) / 2.0;
|
if (new_descender > descender)
|
||||||
goto restart;
|
descender = new_descender;
|
||||||
}
|
|
||||||
|
COMPUTE_BASELINE;
|
||||||
|
|
||||||
|
WANT_LINE_HEIGHT(new_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g->g == NSControlGlyph)
|
if (g->g == NSControlGlyph)
|
||||||
{
|
{
|
||||||
unichar ch = [[curTextStorage string] characterAtIndex: g->char_index];
|
unichar ch = [[curTextStorage string] characterAtIndex: g->char_index];
|
||||||
|
|
||||||
|
/* TODO: need to handle other control characters */
|
||||||
|
|
||||||
g->pos = p;
|
g->pos = p;
|
||||||
g->width = 0;
|
g->size.width = 0;
|
||||||
g->dont_show = YES;
|
g->dont_show = YES;
|
||||||
g->nominal = YES;
|
g->nominal = !prev_was_attachment;
|
||||||
i++;
|
i++;
|
||||||
g++;
|
g++;
|
||||||
last_glyph = NSNullGlyph;
|
last_glyph = NSNullGlyph;
|
||||||
|
|
||||||
|
prev_was_attachment = NO;
|
||||||
|
|
||||||
if (ch == 0xa)
|
if (ch == 0xa)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
g->nominal = YES;
|
|
||||||
if (g->attributes.explicit_kern)
|
/* Set up glyph information. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
|
Currently, the attributes of the attachment character (eg. font)
|
||||||
|
affect the layout. Think hard about this.
|
||||||
|
*/
|
||||||
|
g->nominal = !prev_was_attachment;
|
||||||
|
|
||||||
|
if (g->attributes.explicit_kern &&
|
||||||
|
g->attributes.kern != 0)
|
||||||
|
{
|
||||||
p.x += g->attributes.kern;
|
p.x += g->attributes.kern;
|
||||||
|
g->nominal = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Baseline adjustments. */
|
||||||
|
{
|
||||||
|
float y = 0;
|
||||||
|
|
||||||
|
/* Attributes are up-side-down in our coordinate system. */
|
||||||
|
if (g->attributes.superscript)
|
||||||
|
{
|
||||||
|
y -= g->attributes.superscript * [f xHeight];
|
||||||
|
}
|
||||||
|
if (g->attributes.baseline_offset)
|
||||||
|
{
|
||||||
|
y -= g->attributes.baseline_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y != p.y)
|
||||||
|
{
|
||||||
|
p.y = y;
|
||||||
|
g->nominal = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The y==0 case is taken care of when the font is changed. */
|
||||||
|
if (y < 0 && f_ascender - y > ascender)
|
||||||
|
ascender = f_ascender - y;
|
||||||
|
if (y > 0 && f_descender + y > descender)
|
||||||
|
descender = f_descender + y;
|
||||||
|
|
||||||
|
COMPUTE_BASELINE;
|
||||||
|
WANT_LINE_HEIGHT(ascender + descender);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g->g == GSAttachmentGlyph)
|
||||||
|
{
|
||||||
|
NSTextAttachment *attach = [curTextStorage attribute: NSAttachmentAttributeName
|
||||||
|
atIndex: g->char_index
|
||||||
|
effectiveRange: NULL];
|
||||||
|
NSTextAttachmentCell *cell = [attach attachmentCell];
|
||||||
|
NSRect r;
|
||||||
|
|
||||||
|
if (!cell)
|
||||||
|
{
|
||||||
|
g->pos = p;
|
||||||
|
g->size = NSMakeSize(0,0);
|
||||||
|
g->dont_show = YES;
|
||||||
|
g->nominal = YES;
|
||||||
|
i++;
|
||||||
|
g++;
|
||||||
|
last_glyph = NSNullGlyph;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = [cell cellFrameForTextContainer: curTextContainer
|
||||||
|
proposedLineFragment: lf->rect
|
||||||
|
glyphPosition: p
|
||||||
|
characterIndex: g->char_index];
|
||||||
|
|
||||||
|
printf("cell at %i, (%g %g) in (%g %g)+(%g %g), got rect (%g %g)+(%g %g)\n",
|
||||||
|
g->char_index,p.x,p.y,
|
||||||
|
lf->rect.origin.x,lf->rect.origin.y,
|
||||||
|
lf->rect.size.width,lf->rect.size.height,
|
||||||
|
r.origin.x,r.origin.y,
|
||||||
|
r.size.width,r.size.height);
|
||||||
|
|
||||||
|
/* For some obscure reason, the rectangle we get is up-side-down
|
||||||
|
compared to everything else here, and has it's origin in p.
|
||||||
|
(Makes sense from the cell's pov, though.) */
|
||||||
|
|
||||||
|
if (-NSMinY(r) > descender)
|
||||||
|
descender = -NSMinY(r);
|
||||||
|
|
||||||
|
if (NSMaxY(r) > ascender)
|
||||||
|
ascender = NSMaxY(r);
|
||||||
|
|
||||||
|
/* Update ascender and descender. Adjust line height and
|
||||||
|
baseline if necessary. */
|
||||||
|
COMPUTE_BASELINE;
|
||||||
|
WANT_LINE_HEIGHT(ascender + descender);
|
||||||
|
|
||||||
|
g->size = r.size;
|
||||||
|
g->pos.x = p.x + r.origin.x;
|
||||||
|
g->pos.y = p.y + r.origin.y;
|
||||||
|
|
||||||
|
p.x = g->pos.x + g->size.width;
|
||||||
|
|
||||||
|
/* An attachment is always in a point range of its own. */
|
||||||
|
g->nominal = NO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* TODO: this is a major bottleneck */
|
/* TODO: this is a major bottleneck */
|
||||||
/* else if (last_glyph)
|
/* if (last_glyph)
|
||||||
{
|
{
|
||||||
p = [f positionOfGlyph: g->g
|
p = [f positionOfGlyph: g->g
|
||||||
precededByGlyph: last_glyph
|
precededByGlyph: last_glyph
|
||||||
|
@ -499,14 +714,17 @@ restart:
|
||||||
p.y += last_p.y;
|
p.y += last_p.y;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
|
||||||
last_p = g->pos = p;
|
last_p = g->pos = p;
|
||||||
g->width = [f advancementForGlyph: g->g].width;
|
g->size = [f advancementForGlyph: g->g]; /* only width is used */
|
||||||
p.x += g->width;
|
p.x += g->size.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Did the glyph fit in the line frag rect? */
|
||||||
if (p.x > lf->rect.size.width)
|
if (p.x > lf->rect.size.width)
|
||||||
{
|
{
|
||||||
|
/* It didn't. Try to break the line. */
|
||||||
switch ([curParagraphStyle lineBreakMode])
|
switch ([curParagraphStyle lineBreakMode])
|
||||||
{
|
{ /* TODO: implement all modes */
|
||||||
default:
|
default:
|
||||||
case NSLineBreakByCharWrapping:
|
case NSLineBreakByCharWrapping:
|
||||||
char_wrapping:
|
char_wrapping:
|
||||||
|
@ -531,22 +749,36 @@ restart:
|
||||||
g = cache + i;
|
g = cache + i;
|
||||||
/* The -1 is always valid since there's at least one glyph in the
|
/* The -1 is always valid since there's at least one glyph in the
|
||||||
line frag rect (see above). */
|
line frag rect (see above). */
|
||||||
lf->last_used = g[-1].pos.x + g[-1].width;
|
lf->last_used = g[-1].pos.x + g[-1].size.width;
|
||||||
last_glyph = NSNullGlyph;
|
last_glyph = NSNullGlyph;
|
||||||
|
prev_was_attachment = NO;
|
||||||
|
|
||||||
lf++;
|
lf++;
|
||||||
lfi++;
|
lfi++;
|
||||||
if (lfi == num_line_frags)
|
if (lfi == num_line_frags)
|
||||||
break;
|
break;
|
||||||
first_glyph = i;
|
first_glyph = i;
|
||||||
goto relayout;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Move to next glyph. */
|
||||||
last_glyph = g->g;
|
last_glyph = g->g;
|
||||||
|
if (last_glyph == GSAttachmentGlyph)
|
||||||
|
{
|
||||||
|
last_glyph = NSNullGlyph;
|
||||||
|
prev_was_attachment = YES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prev_was_attachment = NO;
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
g++;
|
g++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
/* Basic layout is done. */
|
||||||
|
|
||||||
|
/* Take care of the alignments. */
|
||||||
if (lfi != num_line_frags)
|
if (lfi != num_line_frags)
|
||||||
{
|
{
|
||||||
lf->last_glyph = i;
|
lf->last_glyph = i;
|
||||||
|
@ -574,17 +806,18 @@ restart:
|
||||||
newParagraph = NO;
|
newParagraph = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Layout is complete. Package it and give it to the layout manager. */
|
||||||
[curLayoutManager setTextContainer: curTextContainer
|
[curLayoutManager setTextContainer: curTextContainer
|
||||||
forGlyphRange: NSMakeRange(cache_base,i)];
|
forGlyphRange: NSMakeRange(cache_base, i)];
|
||||||
curGlyph = i + cache_base;
|
curGlyph = i + cache_base;
|
||||||
{
|
{
|
||||||
line_frag_t *lf;
|
line_frag_t *lf;
|
||||||
NSPoint p;
|
NSPoint p;
|
||||||
unsigned int i,j;
|
unsigned int i, j;
|
||||||
glyph_cache_t *g;
|
glyph_cache_t *g;
|
||||||
NSRect used_rect;
|
NSRect used_rect;
|
||||||
|
|
||||||
for (lf = line_frags,i = 0,g = cache;lfi >= 0;lfi--,lf++)
|
for (lf = line_frags, i = 0, g = cache; lfi >= 0; lfi--, lf++)
|
||||||
{
|
{
|
||||||
used_rect.origin.x = g->pos.x + lf->rect.origin.x;
|
used_rect.origin.x = g->pos.x + lf->rect.origin.x;
|
||||||
used_rect.size.width = lf->last_used - g->pos.x;
|
used_rect.size.width = lf->last_used - g->pos.x;
|
||||||
|
@ -596,6 +829,7 @@ restart:
|
||||||
forGlyphRange: NSMakeRange(cache_base + i,lf->last_glyph - i)
|
forGlyphRange: NSMakeRange(cache_base + i,lf->last_glyph - i)
|
||||||
usedRect: used_rect];
|
usedRect: used_rect];
|
||||||
p = g->pos;
|
p = g->pos;
|
||||||
|
/* TODO: probably don't need to call unless the flags are YES */
|
||||||
[curLayoutManager setDrawsOutsideLineFragment: g->outside_line_frag
|
[curLayoutManager setDrawsOutsideLineFragment: g->outside_line_frag
|
||||||
forGlyphAtIndex: cache_base + i];
|
forGlyphAtIndex: cache_base + i];
|
||||||
[curLayoutManager setNotShownAttribute: g->dont_show
|
[curLayoutManager setNotShownAttribute: g->dont_show
|
||||||
|
@ -607,7 +841,12 @@ restart:
|
||||||
if (!g->nominal && i != j)
|
if (!g->nominal && i != j)
|
||||||
{
|
{
|
||||||
[curLayoutManager setLocation: p
|
[curLayoutManager setLocation: p
|
||||||
forStartOfGlyphRange: NSMakeRange(cache_base + j,i - j)];
|
forStartOfGlyphRange: NSMakeRange(cache_base + j, i - j)];
|
||||||
|
if (g[-1].g == GSAttachmentGlyph)
|
||||||
|
{
|
||||||
|
[curLayoutManager setAttachmentSize: g[-1].size
|
||||||
|
forGlyphRange: NSMakeRange(cache_base + j, i - j)];
|
||||||
|
}
|
||||||
p = g->pos;
|
p = g->pos;
|
||||||
p.y += baseline;
|
p.y += baseline;
|
||||||
j = i;
|
j = i;
|
||||||
|
@ -619,6 +858,11 @@ restart:
|
||||||
{
|
{
|
||||||
[curLayoutManager setLocation: p
|
[curLayoutManager setLocation: p
|
||||||
forStartOfGlyphRange: NSMakeRange(cache_base + j,i - j)];
|
forStartOfGlyphRange: NSMakeRange(cache_base + j,i - j)];
|
||||||
|
if (g[-1].g == GSAttachmentGlyph)
|
||||||
|
{
|
||||||
|
[curLayoutManager setAttachmentSize: g[-1].size
|
||||||
|
forGlyphRange: NSMakeRange(cache_base + j, i - j)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -632,8 +876,8 @@ restart:
|
||||||
line_frags = NULL;
|
line_frags = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we're really at the end, we should probably set the extra line frag
|
/* TODO: if we're really at the end, we should probably set the extra
|
||||||
stuff here */
|
line frag stuff here */
|
||||||
if (newParagraph)
|
if (newParagraph)
|
||||||
return 3;
|
return 3;
|
||||||
else
|
else
|
||||||
|
|
|
@ -1257,13 +1257,6 @@ it should still be safe. might lose opportunities to merge runs, though.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) setAttachmentSize: (NSSize)size
|
|
||||||
forGlyphRange: (NSRange)range
|
|
||||||
{
|
|
||||||
NSLog(@"%s not implemented yet", __PRETTY_FUNCTION__);
|
|
||||||
/* TODO!! */
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@ -1287,8 +1280,13 @@ it should still be safe. might lose opportunities to merge runs, though.
|
||||||
if (tc->linefrags)
|
if (tc->linefrags)
|
||||||
{
|
{
|
||||||
for (j = 0, lf = tc->linefrags; j < tc->num_linefrags; j++, lf++)
|
for (j = 0, lf = tc->linefrags; j < tc->num_linefrags; j++, lf++)
|
||||||
|
{
|
||||||
if (lf->points)
|
if (lf->points)
|
||||||
free(lf->points);
|
free(lf->points);
|
||||||
|
if (lf->attachments)
|
||||||
|
free(lf->attachments);
|
||||||
|
}
|
||||||
|
|
||||||
free(tc->linefrags);
|
free(tc->linefrags);
|
||||||
}
|
}
|
||||||
tc->linefrags = NULL;
|
tc->linefrags = NULL;
|
||||||
|
@ -1653,6 +1651,53 @@ forStartOfGlyphRange: (NSRange)glyphRange
|
||||||
layout_char = [self characterIndexForGlyphAtIndex: layout_glyph];
|
layout_char = [self characterIndexForGlyphAtIndex: layout_glyph];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-(void) setAttachmentSize: (NSSize)size
|
||||||
|
forGlyphRange: (NSRange)glyphRange
|
||||||
|
{
|
||||||
|
textcontainer_t *tc;
|
||||||
|
int i;
|
||||||
|
linefrag_t *lf;
|
||||||
|
linefrag_attachment_t *la;
|
||||||
|
|
||||||
|
SETUP_STUFF
|
||||||
|
|
||||||
|
for (i = 0, tc = textcontainers; i < num_textcontainers; i++, tc++)
|
||||||
|
{
|
||||||
|
if (tc->pos <= glyphRange.location &&
|
||||||
|
tc->pos + tc->length >= glyphRange.location + glyphRange.length)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == num_textcontainers)
|
||||||
|
{
|
||||||
|
NSLog(@"%s: text container not set for range", __PRETTY_FUNCTION__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0, lf = tc->linefrags; i < tc->num_linefrags; i++, lf++)
|
||||||
|
{
|
||||||
|
if (lf->pos <= glyphRange.location &&
|
||||||
|
lf->pos + lf->length >= glyphRange.location + glyphRange.length)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == tc->num_linefrags)
|
||||||
|
{
|
||||||
|
NSLog(@"%s: line fragment rect not set for range", __PRETTY_FUNCTION__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: we do no sanity checking of attachment size ranges. might want
|
||||||
|
to consider doing it */
|
||||||
|
lf->attachments = realloc(lf->attachments,
|
||||||
|
sizeof(linefrag_attachment_t) * (lf->num_attachments + 1));
|
||||||
|
la = &lf->attachments[lf->num_attachments++];
|
||||||
|
|
||||||
|
memset(la, 0, sizeof(linefrag_attachment_t));
|
||||||
|
la->pos = glyphRange.location;
|
||||||
|
la->length = glyphRange.length;
|
||||||
|
la->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
#undef SETUP_STUFF
|
#undef SETUP_STUFF
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -697,6 +697,9 @@ container */
|
||||||
linefrag_t *lf;
|
linefrag_t *lf;
|
||||||
linefrag_point_t *lp;
|
linefrag_point_t *lp;
|
||||||
|
|
||||||
|
linefrag_attachment_t *la;
|
||||||
|
int la_i;
|
||||||
|
|
||||||
NSPoint p;
|
NSPoint p;
|
||||||
unsigned int g;
|
unsigned int g;
|
||||||
|
|
||||||
|
@ -715,6 +718,8 @@ container */
|
||||||
int gbuf_len;
|
int gbuf_len;
|
||||||
NSPoint gbuf_point;
|
NSPoint gbuf_point;
|
||||||
|
|
||||||
|
NSView *controlView = nil;
|
||||||
|
|
||||||
|
|
||||||
if (!range.length)
|
if (!range.length)
|
||||||
return;
|
return;
|
||||||
|
@ -741,6 +746,9 @@ container */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
la = lf->attachments;
|
||||||
|
la_i = 0;
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
lp = lf->points;
|
lp = lf->points;
|
||||||
while (lp->pos + lp->length < range.location)
|
while (lp->pos + lp->length < range.location)
|
||||||
|
@ -784,6 +792,8 @@ container */
|
||||||
lf++;
|
lf++;
|
||||||
j = 0;
|
j = 0;
|
||||||
lp = lf->points;
|
lp = lf->points;
|
||||||
|
la = lf->attachments;
|
||||||
|
la_i = 0;
|
||||||
}
|
}
|
||||||
p = lp->p;
|
p = lp->p;
|
||||||
p.x += lf->rect.origin.x + containerOrigin.x;
|
p.x += lf->rect.origin.x + containerOrigin.x;
|
||||||
|
@ -827,6 +837,58 @@ container */
|
||||||
}
|
}
|
||||||
if (!glyph->isNotShown && glyph->g && glyph->g != NSControlGlyph)
|
if (!glyph->isNotShown && glyph->g && glyph->g != NSControlGlyph)
|
||||||
{
|
{
|
||||||
|
if (glyph->g == GSAttachmentGlyph)
|
||||||
|
{
|
||||||
|
/* Silently ignore if we don't have any size information for
|
||||||
|
it. */
|
||||||
|
if (g >= range.location && la)
|
||||||
|
{
|
||||||
|
unsigned int char_index =
|
||||||
|
[self characterRangeForGlyphRange: NSMakeRange(g,1)
|
||||||
|
actualGlyphRange: NULL].location;
|
||||||
|
NSObject<NSTextAttachmentCell> *cell = [[_textStorage attribute: NSAttachmentAttributeName
|
||||||
|
atIndex: char_index
|
||||||
|
effectiveRange: NULL] attachmentCell];
|
||||||
|
NSRect cellFrame;
|
||||||
|
|
||||||
|
if (!controlView)
|
||||||
|
controlView = [tc->textContainer textView];
|
||||||
|
|
||||||
|
while (la->pos != g && la_i < lf->num_attachments)
|
||||||
|
{
|
||||||
|
la++;
|
||||||
|
la_i++;
|
||||||
|
}
|
||||||
|
if (la_i >= lf->num_attachments)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cellFrame.origin = p;
|
||||||
|
cellFrame.size = la->size;
|
||||||
|
cellFrame.origin.y -= cellFrame.size.height;
|
||||||
|
|
||||||
|
/* Drawing the cell might mess up our state. */
|
||||||
|
/* TODO:
|
||||||
|
optimize this. probably cheaper to not save and
|
||||||
|
explicitly reset just the stuff we actually use, or to
|
||||||
|
collect attachments and draw them in bunches of eg. 4
|
||||||
|
|
||||||
|
should they really be drawn in our coordinate system?
|
||||||
|
*/
|
||||||
|
[cell drawWithFrame: cellFrame
|
||||||
|
inView: controlView
|
||||||
|
characterIndex: char_index
|
||||||
|
layoutManager: self];
|
||||||
|
[f set];
|
||||||
|
if (color)
|
||||||
|
[color set];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPSsetgray(ctxt, 0.0);
|
||||||
|
DPSsetalpha(ctxt, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (g >= range.location)
|
if (g >= range.location)
|
||||||
{
|
{
|
||||||
if (!gbuf_len)
|
if (!gbuf_len)
|
||||||
|
@ -860,6 +922,7 @@ for (i = 0; i < gbuf_len; i++) printf(" %3i : %04x\n", i, gbuf[i]); */
|
||||||
GSShowGlyphs(ctxt, gbuf, gbuf_len);
|
GSShowGlyphs(ctxt, gbuf, gbuf_len);
|
||||||
DPSnewpath(ctxt);
|
DPSnewpath(ctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef GBUF_SIZE
|
#undef GBUF_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,8 +75,7 @@
|
||||||
{
|
{
|
||||||
NSRect aRect;
|
NSRect aRect;
|
||||||
|
|
||||||
// FIXME: We ignore the proposedLineFragment
|
aRect.origin = [self cellBaselineOffset];
|
||||||
aRect.origin = position;
|
|
||||||
aRect.size = [self cellSize];
|
aRect.size = [self cellSize];
|
||||||
return aRect;
|
return aRect;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue