On Sunday 16 October 2005 12:12 pm, Ethan A Merritt wrote:
>
> today's patchset adds generic clipping of arrows,
> fixing bug #1187336 and a bunch of others.
Clipping arrow to the visible screen is messy because
the component lines and fill areas must be individually
clipped. This is particularly nasty if the start/end
coordinates have been forced to (unsigned int), because
negative coordinates are masquerading as large positive
numbers.
Clipping the vector itself before calling term->arrow()
may not be sufficient, because the head flag needs to be
adjusted so that a head is not draw on an end that was
clipped. (Or so it seems to me; perhaps there are cases
where one wants to draw the head anyway).
Until very recently, arrows were basically not clipped.
This caused problems on many terminals.
Current state of the code in cvs, as recently modified:
- full clipping is done in do_arrow(), which is a generic
routine called by most terminals. Because this is a
terminal entry point, the not-yet-clipped coordinates have
already been forced to (unsigned int). Casting them back
to (int) works, but is an ugly hack.
- The clipping in do_arrow() does not help terminals which
have a private term->arrow() routine (e.g. metapost, TeX
variants).
- Terminals which want to do clipping themselves (e.g. post)
set a flag TERM_CAN_CLIP, in which case the generic code
does not, in fact, clip the arrow. I think that's OK, but
I mention it for completeness.
I suggest that the clipping code below become a new routine
draw_clip_arrow(), analogous to draw_clip_line(), and all
places which currently call (term->arrow)() directly be
changed to call this intermediate layer routine instead.
This has the advantage that it will apply equally to all
terminals, can operate on coordinates before they have
been stuffed into an (unsigned int), and benefits from the
fact that draw_clip_line() and clip_point() can now be set
to clip against any desired bounding box.
This would replace the clipping code in do_arrow() and
possibly code in some individual terminal drivers.
The call site could specify a bounding box to clip
against if the default is not appropriate:
BoundingBox *clip_save = clip_area;
clip_area = &(BoundingBox *){ 0, xmax, 0, ymax };
draw_clip_arrow(...)
clip_area = clip_save;
draw_clip_arrow( int sx, int sy, int ex, int ey, int head)
{
/* Don't draw head if the arrow itself is clipped */
if (head == BOTH_HEADS && clip_point(sx,sy))
head = END_HEAD;
if (head == BOTH_HEADS && clip_point(ex,ey))
head = BACKHEAD;
if (head == BACKHEAD && clip_point(sx,sy))
head = NOHEAD;
if (head == END_HEAD && clip_point(ex,ey))
head = NOHEAD;
clip_line(&sx, &sy, &ex, &ey);
/* Call terminal routine to draw the clipped arrow */
(term->arrow)((unsigned int)sx, (unsigned int)sy,
(unsigned int)ex, (unsigned int)ey, head);
}
--
Ethan A Merritt merritt@...
Biomolecular Structure Center
Mailstop 357742
University of Washington, Seattle, WA 98195
|